update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / psi / impl / source / parsing / StatementParsing.java
blob89c35b07456f1a4f2061ab0a51e2d8d46a41096a
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.psi.impl.source.parsing;
18 import com.intellij.codeInsight.daemon.JavaErrorMessages;
19 import com.intellij.lang.ASTFactory;
20 import com.intellij.lexer.*;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.psi.JavaTokenType;
23 import com.intellij.psi.PsiManager;
24 import com.intellij.psi.TokenType;
25 import com.intellij.psi.impl.source.DummyHolderFactory;
26 import com.intellij.psi.impl.source.tree.*;
27 import com.intellij.psi.jsp.AbstractJspJavaLexer;
28 import com.intellij.psi.tree.IElementType;
29 import com.intellij.psi.tree.ILazyParseableElementType;
30 import com.intellij.util.SmartList;
31 import org.jetbrains.annotations.Nullable;
33 import java.util.ArrayList;
34 import java.util.List;
36 public class StatementParsing extends Parsing {
37 private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.StatementParsing");
39 public interface StatementParser {
40 @Nullable
41 CompositeElement parseStatement(Lexer lexer);
44 public interface StatementParsingHandler {
45 @Nullable StatementParser getParserForToken(IElementType token);
48 private List<StatementParsingHandler> myCustomHandlers = null;
50 public StatementParsing(JavaParsingContext context) {
51 super(context);
54 public void registerCustomStatementParser(StatementParsingHandler handler) {
55 if (myCustomHandlers == null) {
56 myCustomHandlers = new ArrayList<StatementParsingHandler>();
59 myCustomHandlers.add(handler);
62 public CompositeElement parseCodeBlockText(PsiManager manager, CharSequence buffer) {
63 return parseCodeBlockText(manager, null, buffer, 0, buffer.length(), -1);
66 public CompositeElement parseCodeBlockText(PsiManager manager,
67 Lexer lexer,
68 CharSequence buffer,
69 int startOffset,
70 int endOffset,
71 int state) {
72 if (lexer == null){
73 lexer = new JavaLexer(myContext.getLanguageLevel());
75 final FilterLexer filterLexer = new FilterLexer(lexer, new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET));
76 if (state < 0) filterLexer.start(buffer, startOffset, endOffset);
77 else filterLexer.start(buffer, startOffset, endOffset, state);
79 final FileElement dummyRoot = DummyHolderFactory.createHolder(manager, null, myContext.getCharTable()).getTreeElement();
80 CompositeElement block = ASTFactory.lazy(JavaElementType.CODE_BLOCK, null);
81 dummyRoot.rawAddChildren(block);
82 parseCodeBlockDeep(block, filterLexer, true);
83 if (block.getFirstChildNode() == null) return null;
85 ParseUtil.insertMissingTokens(block, lexer, startOffset, endOffset, state, WhiteSpaceAndCommentsProcessor.INSTANCE, myContext);
86 return block;
89 public TreeElement parseStatements(PsiManager manager,
90 Lexer lexer,
91 CharSequence buffer,
92 int startOffset,
93 int endOffset,
94 int state) {
95 if (lexer == null){
96 lexer = new JavaLexer(myContext.getLanguageLevel());
98 final FilterLexer filterLexer = new FilterLexer(lexer, new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET));
99 if (state < 0) filterLexer.start(buffer, startOffset, endOffset);
100 else filterLexer.start(buffer, startOffset, endOffset, state);
102 final FileElement dummyRoot = DummyHolderFactory.createHolder(manager, null, myContext.getCharTable()).getTreeElement();
103 parseStatements(dummyRoot, filterLexer, RBRACE_IS_ERROR);
105 ParseUtil.insertMissingTokens(dummyRoot,
106 lexer,
107 startOffset,
108 endOffset,
109 state,
110 WhiteSpaceAndCommentsProcessor.INSTANCE, myContext);
111 return dummyRoot.getFirstChildNode();
114 public TreeElement parseCodeBlock(Lexer lexer, boolean deep) {
115 if (lexer.getTokenType() != JavaTokenType.LBRACE) return null;
116 Lexer badLexer = lexer instanceof StoppableLexerAdapter ? ((StoppableLexerAdapter)lexer).getDelegate() : lexer;
117 if (badLexer instanceof FilterLexer){
118 final Lexer original = ((FilterLexer)badLexer).getOriginal();
119 if (original instanceof AbstractJspJavaLexer){
120 deep = true; // deep parsing of code blocks in JSP would lead to incorrect parsing on transforming
124 if (!deep){
125 int start = lexer.getTokenStart();
126 lexer.advance();
127 int braceCount = 1;
128 int end;
129 while(true){
130 IElementType tokenType = lexer.getTokenType();
131 if (tokenType == null){
132 end = lexer.getTokenStart();
133 break;
135 if (tokenType == JavaTokenType.LBRACE){
136 braceCount++;
138 else if (tokenType == JavaTokenType.RBRACE){
139 braceCount--;
141 if (braceCount == 0){
142 end = lexer.getTokenEnd();
143 lexer.advance();
144 break;
147 if (braceCount == 1 && (tokenType == JavaTokenType.SEMICOLON || tokenType == JavaTokenType.RBRACE)) {
148 lexer.advance();
150 final LexerPosition position = lexer.getCurrentPosition();
151 List<IElementType> list = new SmartList<IElementType>();
152 while (true) {
153 final IElementType type = lexer.getTokenType();
154 if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(type) || type == JavaTokenType.IDENTIFIER || ElementType.MODIFIER_BIT_SET.contains(type) ||
155 type == JavaTokenType.LT || type == JavaTokenType.GT || type == JavaTokenType.GTGT || type == JavaTokenType.GTGTGT || type ==
156 JavaTokenType.COMMA || type ==
157 JavaTokenType.DOT ||
158 type == JavaTokenType.EXTENDS_KEYWORD || type == JavaTokenType.IMPLEMENTS_KEYWORD) {
159 list.add(type);
160 lexer.advance();
161 } else {
162 break;
165 if (lexer.getTokenType() == JavaTokenType.LPARENTH && list.size() >= 2) {
166 final IElementType last = list.get(list.size() - 1);
167 final IElementType prevLast = list.get(list.size() - 2);
168 if (last == JavaTokenType.IDENTIFIER && (prevLast == JavaTokenType.IDENTIFIER || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(prevLast))) {
169 lexer.restore(position);
170 end = lexer.getTokenStart();
171 break;
175 else {
176 lexer.advance();
179 final TreeElement chameleon = ASTFactory.lazy(JavaElementType.CODE_BLOCK, myContext.getCharTable().intern(lexer.getBufferSequence(), start, end));
180 if (braceCount != 0){
181 chameleon.putUserData(TreeUtil.UNCLOSED_ELEMENT_PROPERTY, "");
183 return chameleon;
185 else{
186 CompositeElement codeBlock = ASTFactory.lazy(JavaElementType.CODE_BLOCK, null);
187 parseCodeBlockDeep(codeBlock, lexer, false);
188 return codeBlock;
192 private void parseCodeBlockDeep(CompositeElement elementToAdd,
193 Lexer lexer,
194 boolean parseToEndOfLexer) {
195 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.LBRACE, lexer.getTokenType());
197 elementToAdd.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
198 lexer.advance();
200 parseStatements(elementToAdd, lexer, parseToEndOfLexer ? LAST_RBRACE_IS_END : RBRACE_IS_END);
202 final TreeElement lastChild = elementToAdd.getLastChildNode();
203 if (lastChild == null || lastChild.getElementType() != JavaTokenType.RBRACE){
204 CompositeElement errorElement = Factory.createErrorElement(JavaErrorMessages.message("expected.rbrace"));
205 elementToAdd.rawAddChildren(errorElement);
206 elementToAdd.putUserData(TreeUtil.UNCLOSED_ELEMENT_PROPERTY, "");
210 private static final int RBRACE_IS_ERROR = 1;
211 private static final int RBRACE_IS_END = 2;
212 private static final int LAST_RBRACE_IS_END = 3;
214 private void parseStatements(CompositeElement elementToAdd, Lexer lexer, int rbraceMode){
215 while(lexer.getTokenType() != null){
216 TreeElement statement = parseStatement(lexer);
217 if (statement != null){
218 elementToAdd.rawAddChildren(statement);
219 continue;
222 IElementType tokenType = lexer.getTokenType();
223 TreeElement tokenElement = ParseUtil.createTokenElement(lexer, myContext.getCharTable());
224 lexer.advance();
226 if (tokenType == JavaTokenType.RBRACE){
227 Label:
228 if (rbraceMode == RBRACE_IS_ERROR) {
230 else if (rbraceMode == RBRACE_IS_END) {
231 elementToAdd.rawAddChildren(tokenElement);
232 return;
234 else if (rbraceMode == LAST_RBRACE_IS_END) {
235 if (lexer.getTokenType() == null) {
236 elementToAdd.rawAddChildren(tokenElement);
237 return;
239 else {
240 break Label;
243 else {
244 LOG.assertTrue(false);
248 String error;
249 if (tokenType == JavaTokenType.ELSE_KEYWORD){
250 error = JavaErrorMessages.message("else.without.if");
252 else if (tokenType == JavaTokenType.CATCH_KEYWORD){
253 error = JavaErrorMessages.message("catch.without.try");
255 else if (tokenType == JavaTokenType.FINAL_KEYWORD){
256 error = JavaErrorMessages.message("finally.without.try");
258 else{
259 error = JavaErrorMessages.message("unexpected.token");
261 CompositeElement errorElement = Factory.createErrorElement(error);
262 errorElement.rawAddChildren(tokenElement);
263 elementToAdd.rawAddChildren(errorElement);
267 @Nullable
268 public TreeElement parseStatementText(CharSequence buffer) {
269 Lexer lexer = new JavaLexer(myContext.getLanguageLevel());
270 final FilterLexer filterLexer = new FilterLexer(lexer, new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET));
271 filterLexer.start(buffer);
273 TreeElement statement = parseStatement(filterLexer);
274 if (statement == null) return null;
275 if (filterLexer.getTokenType() != null) return null;
277 if(statement instanceof CompositeElement)
278 ParseUtil.insertMissingTokens((CompositeElement)statement, lexer, 0, buffer.length(), -1, WhiteSpaceAndCommentsProcessor.INSTANCE, myContext);
279 return statement;
282 @Nullable
283 public TreeElement parseStatement(Lexer lexer) {
284 IElementType tokenType = lexer.getTokenType();
285 if (myCustomHandlers != null) {
286 for (StatementParsingHandler handler : myCustomHandlers) {
287 final StatementParser parser = handler.getParserForToken(tokenType);
288 if (parser != null) {
289 return parser.parseStatement(lexer);
294 if (tokenType == JavaTokenType.IF_KEYWORD) {
295 return parseIfStatement(lexer);
297 if (tokenType == JavaTokenType.WHILE_KEYWORD) {
298 return parseWhileStatement(lexer);
300 if (tokenType == JavaTokenType.FOR_KEYWORD) {
301 return parseForStatement(lexer);
303 if (tokenType == JavaTokenType.DO_KEYWORD) {
304 return parseDoWhileStatement(lexer);
306 if (tokenType == JavaTokenType.SWITCH_KEYWORD) {
307 return parseSwitchStatement(lexer);
309 if (tokenType == JavaTokenType.CASE_KEYWORD || tokenType == JavaTokenType.DEFAULT_KEYWORD) {
310 return parseSwitchLabelStatement(lexer);
312 if (tokenType == JavaTokenType.BREAK_KEYWORD) {
313 return parseBreakStatement(lexer);
315 if (tokenType == JavaTokenType.CONTINUE_KEYWORD) {
316 return parseContinueStatement(lexer);
318 if (tokenType == JavaTokenType.RETURN_KEYWORD) {
319 return parseReturnStatement(lexer);
321 if (tokenType == JavaTokenType.THROW_KEYWORD) {
322 return parseThrowStatement(lexer);
324 if (tokenType == JavaTokenType.SYNCHRONIZED_KEYWORD) {
325 return parseSynchronizedStatement(lexer);
327 if (tokenType == JavaTokenType.TRY_KEYWORD) {
328 return parseTryStatement(lexer);
330 if (tokenType == JavaTokenType.ASSERT_KEYWORD) {
331 return parseAssertStatement(lexer);
333 if (tokenType == JavaTokenType.LBRACE) {
334 return parseBlockStatement(lexer);
336 if (tokenType instanceof ILazyParseableElementType) {
337 TreeElement declaration = ASTFactory.lazy((ILazyParseableElementType)tokenType, myContext.tokenText(lexer));
338 lexer.advance();
339 return declaration;
341 if (tokenType == JavaTokenType.SEMICOLON) {
342 CompositeElement element = ASTFactory.composite(JavaElementType.EMPTY_STATEMENT);
343 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
344 lexer.advance();
345 return element;
347 if (tokenType == JavaTokenType.IDENTIFIER || tokenType == JavaTokenType.AT) {
348 final LexerPosition refPos = lexer.getCurrentPosition();
349 parseAnnotationListTo(lexer, null); // @Ann ClassName.field++;
350 skipQualifiedName(lexer);
351 final IElementType suspectedLT = lexer.getTokenType();
352 lexer.restore(refPos);
353 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.IDENTIFIER || lexer.getTokenType() == JavaTokenType.AT);
354 if (suspectedLT == JavaTokenType.LT) {
355 final TreeElement decl = myContext.getDeclarationParsing().parseDeclaration(lexer, DeclarationParsing.Context.CODE_BLOCK_CONTEXT);
356 CompositeElement declStatement = ASTFactory.composite(JavaElementType.DECLARATION_STATEMENT);
357 if (decl != null) {
358 declStatement.rawAddChildren(decl);
360 else {
361 final CompositeElement type = parseType(lexer, false, false);
362 if (type != null) declStatement.rawAddChildren(type);
363 final CompositeElement errorElement = Factory.createErrorElement(JavaErrorMessages.message("expected.identifier"));
364 declStatement.rawAddChildren(errorElement);
366 return declStatement;
370 final LexerPosition pos = lexer.getCurrentPosition();
371 CompositeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
372 final LexerPosition pos1 = lexer.getCurrentPosition();
373 if (expr != null) {
374 int count = 1;
375 CompositeElement element = null;
376 while (lexer.getTokenType() == JavaTokenType.COMMA) {
377 CompositeElement list = ASTFactory.composite(JavaElementType.EXPRESSION_LIST);
378 element = ASTFactory.composite(JavaElementType.EXPRESSION_LIST_STATEMENT);
379 element.rawAddChildren(list);
380 list.rawAddChildren(expr);
381 final LexerPosition commaPos = lexer.getCurrentPosition();
382 TreeElement comma = ParseUtil.createTokenElement(lexer, myContext.getCharTable());
383 lexer.advance();
384 CompositeElement expr1 = myContext.getExpressionParsing().parseExpression(lexer);
385 if (expr1 == null) {
386 lexer.restore(commaPos);
387 break;
389 list.rawAddChildren(comma);
390 list.rawAddChildren(expr1);
391 count++;
393 if (count > 1) {
394 processClosingSemicolon(element, lexer);
395 return element;
397 if (expr.getElementType() != JavaElementType.REFERENCE_EXPRESSION) {
398 element = ASTFactory.composite(JavaElementType.EXPRESSION_STATEMENT);
399 element.rawAddChildren(expr);
400 processClosingSemicolon(element, lexer);
401 return element;
403 lexer.restore(pos);
406 TreeElement decl = myContext.getDeclarationParsing().parseDeclaration(lexer, DeclarationParsing.Context.CODE_BLOCK_CONTEXT);
407 if (decl != null) {
408 CompositeElement declStatement = ASTFactory.composite(JavaElementType.DECLARATION_STATEMENT);
409 declStatement.rawAddChildren(decl);
410 return declStatement;
413 if (lexer.getTokenType() == JavaTokenType.IDENTIFIER) {
414 TreeElement identifier = ParseUtil.createTokenElement(lexer, myContext.getCharTable());
415 lexer.advance();
416 if (lexer.getTokenType() == JavaTokenType.COLON) {
417 CompositeElement element = ASTFactory.composite(JavaElementType.LABELED_STATEMENT);
418 element.rawAddChildren(identifier);
419 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
420 lexer.advance();
421 TreeElement statement = parseStatement(lexer);
422 if (statement != null) {
423 element.rawAddChildren(statement);
425 return element;
427 lexer.restore(pos);
430 if (expr != null) {
431 lexer.restore(pos1);
432 CompositeElement element = ASTFactory.composite(JavaElementType.EXPRESSION_STATEMENT);
433 element.rawAddChildren(expr);
434 processClosingSemicolon(element, lexer);
435 return element;
438 return null;
441 private static void skipQualifiedName(Lexer lexer) {
442 if (lexer.getTokenType() != JavaTokenType.IDENTIFIER) return;
443 while(true){
444 lexer.advance();
445 if (lexer.getTokenType() != JavaTokenType.DOT) return;
446 final LexerPosition position = lexer.getCurrentPosition();
447 lexer.advance();
448 if (lexer.getTokenType() != JavaTokenType.IDENTIFIER){
449 lexer.restore(position);
450 return;
455 private CompositeElement parseIfStatement(Lexer lexer) {
456 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.IF_KEYWORD);
457 CompositeElement element = ASTFactory.composite(JavaElementType.IF_STATEMENT);
458 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
459 lexer.advance();
461 if (!processExpressionInParens(lexer, element)){
462 return element;
465 TreeElement thenStatement = parseStatement(lexer);
466 if (thenStatement == null){
467 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.statement")));
468 return element;
471 element.rawAddChildren(thenStatement);
473 if (lexer.getTokenType() != JavaTokenType.ELSE_KEYWORD){
474 return element;
477 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
478 lexer.advance();
479 TreeElement elseStatement = parseStatement(lexer);
480 if (elseStatement == null){
481 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.statement")));
482 return element;
484 element.rawAddChildren(elseStatement);
485 return element;
488 private CompositeElement parseWhileStatement(Lexer lexer) {
489 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.WHILE_KEYWORD);
490 CompositeElement element = ASTFactory.composite(JavaElementType.WHILE_STATEMENT);
491 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
492 lexer.advance();
494 if (!processExpressionInParens(lexer, element)){
495 return element;
498 TreeElement statement = parseStatement(lexer);
499 if (statement == null){
500 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.statement")));
501 return element;
504 element.rawAddChildren(statement);
505 return element;
508 private CompositeElement parseForStatement(Lexer lexer) {
509 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.FOR_KEYWORD);
510 final TreeElement forKeyword = ParseUtil.createTokenElement(lexer, myContext.getCharTable());
511 lexer.advance();
513 if (lexer.getTokenType() != JavaTokenType.LPARENTH){
514 CompositeElement errorForElement = ASTFactory.composite(JavaElementType.FOR_STATEMENT);
515 errorForElement.rawAddChildren(forKeyword);
516 errorForElement.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lparen")));
517 return errorForElement;
520 final TreeElement lparenth = ParseUtil.createTokenElement(lexer, myContext.getCharTable());
521 lexer.advance();
523 final LexerPosition afterLParenth = lexer.getCurrentPosition();
524 final TreeElement parameter = myContext.getDeclarationParsing().parseParameter(lexer, false);
525 if (parameter == null || parameter.getElementType() != JavaElementType.PARAMETER || lexer.getTokenType() != JavaTokenType.COLON) {
526 lexer.restore(afterLParenth);
527 return parseForLoopFromInitialization(forKeyword, lparenth, lexer);
529 else {
530 return parseForEachFromColon(forKeyword, lparenth, parameter, lexer);
534 private CompositeElement parseForEachFromColon(TreeElement forKeyword,
535 TreeElement lparenth,
536 TreeElement parameter,
537 Lexer lexer) {
538 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.COLON);
539 final CompositeElement element = ASTFactory.composite(JavaElementType.FOREACH_STATEMENT);
540 element.rawAddChildren(forKeyword);
541 element.rawAddChildren(lparenth);
542 element.rawAddChildren(parameter);
543 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
544 lexer.advance();
545 final CompositeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
546 if (expr != null) {
547 element.rawAddChildren(expr);
549 else {
550 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.expression")));
552 if (lexer.getTokenType() == JavaTokenType.RPARENTH) {
553 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
554 lexer.advance();
555 final TreeElement body = parseStatement(lexer);
556 if (body != null) {
557 element.rawAddChildren(body);
558 } else {
559 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.statement")));
562 else {
563 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.rparen")));
565 return element;
568 private CompositeElement parseForLoopFromInitialization(final TreeElement forKeyword,
569 final TreeElement lparenth,
570 Lexer lexer) {// parsing normal for statement for statement
571 CompositeElement element = ASTFactory.composite(JavaElementType.FOR_STATEMENT);
572 element.rawAddChildren(forKeyword);
573 element.rawAddChildren(lparenth);
574 TreeElement init = parseStatement(lexer);
575 if (init == null){
576 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.statement")));
577 if (lexer.getTokenType() != JavaTokenType.RPARENTH){
578 return element;
581 else{
582 element.rawAddChildren(init);
584 CompositeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
585 if (expr != null){
586 element.rawAddChildren(expr);
589 if (lexer.getTokenType() != JavaTokenType.SEMICOLON){
590 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.semicolon")));
591 if (lexer.getTokenType() != JavaTokenType.RPARENTH){
592 return element;
595 else{
596 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
597 lexer.advance();
598 parseExpressionOrExpressionList(lexer, element);
599 if (lexer.getTokenType() != JavaTokenType.RPARENTH){
600 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.rparen")));
601 return element;
606 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
607 lexer.advance();
609 TreeElement statement = parseStatement(lexer);
610 if (statement == null){
611 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.statement")));
612 return element;
615 element.rawAddChildren(statement);
617 return element;
620 private void parseExpressionOrExpressionList(Lexer lexer, CompositeElement element) {
621 CompositeElement expression = myContext.getExpressionParsing().parseExpression(lexer);
622 if (expression != null) {
623 final CompositeElement expressionStatement;
624 if (lexer.getTokenType() != JavaTokenType.COMMA) {
625 expressionStatement = ASTFactory.composite(JavaElementType.EXPRESSION_STATEMENT);
626 expressionStatement.rawAddChildren(expression);
627 } else {
628 expressionStatement = ASTFactory.composite(JavaElementType.EXPRESSION_LIST_STATEMENT);
629 final CompositeElement expressionList = ASTFactory.composite(JavaElementType.EXPRESSION_LIST);
630 expressionList.rawAddChildren(expression);
631 do {
632 expressionList.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
633 lexer.advance();
634 final CompositeElement nextExpression = myContext.getExpressionParsing().parseExpression(lexer);
635 if (nextExpression != null) {
636 expressionList.rawAddChildren(nextExpression);
637 } else {
638 expressionList.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.expression")));
640 } while (lexer.getTokenType() == JavaTokenType.COMMA);
641 expressionStatement.rawAddChildren(expressionList);
643 element.rawAddChildren(expressionStatement);
647 private CompositeElement parseDoWhileStatement(Lexer lexer) {
648 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.DO_KEYWORD);
649 CompositeElement element = ASTFactory.composite(JavaElementType.DO_WHILE_STATEMENT);
650 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
651 lexer.advance();
653 TreeElement statement = parseStatement(lexer);
654 if (statement == null){
655 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.statement")));
656 return element;
659 element.rawAddChildren(statement);
661 if (lexer.getTokenType() != JavaTokenType.WHILE_KEYWORD){
662 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.while")));
663 return element;
666 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
667 lexer.advance();
669 if (!processExpressionInParens(lexer, element)){
670 return element;
673 processClosingSemicolon(element, lexer);
675 return element;
678 private CompositeElement parseSwitchStatement(Lexer lexer) {
679 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.SWITCH_KEYWORD);
680 CompositeElement element = ASTFactory.composite(JavaElementType.SWITCH_STATEMENT);
681 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
682 lexer.advance();
684 if (!processExpressionInParens(lexer, element)){
685 return element;
688 TreeElement codeBlock = parseCodeBlock(lexer, DEEP_PARSE_BLOCKS_IN_STATEMENTS);
689 if (codeBlock == null){
690 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lbrace")));
691 return element;
694 element.rawAddChildren(codeBlock);
695 return element;
698 @Nullable
699 private CompositeElement parseSwitchLabelStatement(Lexer lexer) {
700 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.CASE_KEYWORD || lexer.getTokenType() == JavaTokenType.DEFAULT_KEYWORD);
701 IElementType tokenType = lexer.getTokenType();
702 final LexerPosition pos = lexer.getCurrentPosition();
703 CompositeElement element = ASTFactory.composite(JavaElementType.SWITCH_LABEL_STATEMENT);
704 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
705 lexer.advance();
706 if (tokenType == JavaTokenType.CASE_KEYWORD){
707 TreeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
708 if (expr == null){
709 lexer.restore(pos);
710 return null;
712 element.rawAddChildren(expr);
714 if (lexer.getTokenType() == JavaTokenType.COLON){
715 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
716 lexer.advance();
718 else{
719 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.colon")));
721 return element;
724 private CompositeElement parseBreakStatement(Lexer lexer) {
725 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.BREAK_KEYWORD);
726 CompositeElement element = ASTFactory.composite(JavaElementType.BREAK_STATEMENT);
727 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
728 lexer.advance();
730 if (lexer.getTokenType() == JavaTokenType.IDENTIFIER){
731 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
732 lexer.advance();
735 processClosingSemicolon(element, lexer);
736 return element;
739 private CompositeElement parseContinueStatement(Lexer lexer) {
740 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.CONTINUE_KEYWORD);
741 CompositeElement element = ASTFactory.composite(JavaElementType.CONTINUE_STATEMENT);
742 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
743 lexer.advance();
745 if (lexer.getTokenType() == JavaTokenType.IDENTIFIER){
746 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
747 lexer.advance();
750 processClosingSemicolon(element, lexer);
751 return element;
754 private CompositeElement parseReturnStatement(Lexer lexer) {
755 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.RETURN_KEYWORD);
756 CompositeElement element = ASTFactory.composite(JavaElementType.RETURN_STATEMENT);
757 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
758 lexer.advance();
760 TreeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
761 if (expr != null){
762 element.rawAddChildren(expr);
765 processClosingSemicolon(element, lexer);
766 return element;
769 private CompositeElement parseThrowStatement(Lexer lexer) {
770 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.THROW_KEYWORD);
772 CompositeElement element = ASTFactory.composite(JavaElementType.THROW_STATEMENT);
773 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
774 lexer.advance();
776 TreeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
777 if (expr != null){
778 element.rawAddChildren(expr);
780 else{
781 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.expression")));
782 return element;
785 processClosingSemicolon(element, lexer);
786 return element;
789 private CompositeElement parseSynchronizedStatement(Lexer lexer) {
790 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.SYNCHRONIZED_KEYWORD);
791 CompositeElement element = ASTFactory.composite(JavaElementType.SYNCHRONIZED_STATEMENT);
792 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
793 lexer.advance();
795 if (!processExpressionInParens(lexer, element)){
796 return element;
799 TreeElement codeBlock = parseCodeBlock(lexer, DEEP_PARSE_BLOCKS_IN_STATEMENTS);
800 if (codeBlock == null){
801 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lbrace")));
802 return element;
805 element.rawAddChildren(codeBlock);
806 return element;
809 private CompositeElement parseTryStatement(Lexer lexer) {
810 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.TRY_KEYWORD);
812 //int pos = ParseUtil.savePosition(lexer);
813 CompositeElement element = ASTFactory.composite(JavaElementType.TRY_STATEMENT);
814 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
815 lexer.advance();
817 TreeElement codeBlock = parseCodeBlock(lexer, DEEP_PARSE_BLOCKS_IN_STATEMENTS);
818 if (codeBlock == null){
819 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lbrace")));
820 return element;
822 element.rawAddChildren(codeBlock);
824 if (lexer.getTokenType() != JavaTokenType.CATCH_KEYWORD && lexer.getTokenType() != JavaTokenType.FINALLY_KEYWORD){
825 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.catch.or.finally")));
826 return element;
829 while(lexer.getTokenType() == JavaTokenType.CATCH_KEYWORD){
830 CompositeElement catchSection = parseCatchSection(lexer);
831 element.rawAddChildren(catchSection);
832 final TreeElement lastChild = catchSection.getLastChildNode();
833 assert lastChild != null;
834 if (lastChild.getElementType() == TokenType.ERROR_ELEMENT) break;
837 if (lexer.getTokenType() == JavaTokenType.FINALLY_KEYWORD){
838 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
839 lexer.advance();
841 codeBlock = parseCodeBlock(lexer, DEEP_PARSE_BLOCKS_IN_STATEMENTS);
842 if (codeBlock == null){
843 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lbrace")));
844 return element;
846 element.rawAddChildren(codeBlock);
849 return element;
852 private CompositeElement parseCatchSection(Lexer lexer) {
853 CompositeElement catchSection = ASTFactory.composite(JavaElementType.CATCH_SECTION);
854 catchSection.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
855 lexer.advance();
857 if (lexer.getTokenType() != JavaTokenType.LPARENTH) {
858 catchSection.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lparen")));
859 return catchSection;
862 catchSection.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
863 lexer.advance();
865 TreeElement parm = myContext.getDeclarationParsing().parseParameter(lexer, false);
866 if (parm == null) {
867 catchSection.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.parameter")));
868 } else {
869 catchSection.rawAddChildren(parm);
872 if (lexer.getTokenType() != JavaTokenType.RPARENTH) {
873 catchSection.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.rparen")));
874 return catchSection;
877 catchSection.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
878 lexer.advance();
880 TreeElement codeBlock = parseCodeBlock(lexer, DEEP_PARSE_BLOCKS_IN_STATEMENTS);
881 if (codeBlock == null) {
882 catchSection.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lbrace")));
883 return catchSection;
885 catchSection.rawAddChildren(codeBlock);
886 return catchSection;
889 private CompositeElement parseAssertStatement(Lexer lexer) {
890 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.ASSERT_KEYWORD);
892 CompositeElement element = ASTFactory.composite(JavaElementType.ASSERT_STATEMENT);
893 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
894 lexer.advance();
896 TreeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
897 if (expr == null){
898 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.boolean.expression")));
899 return element;
902 element.rawAddChildren(expr);
904 if (lexer.getTokenType() == JavaTokenType.COLON){
905 element.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
906 lexer.advance();
908 TreeElement expr2 = myContext.getExpressionParsing().parseExpression(lexer);
909 if (expr2 == null){
910 element.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.expression")));
911 return element;
914 element.rawAddChildren(expr2);
917 processClosingSemicolon(element, lexer);
918 return element;
921 private CompositeElement parseBlockStatement(Lexer lexer) {
922 LOG.assertTrue(lexer.getTokenType() == JavaTokenType.LBRACE);
923 CompositeElement element = ASTFactory.composite(JavaElementType.BLOCK_STATEMENT);
924 TreeElement codeBlock = parseCodeBlock(lexer, DEEP_PARSE_BLOCKS_IN_STATEMENTS);
925 element.rawAddChildren(codeBlock);
926 return element;
929 private boolean processExpressionInParens(Lexer lexer, CompositeElement parent) {
930 if (lexer.getTokenType() != JavaTokenType.LPARENTH){
931 parent.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.lparen")));
932 return false;
935 parent.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
936 lexer.advance();
938 final LexerPosition beforeExprPos = lexer.getCurrentPosition();
939 CompositeElement expr = myContext.getExpressionParsing().parseExpression(lexer);
940 if (expr == null || lexer.getTokenType() == JavaTokenType.SEMICOLON){
941 if (expr != null){
942 lexer.restore(beforeExprPos);
944 parent.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.expression")));
945 if (lexer.getTokenType() != JavaTokenType.RPARENTH){
946 return false;
949 else{
950 parent.rawAddChildren(expr);
952 if (lexer.getTokenType() != JavaTokenType.RPARENTH){
953 parent.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.rparen")));
954 return false;
958 // add ')'
959 parent.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
960 lexer.advance();
962 return true;
965 private void processClosingSemicolon(CompositeElement statement, Lexer lexer) {
966 if (lexer.getTokenType() == JavaTokenType.SEMICOLON){
967 statement.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
968 lexer.advance();
970 else{
971 statement.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.semicolon")));
975 @Nullable
976 public TreeElement parseCatchSectionText(CharSequence buffer) {
977 Lexer lexer = new JavaLexer(myContext.getLanguageLevel());
978 final FilterLexer filterLexer = new FilterLexer(lexer, new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET));
979 filterLexer.start(buffer);
981 CompositeElement catchSection = parseCatchSection(filterLexer);
982 if (catchSection == null) return null;
983 if (filterLexer.getTokenType() != null) return null;
985 ParseUtil.insertMissingTokens(catchSection, lexer, 0, buffer.length(), -1, WhiteSpaceAndCommentsProcessor.INSTANCE, myContext);
986 return catchSection;