2 * Copyright 2000-2016 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.lang.java.parser;
18 import com.intellij.codeInsight.daemon.JavaErrorMessages;
19 import com.intellij.lang.PsiBuilder;
20 import com.intellij.lang.WhitespacesBinders;
21 import com.intellij.psi.JavaTokenType;
22 import com.intellij.psi.TokenType;
23 import com.intellij.psi.impl.source.tree.ElementType;
24 import com.intellij.psi.impl.source.tree.JavaElementType;
25 import com.intellij.psi.tree.IElementType;
26 import com.intellij.psi.tree.TokenSet;
27 import com.intellij.util.Function;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
30 import org.jetbrains.annotations.PropertyKey;
32 import static com.intellij.codeInsight.daemon.JavaErrorMessages.BUNDLE;
33 import static com.intellij.lang.PsiBuilderUtil.*;
34 import static com.intellij.lang.java.parser.JavaParserUtil.*;
36 public class ExpressionParser {
37 private enum ExprType {
38 CONDITIONAL_OR, CONDITIONAL_AND, OR, XOR, AND, EQUALITY, RELATIONAL, SHIFT, ADDITIVE, MULTIPLICATIVE, UNARY, TYPE
41 private static final TokenSet ASSIGNMENT_OPS = TokenSet.create(
42 JavaTokenType.EQ, JavaTokenType.ASTERISKEQ, JavaTokenType.DIVEQ, JavaTokenType.PERCEQ, JavaTokenType.PLUSEQ, JavaTokenType.MINUSEQ,
43 JavaTokenType.LTLTEQ, JavaTokenType.GTGTEQ, JavaTokenType.GTGTGTEQ, JavaTokenType.ANDEQ, JavaTokenType.OREQ, JavaTokenType.XOREQ);
44 private static final TokenSet RELATIONAL_OPS = TokenSet.create(JavaTokenType.LT, JavaTokenType.GT, JavaTokenType.LE, JavaTokenType.GE);
45 private static final TokenSet POSTFIX_OPS = TokenSet.create(JavaTokenType.PLUSPLUS, JavaTokenType.MINUSMINUS);
46 private static final TokenSet PREF_ARITHMETIC_OPS = TokenSet.orSet(POSTFIX_OPS, TokenSet.create(JavaTokenType.PLUS, JavaTokenType.MINUS));
47 private static final TokenSet PREFIX_OPS = TokenSet.orSet(PREF_ARITHMETIC_OPS, TokenSet.create(JavaTokenType.TILDE, JavaTokenType.EXCL));
48 private static final TokenSet LITERALS = TokenSet.create(
49 JavaTokenType.TRUE_KEYWORD, JavaTokenType.FALSE_KEYWORD, JavaTokenType.NULL_KEYWORD, JavaTokenType.INTEGER_LITERAL,
50 JavaTokenType.LONG_LITERAL, JavaTokenType.FLOAT_LITERAL, JavaTokenType.DOUBLE_LITERAL, JavaTokenType.CHARACTER_LITERAL,
51 JavaTokenType.STRING_LITERAL);
52 private static final TokenSet CONDITIONAL_OR_OPS = TokenSet.create(JavaTokenType.OROR);
53 private static final TokenSet CONDITIONAL_AND_OPS = TokenSet.create(JavaTokenType.ANDAND);
54 private static final TokenSet OR_OPS = TokenSet.create(JavaTokenType.OR);
55 private static final TokenSet XOR_OPS = TokenSet.create(JavaTokenType.XOR);
56 private static final TokenSet AND_OPS = TokenSet.create(JavaTokenType.AND);
57 private static final TokenSet EQUALITY_OPS = TokenSet.create(JavaTokenType.EQEQ, JavaTokenType.NE);
58 private static final TokenSet SHIFT_OPS = TokenSet.create(JavaTokenType.LTLT, JavaTokenType.GTGT, JavaTokenType.GTGTGT);
59 private static final TokenSet ADDITIVE_OPS = TokenSet.create(JavaTokenType.PLUS, JavaTokenType.MINUS);
60 private static final TokenSet MULTIPLICATIVE_OPS = TokenSet.create(JavaTokenType.ASTERISK, JavaTokenType.DIV, JavaTokenType.PERC);
61 private static final TokenSet ARGS_LIST_END = TokenSet.create(JavaTokenType.RPARENTH, JavaTokenType.RBRACE, JavaTokenType.RBRACKET);
62 private static final TokenSet ARGS_LIST_CONTINUE = TokenSet.create(
63 JavaTokenType.IDENTIFIER, TokenType.BAD_CHARACTER, JavaTokenType.COMMA, JavaTokenType.INTEGER_LITERAL, JavaTokenType.STRING_LITERAL);
64 private static final TokenSet THIS_OR_SUPER = TokenSet.create(JavaTokenType.THIS_KEYWORD, JavaTokenType.SUPER_KEYWORD);
65 private static final TokenSet ID_OR_SUPER = TokenSet.create(JavaTokenType.IDENTIFIER, JavaTokenType.SUPER_KEYWORD);
66 private static final TokenSet TYPE_START = TokenSet.orSet(
67 ElementType.PRIMITIVE_TYPE_BIT_SET, TokenSet.create(JavaTokenType.IDENTIFIER, JavaTokenType.AT));
69 private final JavaParser myParser;
71 public ExpressionParser(@NotNull final JavaParser javaParser) {
72 myParser = javaParser;
76 public PsiBuilder.Marker parse(final PsiBuilder builder) {
77 return parseAssignment(builder);
81 private PsiBuilder.Marker parseAssignment(final PsiBuilder builder) {
82 final PsiBuilder.Marker left = parseConditional(builder);
83 if (left == null) return null;
85 final IElementType tokenType = getGtTokenType(builder);
86 if (ASSIGNMENT_OPS.contains(tokenType) && tokenType != null) {
87 final PsiBuilder.Marker assignment = left.precede();
88 advanceGtToken(builder, tokenType);
90 final PsiBuilder.Marker right = parse(builder);
92 error(builder, JavaErrorMessages.message("expected.expression"));
95 assignment.done(JavaElementType.ASSIGNMENT_EXPRESSION);
103 public PsiBuilder.Marker parseConditional(final PsiBuilder builder) {
104 final PsiBuilder.Marker condition = parseExpression(builder, ExprType.CONDITIONAL_OR);
105 if (condition == null) return null;
107 if (builder.getTokenType() != JavaTokenType.QUEST) return condition;
108 final PsiBuilder.Marker ternary = condition.precede();
109 builder.advanceLexer();
111 final PsiBuilder.Marker truePart = parse(builder);
112 if (truePart == null) {
113 error(builder, JavaErrorMessages.message("expected.expression"));
114 ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
118 if (builder.getTokenType() != JavaTokenType.COLON) {
119 error(builder, JavaErrorMessages.message("expected.colon"));
120 ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
123 builder.advanceLexer();
125 final PsiBuilder.Marker falsePart = parseConditional(builder);
126 if (falsePart == null) {
127 error(builder, JavaErrorMessages.message("expected.expression"));
128 ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
132 ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
137 private PsiBuilder.Marker parseExpression(final PsiBuilder builder, final ExprType type) {
140 return parseBinary(builder, ExprType.CONDITIONAL_AND, CONDITIONAL_OR_OPS);
142 case CONDITIONAL_AND:
143 return parseBinary(builder, ExprType.OR, CONDITIONAL_AND_OPS);
146 return parseBinary(builder, ExprType.XOR, OR_OPS);
149 return parseBinary(builder, ExprType.AND, XOR_OPS);
152 return parseBinary(builder, ExprType.EQUALITY, AND_OPS);
155 return parseBinary(builder, ExprType.RELATIONAL, EQUALITY_OPS);
158 return parseRelational(builder);
161 return parseBinary(builder, ExprType.ADDITIVE, SHIFT_OPS);
164 return parseBinary(builder, ExprType.MULTIPLICATIVE, ADDITIVE_OPS);
167 return parseBinary(builder, ExprType.UNARY, MULTIPLICATIVE_OPS);
170 return parseUnary(builder);
173 return myParser.getReferenceParser().parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
176 assert false : "Unexpected type: " + type;
182 private PsiBuilder.Marker parseBinary(final PsiBuilder builder, final ExprType type, final TokenSet ops) {
183 PsiBuilder.Marker result = parseExpression(builder, type);
184 if (result == null) return null;
185 int operandCount = 1;
187 IElementType tokenType = getGtTokenType(builder);
188 IElementType currentExprTokenType = tokenType;
190 if (tokenType == null || !ops.contains(tokenType)) break;
192 advanceGtToken(builder, tokenType);
194 final PsiBuilder.Marker right = parseExpression(builder, type);
196 tokenType = getGtTokenType(builder);
197 if (tokenType == null || !ops.contains(tokenType) || tokenType != currentExprTokenType || right == null) {
199 result = result.precede();
201 error(builder, JavaErrorMessages.message("expected.expression"));
203 result.done(operandCount > 2 ? JavaElementType.POLYADIC_EXPRESSION : JavaElementType.BINARY_EXPRESSION);
204 if (right == null) break;
205 currentExprTokenType = tokenType;
214 private PsiBuilder.Marker parseRelational(final PsiBuilder builder) {
215 PsiBuilder.Marker left = parseExpression(builder, ExprType.SHIFT);
216 if (left == null) return null;
218 IElementType tokenType;
219 while ((tokenType = getGtTokenType(builder)) != null) {
220 final IElementType toCreate;
221 final ExprType toParse;
222 if (RELATIONAL_OPS.contains(tokenType)) {
223 toCreate = JavaElementType.BINARY_EXPRESSION;
224 toParse = ExprType.SHIFT;
226 else if (tokenType == JavaTokenType.INSTANCEOF_KEYWORD) {
227 toCreate = JavaElementType.INSTANCE_OF_EXPRESSION;
228 toParse = ExprType.TYPE;
234 final PsiBuilder.Marker expression = left.precede();
235 advanceGtToken(builder, tokenType);
237 final PsiBuilder.Marker right = parseExpression(builder, toParse);
239 error(builder, JavaErrorMessages.message(toParse == ExprType.TYPE ? "expected.type" : "expected.expression"));
240 expression.done(toCreate);
244 expression.done(toCreate);
252 private PsiBuilder.Marker parseUnary(final PsiBuilder builder) {
253 final IElementType tokenType = builder.getTokenType();
255 if (PREFIX_OPS.contains(tokenType)) {
256 final PsiBuilder.Marker unary = builder.mark();
257 builder.advanceLexer();
259 final PsiBuilder.Marker operand = parseUnary(builder);
260 if (operand == null) {
261 error(builder, JavaErrorMessages.message("expected.expression"));
264 unary.done(JavaElementType.PREFIX_EXPRESSION);
267 else if (tokenType == JavaTokenType.LPARENTH) {
268 final PsiBuilder.Marker typeCast = builder.mark();
269 builder.advanceLexer();
271 ReferenceParser.TypeInfo typeInfo = myParser.getReferenceParser().parseTypeInfo(
272 builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD | ReferenceParser.CONJUNCTIONS | ReferenceParser.INCOMPLETE_ANNO);
273 if (typeInfo == null || !expect(builder, JavaTokenType.RPARENTH)) {
274 typeCast.rollbackTo();
275 return parsePostfix(builder);
278 if (PREF_ARITHMETIC_OPS.contains(builder.getTokenType()) && !typeInfo.isPrimitive) {
279 typeCast.rollbackTo();
280 return parsePostfix(builder);
283 final PsiBuilder.Marker expr = parseUnary(builder);
285 if (!typeInfo.isParameterized) { // cannot parse correct parenthesized expression after correct parameterized type
286 typeCast.rollbackTo();
287 return parsePostfix(builder);
290 error(builder, JavaErrorMessages.message("expected.expression"));
294 typeCast.done(JavaElementType.TYPE_CAST_EXPRESSION);
298 return parsePostfix(builder);
303 private PsiBuilder.Marker parsePostfix(final PsiBuilder builder) {
304 PsiBuilder.Marker operand = parsePrimary(builder, null, -1);
305 if (operand == null) return null;
307 while (POSTFIX_OPS.contains(builder.getTokenType())) {
308 final PsiBuilder.Marker postfix = operand.precede();
309 builder.advanceLexer();
310 postfix.done(JavaElementType.POSTFIX_EXPRESSION);
317 private enum BreakPoint {P1, P2, P4}
320 private PsiBuilder.Marker parsePrimary(PsiBuilder builder, @Nullable BreakPoint breakPoint, int breakOffset) {
321 PsiBuilder.Marker startMarker = builder.mark();
323 PsiBuilder.Marker expr = parsePrimaryExpressionStart(builder);
330 final IElementType tokenType = builder.getTokenType();
331 if (tokenType == JavaTokenType.DOT) {
332 final PsiBuilder.Marker dotPos = builder.mark();
333 final int dotOffset = builder.getCurrentOffset();
334 builder.advanceLexer();
336 IElementType dotTokenType = builder.getTokenType();
337 if (dotTokenType == JavaTokenType.AT) {
338 myParser.getDeclarationParser().parseAnnotations(builder);
339 dotTokenType = builder.getTokenType();
342 if (dotTokenType == JavaTokenType.CLASS_KEYWORD && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
343 if (breakPoint == BreakPoint.P1 && builder.getCurrentOffset() == breakOffset) {
344 error(builder, JavaErrorMessages.message("expected.identifier"));
345 drop(startMarker, dotPos);
349 final PsiBuilder.Marker copy = startMarker.precede();
350 final int offset = builder.getCurrentOffset();
351 startMarker.rollbackTo();
353 final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
354 if (classObjAccess == null || builder.getCurrentOffset() < offset) {
356 return parsePrimary(builder, BreakPoint.P1, offset);
360 expr = classObjAccess;
362 else if (dotTokenType == JavaTokenType.NEW_KEYWORD) {
364 expr = parseNew(builder, expr);
366 else if (dotTokenType == JavaTokenType.SUPER_KEYWORD && builder.lookAhead(1) == JavaTokenType.LPARENTH) {
368 PsiBuilder.Marker refExpr = expr.precede();
369 builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
370 builder.advanceLexer();
371 refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
374 else if (THIS_OR_SUPER.contains(dotTokenType) && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
375 if (breakPoint == BreakPoint.P2 && builder.getCurrentOffset() == breakOffset) {
381 PsiBuilder.Marker copy = startMarker.precede();
382 int offset = builder.getCurrentOffset();
383 startMarker.rollbackTo();
385 PsiBuilder.Marker ref = myParser.getReferenceParser().parseJavaCodeReference(builder, false, true, false, false);
386 if (ref == null || builder.getTokenType() != JavaTokenType.DOT || builder.getCurrentOffset() != dotOffset) {
388 return parsePrimary(builder, BreakPoint.P2, offset);
390 builder.advanceLexer();
392 if (builder.getTokenType() != dotTokenType) {
394 return parsePrimary(builder, BreakPoint.P2, offset);
396 builder.advanceLexer();
399 expr = ref.precede();
400 expr.done(dotTokenType == JavaTokenType.THIS_KEYWORD ? JavaElementType.THIS_EXPRESSION : JavaElementType.SUPER_EXPRESSION);
403 PsiBuilder.Marker refExpr = expr.precede();
405 myParser.getReferenceParser().parseReferenceParameterList(builder, false, false);
407 if (!expect(builder, ID_OR_SUPER)) {
409 builder.advanceLexer();
410 myParser.getReferenceParser().parseReferenceParameterList(builder, false, false);
411 error(builder, JavaErrorMessages.message("expected.identifier"));
412 refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
418 refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
422 else if (tokenType == JavaTokenType.LPARENTH) {
423 if (exprType(expr) != JavaElementType.REFERENCE_EXPRESSION) {
428 PsiBuilder.Marker callExpr = expr.precede();
429 parseArgumentList(builder);
430 callExpr.done(JavaElementType.METHOD_CALL_EXPRESSION);
433 else if (tokenType == JavaTokenType.LBRACKET) {
434 if (breakPoint == BreakPoint.P4) {
439 builder.advanceLexer();
441 if (builder.getTokenType() == JavaTokenType.RBRACKET && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
442 final int pos = builder.getCurrentOffset();
443 final PsiBuilder.Marker copy = startMarker.precede();
444 startMarker.rollbackTo();
446 final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
447 if (classObjAccess == null || builder.getCurrentOffset() <= pos) {
449 return parsePrimary(builder, BreakPoint.P4, -1);
453 expr = classObjAccess;
456 final PsiBuilder.Marker arrayAccess = expr.precede();
458 final PsiBuilder.Marker index = parse(builder);
460 error(builder, JavaErrorMessages.message("expected.expression"));
461 arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
466 if (builder.getTokenType() != JavaTokenType.RBRACKET) {
467 error(builder, JavaErrorMessages.message("expected.rbracket"));
468 arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
472 builder.advanceLexer();
474 arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
478 else if (tokenType == JavaTokenType.DOUBLE_COLON) {
479 return parseMethodReference(builder, startMarker);
489 private PsiBuilder.Marker parsePrimaryExpressionStart(final PsiBuilder builder) {
490 IElementType tokenType = builder.getTokenType();
492 if (LITERALS.contains(tokenType)) {
493 final PsiBuilder.Marker literal = builder.mark();
494 builder.advanceLexer();
495 literal.done(JavaElementType.LITERAL_EXPRESSION);
499 if (tokenType == JavaTokenType.LBRACE) {
500 return parseArrayInitializer(builder);
503 if (tokenType == JavaTokenType.NEW_KEYWORD) {
504 return parseNew(builder, null);
507 if (tokenType == JavaTokenType.LPARENTH) {
508 final PsiBuilder.Marker lambda = parseLambdaAfterParenth(builder);
509 if (lambda != null) {
513 final PsiBuilder.Marker parenth = builder.mark();
514 builder.advanceLexer();
516 final PsiBuilder.Marker inner = parse(builder);
518 error(builder, JavaErrorMessages.message("expected.expression"));
521 if (!expect(builder, JavaTokenType.RPARENTH)) {
523 error(builder, JavaErrorMessages.message("expected.rparen"));
527 parenth.done(JavaElementType.PARENTH_EXPRESSION);
531 if (TYPE_START.contains(tokenType)) {
532 final PsiBuilder.Marker mark = builder.mark();
534 final ReferenceParser.TypeInfo typeInfo = myParser.getReferenceParser().parseTypeInfo(builder, 0);
535 if (typeInfo != null) {
536 boolean optionalClassKeyword = typeInfo.isPrimitive || typeInfo.isArray;
537 if (optionalClassKeyword || !typeInfo.hasErrors && typeInfo.isParameterized) {
538 final PsiBuilder.Marker result = parseClassAccessOrMethodReference(builder, mark, optionalClassKeyword);
539 if (result != null) {
548 PsiBuilder.Marker annotation = null;
549 if (tokenType == JavaTokenType.AT) {
550 annotation = myParser.getDeclarationParser().parseAnnotations(builder);
551 tokenType = builder.getTokenType();
554 if (tokenType == JavaTokenType.IDENTIFIER) {
555 if (builder.lookAhead(1) == JavaTokenType.ARROW) {
556 return parseLambdaExpression(builder, false);
559 final PsiBuilder.Marker refExpr;
560 if (annotation != null) {
561 final PsiBuilder.Marker refParam = annotation.precede();
562 refParam.doneBefore(JavaElementType.REFERENCE_PARAMETER_LIST, annotation);
563 refExpr = refParam.precede();
566 refExpr = builder.mark();
567 builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
570 builder.advanceLexer();
571 refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
575 if (annotation != null) {
576 annotation.rollbackTo();
577 tokenType = builder.getTokenType();
580 PsiBuilder.Marker expr = null;
581 if (tokenType == JavaTokenType.LT) {
582 expr = builder.mark();
584 if (!myParser.getReferenceParser().parseReferenceParameterList(builder, false, false)) {
589 tokenType = builder.getTokenType();
590 if (!THIS_OR_SUPER.contains(tokenType)) {
596 if (THIS_OR_SUPER.contains(tokenType)) {
598 expr = builder.mark();
599 builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
601 builder.advanceLexer();
602 expr.done(builder.getTokenType() == JavaTokenType.LPARENTH
603 ? JavaElementType.REFERENCE_EXPRESSION
604 : tokenType == JavaTokenType.THIS_KEYWORD
605 ? JavaElementType.THIS_EXPRESSION
606 : JavaElementType.SUPER_EXPRESSION);
614 private PsiBuilder.Marker parseArrayInitializer(PsiBuilder builder) {
615 return parseArrayInitializer(builder, JavaElementType.ARRAY_INITIALIZER_EXPRESSION, new Function<PsiBuilder, Boolean>() {
617 public Boolean fun(PsiBuilder builder) {
618 return parse(builder) != null;
620 }, "expected.expression");
624 public PsiBuilder.Marker parseArrayInitializer(@NotNull PsiBuilder builder,
625 @NotNull IElementType type,
626 @NotNull Function<PsiBuilder, Boolean> elementParser,
627 @NotNull @PropertyKey(resourceBundle = BUNDLE) String missingElementKey) {
628 final PsiBuilder.Marker arrayInit = builder.mark();
629 builder.advanceLexer();
631 boolean first = true;
633 if (builder.getTokenType() == JavaTokenType.RBRACE) {
634 builder.advanceLexer();
638 if (builder.getTokenType() == null) {
639 error(builder, JavaErrorMessages.message("expected.rbrace"));
643 if (!elementParser.fun(builder)) {
644 if (builder.getTokenType() == JavaTokenType.COMMA) {
645 if (first && builder.lookAhead(1) == JavaTokenType.RBRACE) {
649 builder.error(JavaErrorMessages.message(missingElementKey));
651 else if (builder.getTokenType() != JavaTokenType.RBRACE) {
652 error(builder, JavaErrorMessages.message("expected.rbrace"));
659 final IElementType tokenType = builder.getTokenType();
660 if (tokenType == JavaTokenType.COMMA) {
661 builder.advanceLexer();
663 else if (tokenType != JavaTokenType.RBRACE) {
664 error(builder, JavaErrorMessages.message("expected.comma"));
668 arrayInit.done(type);
673 private PsiBuilder.Marker parseNew(PsiBuilder builder, @Nullable PsiBuilder.Marker start) {
674 PsiBuilder.Marker newExpr = (start != null ? start.precede() : builder.mark());
675 builder.advanceLexer();
677 myParser.getReferenceParser().parseReferenceParameterList(builder, false, true);
679 PsiBuilder.Marker refOrType;
680 PsiBuilder.Marker anno = myParser.getDeclarationParser().parseAnnotations(builder);
681 IElementType tokenType = builder.getTokenType();
682 if (tokenType == JavaTokenType.IDENTIFIER) {
684 refOrType = myParser.getReferenceParser().parseJavaCodeReference(builder, true, true, true, true);
685 if (refOrType == null) {
686 error(builder, JavaErrorMessages.message("expected.identifier"));
687 newExpr.done(JavaElementType.NEW_EXPRESSION);
691 else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
693 builder.advanceLexer();
696 error(builder, JavaErrorMessages.message("expected.identifier"));
697 newExpr.done(JavaElementType.NEW_EXPRESSION);
701 if (refOrType != null && builder.getTokenType() == JavaTokenType.LPARENTH) {
702 parseArgumentList(builder);
703 if (builder.getTokenType() == JavaTokenType.LBRACE) {
704 final PsiBuilder.Marker classElement = refOrType.precede();
705 myParser.getDeclarationParser().parseClassBodyWithBraces(builder, false, false);
706 classElement.done(JavaElementType.ANONYMOUS_CLASS);
708 newExpr.done(JavaElementType.NEW_EXPRESSION);
712 anno = myParser.getDeclarationParser().parseAnnotations(builder);
714 if (builder.getTokenType() != JavaTokenType.LBRACKET) {
716 error(builder, JavaErrorMessages.message(refOrType == null ? "expected.lbracket" : "expected.lparen.or.lbracket"));
717 newExpr.done(JavaElementType.NEW_EXPRESSION);
721 int bracketCount = 0;
724 anno = myParser.getDeclarationParser().parseAnnotations(builder);
726 if (builder.getTokenType() != JavaTokenType.LBRACKET) {
730 builder.advanceLexer();
732 if (bracketCount == dimCount) {
733 final PsiBuilder.Marker dimExpr = parse(builder);
734 if (dimExpr != null) {
740 if (!expectOrError(builder, JavaTokenType.RBRACKET, "expected.rbracket")) {
741 newExpr.done(JavaElementType.NEW_EXPRESSION);
747 if (builder.getTokenType() == JavaTokenType.LBRACE) {
748 parseArrayInitializer(builder);
751 error(builder, JavaErrorMessages.message("expected.array.initializer"));
755 newExpr.done(JavaElementType.NEW_EXPRESSION);
760 private PsiBuilder.Marker parseClassAccessOrMethodReference(PsiBuilder builder) {
761 PsiBuilder.Marker expr = builder.mark();
763 boolean primitive = ElementType.PRIMITIVE_TYPE_BIT_SET.contains(builder.getTokenType());
764 if (myParser.getReferenceParser().parseType(builder, 0) == null) {
769 PsiBuilder.Marker result = parseClassAccessOrMethodReference(builder, expr, primitive);
770 if (result == null) expr.rollbackTo();
775 private PsiBuilder.Marker parseClassAccessOrMethodReference(PsiBuilder builder, PsiBuilder.Marker expr, boolean optionalClassKeyword) {
776 IElementType tokenType = builder.getTokenType();
777 if (tokenType == JavaTokenType.DOT) {
778 return parseClassObjectAccess(builder, expr, optionalClassKeyword);
780 else if (tokenType == JavaTokenType.DOUBLE_COLON) {
781 return parseMethodReference(builder, expr);
788 private static PsiBuilder.Marker parseClassObjectAccess(PsiBuilder builder, PsiBuilder.Marker expr, boolean optionalClassKeyword) {
789 final PsiBuilder.Marker mark = builder.mark();
790 builder.advanceLexer();
792 if (builder.getTokenType() == JavaTokenType.CLASS_KEYWORD) {
794 builder.advanceLexer();
797 if (!optionalClassKeyword) return null;
799 builder.error(".class expected");
802 expr.done(JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION);
807 private PsiBuilder.Marker parseMethodReference(final PsiBuilder builder, final PsiBuilder.Marker start) {
808 builder.advanceLexer();
810 myParser.getReferenceParser().parseReferenceParameterList(builder, false, false);
812 if (!expect(builder, JavaTokenType.IDENTIFIER) && !expect(builder, JavaTokenType.NEW_KEYWORD)) {
813 error(builder, JavaErrorMessages.message("expected.identifier"));
816 start.done(JavaElementType.METHOD_REF_EXPRESSION);
821 private PsiBuilder.Marker parseLambdaAfterParenth(final PsiBuilder builder) {
822 final boolean isLambda;
823 final boolean isTyped;
825 final IElementType nextToken1 = builder.lookAhead(1);
826 final IElementType nextToken2 = builder.lookAhead(2);
827 if (nextToken1 == JavaTokenType.RPARENTH && nextToken2 == JavaTokenType.ARROW) {
831 else if (nextToken1 == JavaTokenType.AT ||
832 ElementType.MODIFIER_BIT_SET.contains(nextToken1) || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(nextToken1)) {
836 else if (nextToken1 == JavaTokenType.IDENTIFIER) {
837 if (nextToken2 == JavaTokenType.COMMA || nextToken2 == JavaTokenType.RPARENTH && builder.lookAhead(3) == JavaTokenType.ARROW) {
841 else if (nextToken2 == JavaTokenType.ARROW) {
846 boolean lambda = false;
848 PsiBuilder.Marker marker = builder.mark();
849 builder.advanceLexer();
850 ReferenceParser.TypeInfo typeInfo = myParser.getReferenceParser().parseTypeInfo(
851 builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
852 if (typeInfo != null) {
853 IElementType t = builder.getTokenType();
854 if (t == JavaTokenType.IDENTIFIER ||
855 t == JavaTokenType.THIS_KEYWORD ||
856 t == JavaTokenType.RPARENTH && builder.lookAhead(1) == JavaTokenType.ARROW) {
871 return isLambda ? parseLambdaExpression(builder, isTyped) : null;
875 private PsiBuilder.Marker parseLambdaExpression(final PsiBuilder builder, final boolean typed) {
876 final PsiBuilder.Marker start = builder.mark();
878 myParser.getDeclarationParser().parseLambdaParameterList(builder, typed);
880 if (!expect(builder, JavaTokenType.ARROW)) {
885 final PsiBuilder.Marker body;
886 if (builder.getTokenType() == JavaTokenType.LBRACE) {
887 body = myParser.getStatementParser().parseCodeBlock(builder);
890 body = parse(builder);
894 builder.error(JavaErrorMessages.message("expected.lbrace"));
897 start.done(JavaElementType.LAMBDA_EXPRESSION);
902 public PsiBuilder.Marker parseArgumentList(final PsiBuilder builder) {
903 final PsiBuilder.Marker list = builder.mark();
904 builder.advanceLexer();
906 boolean first = true;
908 final IElementType tokenType = builder.getTokenType();
909 if (first && (ARGS_LIST_END.contains(tokenType) || builder.eof())) break;
910 if (!first && !ARGS_LIST_CONTINUE.contains(tokenType)) break;
912 boolean hasError = false;
914 if (builder.getTokenType() == JavaTokenType.COMMA) {
915 builder.advanceLexer();
919 error(builder, JavaErrorMessages.message("expected.comma.or.rparen"));
920 emptyExpression(builder);
925 final PsiBuilder.Marker arg = parse(builder);
928 error(builder, JavaErrorMessages.message("expected.expression"));
929 emptyExpression(builder);
931 if (!ARGS_LIST_CONTINUE.contains(builder.getTokenType())) break;
932 if (builder.getTokenType() != JavaTokenType.COMMA && !builder.eof()) {
933 builder.advanceLexer();
938 final boolean closed = expectOrError(builder, JavaTokenType.RPARENTH, "expected.rparen");
940 list.done(JavaElementType.EXPRESSION_LIST);
942 list.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
947 private static void emptyExpression(final PsiBuilder builder) {
948 emptyElement(builder, JavaElementType.EMPTY_EXPRESSION);
952 private static IElementType getGtTokenType(final PsiBuilder builder) {
953 IElementType tokenType = builder.getTokenType();
954 if (tokenType != JavaTokenType.GT) return tokenType;
956 if (builder.rawLookup(1) == JavaTokenType.GT) {
957 if (builder.rawLookup(2) == JavaTokenType.GT) {
958 if (builder.rawLookup(3) == JavaTokenType.EQ) {
959 tokenType = JavaTokenType.GTGTGTEQ;
962 tokenType = JavaTokenType.GTGTGT;
965 else if (builder.rawLookup(2) == JavaTokenType.EQ) {
966 tokenType = JavaTokenType.GTGTEQ;
969 tokenType = JavaTokenType.GTGT;
972 else if (builder.rawLookup(1) == JavaTokenType.EQ) {
973 tokenType = JavaTokenType.GE;
979 private static void advanceGtToken(final PsiBuilder builder, final IElementType type) {
980 final PsiBuilder.Marker gtToken = builder.mark();
982 if (type == JavaTokenType.GTGTGTEQ) {
985 else if (type == JavaTokenType.GTGTGT || type == JavaTokenType.GTGTEQ) {
988 else if (type == JavaTokenType.GTGT || type == JavaTokenType.GE) {
993 builder.advanceLexer();
997 gtToken.collapse(type);