2ac9a064dbb10a5a08580fe3e9648717c50faa5a
[idea/community.git] / java / java-psi-impl / src / com / intellij / lang / java / parser / ExpressionParser.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.lang.java.parser;
17
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;
31
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.*;
35
36 public class ExpressionParser {
37   private enum ExprType {
38     CONDITIONAL_OR, CONDITIONAL_AND, OR, XOR, AND, EQUALITY, RELATIONAL, SHIFT, ADDITIVE, MULTIPLICATIVE, UNARY, TYPE
39   }
40
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));
68
69   private final JavaParser myParser;
70
71   public ExpressionParser(@NotNull final JavaParser javaParser) {
72     myParser = javaParser;
73   }
74
75   @Nullable
76   public PsiBuilder.Marker parse(final PsiBuilder builder) {
77     return parseAssignment(builder);
78   }
79
80   @Nullable
81   private PsiBuilder.Marker parseAssignment(final PsiBuilder builder) {
82     final PsiBuilder.Marker left = parseConditional(builder);
83     if (left == null) return null;
84
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);
89
90       final PsiBuilder.Marker right = parse(builder);
91       if (right == null) {
92         error(builder, JavaErrorMessages.message("expected.expression"));
93       }
94
95       assignment.done(JavaElementType.ASSIGNMENT_EXPRESSION);
96       return assignment;
97     }
98
99     return left;
100   }
101
102   @Nullable
103   public PsiBuilder.Marker parseConditional(final PsiBuilder builder) {
104     final PsiBuilder.Marker condition = parseExpression(builder, ExprType.CONDITIONAL_OR);
105     if (condition == null) return null;
106
107     if (builder.getTokenType() != JavaTokenType.QUEST) return condition;
108     final PsiBuilder.Marker ternary = condition.precede();
109     builder.advanceLexer();
110
111     final PsiBuilder.Marker truePart = parse(builder);
112     if (truePart == null) {
113       error(builder, JavaErrorMessages.message("expected.expression"));
114       ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
115       return ternary;
116     }
117
118     if (builder.getTokenType() != JavaTokenType.COLON) {
119       error(builder, JavaErrorMessages.message("expected.colon"));
120       ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
121       return ternary;
122     }
123     builder.advanceLexer();
124
125     final PsiBuilder.Marker falsePart = parseConditional(builder);
126     if (falsePart == null) {
127       error(builder, JavaErrorMessages.message("expected.expression"));
128       ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
129       return ternary;
130     }
131
132     ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
133     return ternary;
134   }
135
136   @Nullable
137   private PsiBuilder.Marker parseExpression(final PsiBuilder builder, final ExprType type) {
138     switch (type) {
139       case CONDITIONAL_OR:
140         return parseBinary(builder, ExprType.CONDITIONAL_AND, CONDITIONAL_OR_OPS);
141
142       case CONDITIONAL_AND:
143         return parseBinary(builder, ExprType.OR, CONDITIONAL_AND_OPS);
144
145       case OR:
146         return parseBinary(builder, ExprType.XOR, OR_OPS);
147
148       case XOR:
149         return parseBinary(builder, ExprType.AND, XOR_OPS);
150
151       case AND:
152         return parseBinary(builder, ExprType.EQUALITY, AND_OPS);
153
154       case EQUALITY:
155         return parseBinary(builder, ExprType.RELATIONAL, EQUALITY_OPS);
156
157       case RELATIONAL:
158         return parseRelational(builder);
159
160       case SHIFT:
161         return parseBinary(builder, ExprType.ADDITIVE, SHIFT_OPS);
162
163       case ADDITIVE:
164         return parseBinary(builder, ExprType.MULTIPLICATIVE, ADDITIVE_OPS);
165
166       case MULTIPLICATIVE:
167         return parseBinary(builder, ExprType.UNARY, MULTIPLICATIVE_OPS);
168
169       case UNARY:
170         return parseUnary(builder);
171
172       case TYPE:
173         return myParser.getReferenceParser().parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
174
175       default:
176         assert false : "Unexpected type: " + type;
177         return null;
178     }
179   }
180
181   @Nullable
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;
186
187     IElementType tokenType = getGtTokenType(builder);
188     IElementType currentExprTokenType = tokenType;
189     while (true) {
190       if (tokenType == null || !ops.contains(tokenType)) break;
191
192       advanceGtToken(builder, tokenType);
193
194       final PsiBuilder.Marker right = parseExpression(builder, type);
195       operandCount++;
196       tokenType = getGtTokenType(builder);
197       if (tokenType == null || !ops.contains(tokenType) || tokenType != currentExprTokenType || right == null) {
198         // save
199         result = result.precede();
200         if (right == null) {
201           error(builder, JavaErrorMessages.message("expected.expression"));
202         }
203         result.done(operandCount > 2 ? JavaElementType.POLYADIC_EXPRESSION : JavaElementType.BINARY_EXPRESSION);
204         if (right == null) break;
205         currentExprTokenType = tokenType;
206         operandCount = 1;
207       }
208     }
209
210     return result;
211   }
212
213   @Nullable
214   private PsiBuilder.Marker parseRelational(final PsiBuilder builder) {
215     PsiBuilder.Marker left = parseExpression(builder, ExprType.SHIFT);
216     if (left == null) return null;
217
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;
225       }
226       else if (tokenType == JavaTokenType.INSTANCEOF_KEYWORD) {
227         toCreate = JavaElementType.INSTANCE_OF_EXPRESSION;
228         toParse = ExprType.TYPE;
229       }
230       else {
231         break;
232       }
233
234       final PsiBuilder.Marker expression = left.precede();
235       advanceGtToken(builder, tokenType);
236
237       final PsiBuilder.Marker right = parseExpression(builder, toParse);
238       if (right == null) {
239         error(builder, JavaErrorMessages.message(toParse == ExprType.TYPE ? "expected.type" : "expected.expression"));
240         expression.done(toCreate);
241         return expression;
242       }
243
244       expression.done(toCreate);
245       left = expression;
246     }
247
248     return left;
249   }
250
251   @Nullable
252   private PsiBuilder.Marker parseUnary(final PsiBuilder builder) {
253     final IElementType tokenType = builder.getTokenType();
254
255     if (PREFIX_OPS.contains(tokenType)) {
256       final PsiBuilder.Marker unary = builder.mark();
257       builder.advanceLexer();
258
259       final PsiBuilder.Marker operand = parseUnary(builder);
260       if (operand == null) {
261         error(builder, JavaErrorMessages.message("expected.expression"));
262       }
263
264       unary.done(JavaElementType.PREFIX_EXPRESSION);
265       return unary;
266     }
267     else if (tokenType == JavaTokenType.LPARENTH) {
268       final PsiBuilder.Marker typeCast = builder.mark();
269       builder.advanceLexer();
270
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);
276       }
277
278       if (PREF_ARITHMETIC_OPS.contains(builder.getTokenType()) && !typeInfo.isPrimitive) {
279         typeCast.rollbackTo();
280         return parsePostfix(builder);
281       }
282
283       final PsiBuilder.Marker expr = parseUnary(builder);
284       if (expr == null) {
285         if (!typeInfo.isParameterized) {  // cannot parse correct parenthesized expression after correct parameterized type
286           typeCast.rollbackTo();
287           return parsePostfix(builder);
288         }
289         else {
290           error(builder, JavaErrorMessages.message("expected.expression"));
291         }
292       }
293
294       typeCast.done(JavaElementType.TYPE_CAST_EXPRESSION);
295       return typeCast;
296     }
297     else {
298       return parsePostfix(builder);
299     }
300   }
301
302   @Nullable
303   private PsiBuilder.Marker parsePostfix(final PsiBuilder builder) {
304     PsiBuilder.Marker operand = parsePrimary(builder, null, -1);
305     if (operand == null) return null;
306
307     while (POSTFIX_OPS.contains(builder.getTokenType())) {
308       final PsiBuilder.Marker postfix = operand.precede();
309       builder.advanceLexer();
310       postfix.done(JavaElementType.POSTFIX_EXPRESSION);
311       operand = postfix;
312     }
313
314     return operand;
315   }
316
317   private enum BreakPoint {P1, P2, P4}
318
319   @Nullable
320   private PsiBuilder.Marker parsePrimary(PsiBuilder builder, @Nullable BreakPoint breakPoint, int breakOffset) {
321     PsiBuilder.Marker startMarker = builder.mark();
322
323     PsiBuilder.Marker expr = parsePrimaryExpressionStart(builder);
324     if (expr == null) {
325       startMarker.drop();
326       return null;
327     }
328
329     while (true) {
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();
335
336         IElementType dotTokenType = builder.getTokenType();
337         if (dotTokenType == JavaTokenType.AT) {
338           myParser.getDeclarationParser().parseAnnotations(builder);
339           dotTokenType = builder.getTokenType();
340         }
341
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);
346             return expr;
347           }
348
349           final PsiBuilder.Marker copy = startMarker.precede();
350           final int offset = builder.getCurrentOffset();
351           startMarker.rollbackTo();
352
353           final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
354           if (classObjAccess == null || builder.getCurrentOffset() < offset) {
355             copy.rollbackTo();
356             return parsePrimary(builder, BreakPoint.P1, offset);
357           }
358
359           startMarker = copy;
360           expr = classObjAccess;
361         }
362         else if (dotTokenType == JavaTokenType.NEW_KEYWORD) {
363           dotPos.drop();
364           expr = parseNew(builder, expr);
365         }
366         else if (dotTokenType == JavaTokenType.SUPER_KEYWORD && builder.lookAhead(1) == JavaTokenType.LPARENTH) {
367           dotPos.drop();
368           PsiBuilder.Marker refExpr = expr.precede();
369           builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
370           builder.advanceLexer();
371           refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
372           expr = refExpr;
373         }
374         else if (THIS_OR_SUPER.contains(dotTokenType) && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
375           if (breakPoint == BreakPoint.P2 && builder.getCurrentOffset() == breakOffset) {
376             dotPos.rollbackTo();
377             startMarker.drop();
378             return expr;
379           }
380
381           PsiBuilder.Marker copy = startMarker.precede();
382           int offset = builder.getCurrentOffset();
383           startMarker.rollbackTo();
384
385           PsiBuilder.Marker ref = myParser.getReferenceParser().parseJavaCodeReference(builder, false, true, false, false);
386           if (ref == null || builder.getTokenType() != JavaTokenType.DOT || builder.getCurrentOffset() != dotOffset) {
387             copy.rollbackTo();
388             return parsePrimary(builder, BreakPoint.P2, offset);
389           }
390           builder.advanceLexer();
391
392           if (builder.getTokenType() != dotTokenType) {
393             copy.rollbackTo();
394             return parsePrimary(builder, BreakPoint.P2, offset);
395           }
396           builder.advanceLexer();
397
398           startMarker = copy;
399           expr = ref.precede();
400           expr.done(dotTokenType == JavaTokenType.THIS_KEYWORD ? JavaElementType.THIS_EXPRESSION : JavaElementType.SUPER_EXPRESSION);
401         }
402         else {
403           PsiBuilder.Marker refExpr = expr.precede();
404
405           myParser.getReferenceParser().parseReferenceParameterList(builder, false, false);
406
407           if (!expect(builder, ID_OR_SUPER)) {
408             dotPos.rollbackTo();
409             builder.advanceLexer();
410             myParser.getReferenceParser().parseReferenceParameterList(builder, false, false);
411             error(builder, JavaErrorMessages.message("expected.identifier"));
412             refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
413             startMarker.drop();
414             return refExpr;
415           }
416
417           dotPos.drop();
418           refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
419           expr = refExpr;
420         }
421       }
422       else if (tokenType == JavaTokenType.LPARENTH) {
423         if (exprType(expr) != JavaElementType.REFERENCE_EXPRESSION) {
424           startMarker.drop();
425           return expr;
426         }
427
428         PsiBuilder.Marker callExpr = expr.precede();
429         parseArgumentList(builder);
430         callExpr.done(JavaElementType.METHOD_CALL_EXPRESSION);
431         expr = callExpr;
432       }
433       else if (tokenType == JavaTokenType.LBRACKET) {
434         if (breakPoint == BreakPoint.P4) {
435           startMarker.drop();
436           return expr;
437         }
438
439         builder.advanceLexer();
440
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();
445
446           final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
447           if (classObjAccess == null || builder.getCurrentOffset() <= pos) {
448             copy.rollbackTo();
449             return parsePrimary(builder, BreakPoint.P4, -1);
450           }
451
452           startMarker = copy;
453           expr = classObjAccess;
454         }
455         else {
456           final PsiBuilder.Marker arrayAccess = expr.precede();
457
458           final PsiBuilder.Marker index = parse(builder);
459           if (index == null) {
460             error(builder, JavaErrorMessages.message("expected.expression"));
461             arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
462             startMarker.drop();
463             return arrayAccess;
464           }
465
466           if (builder.getTokenType() != JavaTokenType.RBRACKET) {
467             error(builder, JavaErrorMessages.message("expected.rbracket"));
468             arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
469             startMarker.drop();
470             return arrayAccess;
471           }
472           builder.advanceLexer();
473
474           arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
475           expr = arrayAccess;
476         }
477       }
478       else if (tokenType == JavaTokenType.DOUBLE_COLON) {
479         return parseMethodReference(builder, startMarker);
480       }
481       else {
482         startMarker.drop();
483         return expr;
484       }
485     }
486   }
487
488   @Nullable
489   private PsiBuilder.Marker parsePrimaryExpressionStart(final PsiBuilder builder) {
490     IElementType tokenType = builder.getTokenType();
491
492     if (LITERALS.contains(tokenType)) {
493       final PsiBuilder.Marker literal = builder.mark();
494       builder.advanceLexer();
495       literal.done(JavaElementType.LITERAL_EXPRESSION);
496       return literal;
497     }
498
499     if (tokenType == JavaTokenType.LBRACE) {
500       return parseArrayInitializer(builder);
501     }
502
503     if (tokenType == JavaTokenType.NEW_KEYWORD) {
504       return parseNew(builder, null);
505     }
506
507     if (tokenType == JavaTokenType.LPARENTH) {
508       final PsiBuilder.Marker lambda = parseLambdaAfterParenth(builder);
509       if (lambda != null) {
510         return lambda;
511       }
512
513       final PsiBuilder.Marker parenth = builder.mark();
514       builder.advanceLexer();
515
516       final PsiBuilder.Marker inner = parse(builder);
517       if (inner == null) {
518         error(builder, JavaErrorMessages.message("expected.expression"));
519       }
520
521       if (!expect(builder, JavaTokenType.RPARENTH)) {
522         if (inner != null) {
523           error(builder, JavaErrorMessages.message("expected.rparen"));
524         }
525       }
526
527       parenth.done(JavaElementType.PARENTH_EXPRESSION);
528       return parenth;
529     }
530
531     if (TYPE_START.contains(tokenType)) {
532       final PsiBuilder.Marker mark = builder.mark();
533
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) {
540             return result;
541           }
542         }
543       }
544
545       mark.rollbackTo();
546     }
547
548     PsiBuilder.Marker annotation = null;
549     if (tokenType == JavaTokenType.AT) {
550       annotation = myParser.getDeclarationParser().parseAnnotations(builder);
551       tokenType = builder.getTokenType();
552     }
553
554     if (tokenType == JavaTokenType.IDENTIFIER) {
555       if (builder.lookAhead(1) == JavaTokenType.ARROW) {
556         return parseLambdaExpression(builder, false);
557       }
558
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();
564       }
565       else {
566         refExpr = builder.mark();
567         builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
568       }
569
570       builder.advanceLexer();
571       refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
572       return refExpr;
573     }
574
575     if (annotation != null) {
576       annotation.rollbackTo();
577       tokenType = builder.getTokenType();
578     }
579
580     PsiBuilder.Marker expr = null;
581     if (tokenType == JavaTokenType.LT) {
582       expr = builder.mark();
583
584       if (!myParser.getReferenceParser().parseReferenceParameterList(builder, false, false)) {
585         expr.rollbackTo();
586         return null;
587       }
588
589       tokenType = builder.getTokenType();
590       if (!THIS_OR_SUPER.contains(tokenType)) {
591         expr.rollbackTo();
592         return null;
593       }
594     }
595
596     if (THIS_OR_SUPER.contains(tokenType)) {
597       if (expr == null) {
598         expr = builder.mark();
599         builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
600       }
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);
607       return expr;
608     }
609
610     return null;
611   }
612
613   @NotNull
614   private PsiBuilder.Marker parseArrayInitializer(PsiBuilder builder) {
615     return parseArrayInitializer(builder, JavaElementType.ARRAY_INITIALIZER_EXPRESSION, new Function<PsiBuilder, Boolean>() {
616       @Override
617       public Boolean fun(PsiBuilder builder) {
618         return parse(builder) != null;
619       }
620     }, "expected.expression");
621   }
622
623   @NotNull
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();
630
631     boolean first = true;
632     while (true) {
633       if (builder.getTokenType() == JavaTokenType.RBRACE) {
634         builder.advanceLexer();
635         break;
636       }
637
638       if (builder.getTokenType() == null) {
639         error(builder, JavaErrorMessages.message("expected.rbrace"));
640         break;
641       }
642
643       if (!elementParser.fun(builder)) {
644         if (builder.getTokenType() == JavaTokenType.COMMA) {
645           if (first && builder.lookAhead(1) == JavaTokenType.RBRACE) {
646             advance(builder, 2);
647             break;
648           }
649           builder.error(JavaErrorMessages.message(missingElementKey));
650         }
651         else if (builder.getTokenType() != JavaTokenType.RBRACE) {
652           error(builder, JavaErrorMessages.message("expected.rbrace"));
653           break;
654         }
655       }
656
657       first = false;
658
659       final IElementType tokenType = builder.getTokenType();
660       if (tokenType == JavaTokenType.COMMA) {
661         builder.advanceLexer();
662       }
663       else if (tokenType != JavaTokenType.RBRACE) {
664         error(builder, JavaErrorMessages.message("expected.comma"));
665       }
666     }
667
668     arrayInit.done(type);
669     return arrayInit;
670   }
671
672   @NotNull
673   private PsiBuilder.Marker parseNew(PsiBuilder builder, @Nullable PsiBuilder.Marker start) {
674     PsiBuilder.Marker newExpr = (start != null ? start.precede() : builder.mark());
675     builder.advanceLexer();
676
677     myParser.getReferenceParser().parseReferenceParameterList(builder, false, true);
678
679     PsiBuilder.Marker refOrType;
680     PsiBuilder.Marker anno = myParser.getDeclarationParser().parseAnnotations(builder);
681     IElementType tokenType = builder.getTokenType();
682     if (tokenType == JavaTokenType.IDENTIFIER) {
683       rollbackTo(anno);
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);
688         return newExpr;
689       }
690     }
691     else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
692       refOrType = null;
693       builder.advanceLexer();
694     }
695     else {
696       error(builder, JavaErrorMessages.message("expected.identifier"));
697       newExpr.done(JavaElementType.NEW_EXPRESSION);
698       return newExpr;
699     }
700
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);
707       }
708       newExpr.done(JavaElementType.NEW_EXPRESSION);
709       return newExpr;
710     }
711
712     anno = myParser.getDeclarationParser().parseAnnotations(builder);
713
714     if (builder.getTokenType() != JavaTokenType.LBRACKET) {
715       rollbackTo(anno);
716       error(builder, JavaErrorMessages.message(refOrType == null ? "expected.lbracket" : "expected.lparen.or.lbracket"));
717       newExpr.done(JavaElementType.NEW_EXPRESSION);
718       return newExpr;
719     }
720
721     int bracketCount = 0;
722     int dimCount = 0;
723     while (true) {
724       anno = myParser.getDeclarationParser().parseAnnotations(builder);
725
726       if (builder.getTokenType() != JavaTokenType.LBRACKET) {
727         rollbackTo(anno);
728         break;
729       }
730       builder.advanceLexer();
731
732       if (bracketCount == dimCount) {
733         final PsiBuilder.Marker dimExpr = parse(builder);
734         if (dimExpr != null) {
735           dimCount++;
736         }
737       }
738       bracketCount++;
739
740       if (!expectOrError(builder, JavaTokenType.RBRACKET, "expected.rbracket")) {
741         newExpr.done(JavaElementType.NEW_EXPRESSION);
742         return newExpr;
743       }
744     }
745
746     if (dimCount == 0) {
747       if (builder.getTokenType() == JavaTokenType.LBRACE) {
748         parseArrayInitializer(builder);
749       }
750       else {
751         error(builder, JavaErrorMessages.message("expected.array.initializer"));
752       }
753     }
754
755     newExpr.done(JavaElementType.NEW_EXPRESSION);
756     return newExpr;
757   }
758
759   @Nullable
760   private PsiBuilder.Marker parseClassAccessOrMethodReference(PsiBuilder builder) {
761     PsiBuilder.Marker expr = builder.mark();
762
763     boolean primitive = ElementType.PRIMITIVE_TYPE_BIT_SET.contains(builder.getTokenType());
764     if (myParser.getReferenceParser().parseType(builder, 0) == null) {
765       expr.drop();
766       return null;
767     }
768
769     PsiBuilder.Marker result = parseClassAccessOrMethodReference(builder, expr, primitive);
770     if (result == null) expr.rollbackTo();
771     return result;
772   }
773
774   @Nullable
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);
779     }
780     else if (tokenType == JavaTokenType.DOUBLE_COLON) {
781       return parseMethodReference(builder, expr);
782     }
783
784     return null;
785   }
786
787   @Nullable
788   private static PsiBuilder.Marker parseClassObjectAccess(PsiBuilder builder, PsiBuilder.Marker expr, boolean optionalClassKeyword) {
789     final PsiBuilder.Marker mark = builder.mark();
790     builder.advanceLexer();
791
792     if (builder.getTokenType() == JavaTokenType.CLASS_KEYWORD) {
793       mark.drop();
794       builder.advanceLexer();
795     }
796     else {
797       if (!optionalClassKeyword) return null;
798       mark.rollbackTo();
799       builder.error(".class expected");
800     }
801
802     expr.done(JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION);
803     return expr;
804   }
805
806   @NotNull
807   private PsiBuilder.Marker parseMethodReference(final PsiBuilder builder, final PsiBuilder.Marker start) {
808     builder.advanceLexer();
809
810     myParser.getReferenceParser().parseReferenceParameterList(builder, false, false);
811
812     if (!expect(builder, JavaTokenType.IDENTIFIER) && !expect(builder, JavaTokenType.NEW_KEYWORD)) {
813       error(builder, JavaErrorMessages.message("expected.identifier"));
814     }
815
816     start.done(JavaElementType.METHOD_REF_EXPRESSION);
817     return start;
818   }
819
820   @Nullable
821   private PsiBuilder.Marker parseLambdaAfterParenth(final PsiBuilder builder) {
822     final boolean isLambda;
823     final boolean isTyped;
824
825     final IElementType nextToken1 = builder.lookAhead(1);
826     final IElementType nextToken2 = builder.lookAhead(2);
827     if (nextToken1 == JavaTokenType.RPARENTH && nextToken2 == JavaTokenType.ARROW) {
828       isLambda = true;
829       isTyped = false;
830     }
831     else if (nextToken1 == JavaTokenType.AT ||
832              ElementType.MODIFIER_BIT_SET.contains(nextToken1) || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(nextToken1)) {
833       isLambda = true;
834       isTyped = true;
835     }
836     else if (nextToken1 == JavaTokenType.IDENTIFIER) {
837       if (nextToken2 == JavaTokenType.COMMA || nextToken2 == JavaTokenType.RPARENTH && builder.lookAhead(3) == JavaTokenType.ARROW) {
838         isLambda = true;
839         isTyped = false;
840       }
841       else if (nextToken2 == JavaTokenType.ARROW) {
842         isLambda = false;
843         isTyped = false;
844       }
845       else {
846         boolean lambda = false;
847
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) {
857             lambda = true;
858           }
859         }
860         marker.rollbackTo();
861
862         isLambda = lambda;
863         isTyped = true;
864       }
865     }
866     else {
867       isLambda = false;
868       isTyped = false;
869     }
870
871     return isLambda ? parseLambdaExpression(builder, isTyped) : null;
872   }
873
874   @Nullable
875   private PsiBuilder.Marker parseLambdaExpression(final PsiBuilder builder, final boolean typed) {
876     final PsiBuilder.Marker start = builder.mark();
877
878     myParser.getDeclarationParser().parseLambdaParameterList(builder, typed);
879
880     if (!expect(builder, JavaTokenType.ARROW)) {
881       start.rollbackTo();
882       return null;
883     }
884
885     final PsiBuilder.Marker body;
886     if (builder.getTokenType() == JavaTokenType.LBRACE) {
887       body = myParser.getStatementParser().parseCodeBlock(builder);
888     }
889     else {
890       body = parse(builder);
891     }
892
893     if (body == null) {
894       builder.error(JavaErrorMessages.message("expected.lbrace"));
895     }
896
897     start.done(JavaElementType.LAMBDA_EXPRESSION);
898     return start;
899   }
900
901   @NotNull
902   public PsiBuilder.Marker parseArgumentList(final PsiBuilder builder) {
903     final PsiBuilder.Marker list = builder.mark();
904     builder.advanceLexer();
905
906     boolean first = true;
907     while (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;
911
912       boolean hasError = false;
913       if (!first) {
914         if (builder.getTokenType() == JavaTokenType.COMMA) {
915           builder.advanceLexer();
916         }
917         else {
918           hasError = true;
919           error(builder, JavaErrorMessages.message("expected.comma.or.rparen"));
920           emptyExpression(builder);
921         }
922       }
923       first = false;
924
925       final PsiBuilder.Marker arg = parse(builder);
926       if (arg == null) {
927         if (!hasError) {
928           error(builder, JavaErrorMessages.message("expected.expression"));
929           emptyExpression(builder);
930         }
931         if (!ARGS_LIST_CONTINUE.contains(builder.getTokenType())) break;
932         if (builder.getTokenType() != JavaTokenType.COMMA && !builder.eof()) {
933           builder.advanceLexer();
934         }
935       }
936     }
937
938     final boolean closed = expectOrError(builder, JavaTokenType.RPARENTH, "expected.rparen");
939
940     list.done(JavaElementType.EXPRESSION_LIST);
941     if (!closed) {
942       list.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
943     }
944     return list;
945   }
946
947   private static void emptyExpression(final PsiBuilder builder) {
948     emptyElement(builder, JavaElementType.EMPTY_EXPRESSION);
949   }
950
951   @Nullable
952   private static IElementType getGtTokenType(final PsiBuilder builder) {
953     IElementType tokenType = builder.getTokenType();
954     if (tokenType != JavaTokenType.GT) return tokenType;
955
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;
960         }
961         else {
962           tokenType = JavaTokenType.GTGTGT;
963         }
964       }
965       else if (builder.rawLookup(2) == JavaTokenType.EQ) {
966         tokenType = JavaTokenType.GTGTEQ;
967       }
968       else {
969         tokenType = JavaTokenType.GTGT;
970       }
971     }
972     else if (builder.rawLookup(1) == JavaTokenType.EQ) {
973       tokenType = JavaTokenType.GE;
974     }
975
976     return tokenType;
977   }
978
979   private static void advanceGtToken(final PsiBuilder builder, final IElementType type) {
980     final PsiBuilder.Marker gtToken = builder.mark();
981
982     if (type == JavaTokenType.GTGTGTEQ) {
983       advance(builder, 4);
984     }
985     else if (type == JavaTokenType.GTGTGT || type == JavaTokenType.GTGTEQ) {
986       advance(builder, 3);
987     }
988     else if (type == JavaTokenType.GTGT || type == JavaTokenType.GE) {
989       advance(builder, 2);
990     }
991     else {
992       gtToken.drop();
993       builder.advanceLexer();
994       return;
995     }
996
997     gtToken.collapse(type);
998   }
999 }