001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.parsing;
018    
019    import com.google.common.collect.ImmutableMap;
020    import com.intellij.lang.PsiBuilder;
021    import com.intellij.psi.tree.IElementType;
022    import com.intellij.psi.tree.TokenSet;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.kotlin.JetNodeType;
025    import org.jetbrains.kotlin.JetNodeTypes;
026    import org.jetbrains.kotlin.lexer.JetToken;
027    import org.jetbrains.kotlin.lexer.JetTokens;
028    import org.jetbrains.kotlin.parsing.JetParsing.NameParsingMode;
029    
030    import java.util.Arrays;
031    import java.util.HashSet;
032    import java.util.Set;
033    
034    import static org.jetbrains.kotlin.JetNodeTypes.*;
035    import static org.jetbrains.kotlin.lexer.JetTokens.*;
036    import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.ALLOW_UNESCAPED_REGULAR_ANNOTATIONS;
037    import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.ONLY_ESCAPED_REGULAR_ANNOTATIONS;
038    import static org.jetbrains.kotlin.parsing.JetParsing.DeclarationParsingMode.LOCAL;
039    
040    public class JetExpressionParsing extends AbstractJetParsing {
041        private static final TokenSet WHEN_CONDITION_RECOVERY_SET = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD);
042        private static final TokenSet WHEN_CONDITION_RECOVERY_SET_WITH_ARROW = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD, ARROW, DOT);
043    
044    
045        private static final ImmutableMap<String, JetToken> KEYWORD_TEXTS = tokenSetToMap(KEYWORDS);
046    
047        private static ImmutableMap<String, JetToken> tokenSetToMap(TokenSet tokens) {
048            ImmutableMap.Builder<String, JetToken> builder = ImmutableMap.builder();
049            for (IElementType token : tokens.getTypes()) {
050                builder.put(token.toString(), (JetToken) token);
051            }
052            return builder.build();
053        }
054    
055        private static final TokenSet TYPE_ARGUMENT_LIST_STOPPERS = TokenSet.create(
056                INTEGER_LITERAL, FLOAT_LITERAL, CHARACTER_LITERAL, OPEN_QUOTE,
057                PACKAGE_KEYWORD, AS_KEYWORD, TYPE_ALIAS_KEYWORD, INTERFACE_KEYWORD, CLASS_KEYWORD, THIS_KEYWORD, VAL_KEYWORD, VAR_KEYWORD,
058                FUN_KEYWORD, FOR_KEYWORD, NULL_KEYWORD,
059                TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD,
060                CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD, TRY_KEYWORD, ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD,
061                WHEN_KEYWORD, RBRACKET, RBRACE, RPAR, PLUSPLUS, MINUSMINUS, EXCLEXCL,
062                //            MUL,
063                PLUS, MINUS, EXCL, DIV, PERC, LTEQ,
064                // TODO GTEQ,   foo<bar, baz>=x
065                EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR, SAFE_ACCESS, ELVIS,
066                SEMICOLON, RANGE, EQ, MULTEQ, DIVEQ, PERCEQ, PLUSEQ, MINUSEQ, NOT_IN, NOT_IS,
067                COLONCOLON,
068                COLON
069        );
070    
071        /*package*/ static final TokenSet EXPRESSION_FIRST = TokenSet.create(
072                // Prefix
073                MINUS, PLUS, MINUSMINUS, PLUSPLUS,
074                EXCL, EXCLEXCL, // Joining complex tokens makes it necessary to put EXCLEXCL here
075                // Atomic
076    
077                COLONCOLON, // callable reference
078    
079                LPAR, // parenthesized
080    
081                // literal constant
082                TRUE_KEYWORD, FALSE_KEYWORD,
083                OPEN_QUOTE,
084                INTEGER_LITERAL, CHARACTER_LITERAL, FLOAT_LITERAL,
085                NULL_KEYWORD,
086    
087                LBRACE, // functionLiteral
088                FUN_KEYWORD, // expression function
089    
090                THIS_KEYWORD, // this
091                SUPER_KEYWORD, // super
092    
093                IF_KEYWORD, // if
094                WHEN_KEYWORD, // when
095                TRY_KEYWORD, // try
096                OBJECT_KEYWORD, // object
097    
098                // jump
099                THROW_KEYWORD,
100                RETURN_KEYWORD,
101                CONTINUE_KEYWORD,
102                BREAK_KEYWORD,
103    
104                // loop
105                FOR_KEYWORD,
106                WHILE_KEYWORD,
107                DO_KEYWORD,
108    
109                IDENTIFIER, // SimpleName
110                FIELD_IDENTIFIER, // Field reference
111    
112                PACKAGE_KEYWORD, // for absolute qualified names
113                AT // Just for better recovery and maybe for annotations
114        );
115    
116        private static final TokenSet STATEMENT_FIRST = TokenSet.orSet(
117                EXPRESSION_FIRST,
118                TokenSet.create(
119                        // declaration
120                        FUN_KEYWORD,
121                        VAL_KEYWORD, VAR_KEYWORD,
122                        INTERFACE_KEYWORD,
123                        CLASS_KEYWORD,
124                        TYPE_ALIAS_KEYWORD
125                ),
126                MODIFIER_KEYWORDS
127        );
128    
129        private static final TokenSet STATEMENT_NEW_LINE_QUICK_RECOVERY_SET =
130                TokenSet.orSet(
131                        TokenSet.andSet(STATEMENT_FIRST, TokenSet.andNot(KEYWORDS, TokenSet.create(IN_KEYWORD))),
132                        TokenSet.create(EOL_OR_SEMICOLON));
133    
134        /*package*/ static final TokenSet EXPRESSION_FOLLOW = TokenSet.create(
135                SEMICOLON, ARROW, COMMA, RBRACE, RPAR, RBRACKET
136        );
137    
138        @SuppressWarnings({"UnusedDeclaration"})
139        public enum Precedence {
140            POSTFIX(PLUSPLUS, MINUSMINUS, EXCLEXCL,
141                    DOT, SAFE_ACCESS), // typeArguments? valueArguments : typeArguments : arrayAccess
142    
143            PREFIX(MINUS, PLUS, MINUSMINUS, PLUSPLUS, EXCL) { // annotations
144    
145                @Override
146                public void parseHigherPrecedence(JetExpressionParsing parser) {
147                    throw new IllegalStateException("Don't call this method");
148                }
149            },
150    
151            COLON_AS(COLON, AS_KEYWORD, AS_SAFE) {
152                @Override
153                public JetNodeType parseRightHandSide(IElementType operation, JetExpressionParsing parser) {
154                    parser.myJetParsing.parseTypeRef();
155                    return BINARY_WITH_TYPE;
156                }
157    
158                @Override
159                public void parseHigherPrecedence(JetExpressionParsing parser) {
160                    parser.parsePrefixExpression();
161                }
162            },
163    
164            MULTIPLICATIVE(MUL, DIV, PERC),
165            ADDITIVE(PLUS, MINUS),
166            RANGE(JetTokens.RANGE),
167            SIMPLE_NAME(IDENTIFIER),
168            ELVIS(JetTokens.ELVIS),
169            IN_OR_IS(IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS) {
170                @Override
171                public JetNodeType parseRightHandSide(IElementType operation, JetExpressionParsing parser) {
172                    if (operation == IS_KEYWORD || operation == NOT_IS) {
173                        parser.myJetParsing.parseTypeRef();
174                        return IS_EXPRESSION;
175                    }
176    
177                    return super.parseRightHandSide(operation, parser);
178                }
179            },
180            COMPARISON(LT, GT, LTEQ, GTEQ),
181            EQUALITY(EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ),
182            CONJUNCTION(ANDAND),
183            DISJUNCTION(OROR),
184            //        ARROW(JetTokens.ARROW),
185            ASSIGNMENT(EQ, PLUSEQ, MINUSEQ, MULTEQ, DIVEQ, PERCEQ),
186            ;
187    
188            static {
189                Precedence[] values = Precedence.values();
190                for (Precedence precedence : values) {
191                    int ordinal = precedence.ordinal();
192                    precedence.higher = ordinal > 0 ? values[ordinal - 1] : null;
193                }
194            }
195    
196            private Precedence higher;
197            private final TokenSet operations;
198    
199            Precedence(IElementType... operations) {
200                this.operations = TokenSet.create(operations);
201            }
202    
203            public void parseHigherPrecedence(JetExpressionParsing parser) {
204                assert higher != null;
205                parser.parseBinaryExpression(higher);
206            }
207    
208            /**
209             *
210             * @param operation the operation sign (e.g. PLUS or IS)
211             * @param parser the parser object
212             * @return node type of the result
213             */
214            public JetNodeType parseRightHandSide(IElementType operation, JetExpressionParsing parser) {
215                parseHigherPrecedence(parser);
216                return BINARY_EXPRESSION;
217            }
218    
219            @NotNull
220            public final TokenSet getOperations() {
221                return operations;
222            }
223        }
224    
225        public static final TokenSet ALLOW_NEWLINE_OPERATIONS = TokenSet.create(
226                DOT, SAFE_ACCESS,
227                COLON, AS_KEYWORD, AS_SAFE,
228                ELVIS,
229                // Can't allow `is` and `!is` because of when entry conditions: IS_KEYWORD, NOT_IS,
230                ANDAND,
231                OROR
232        );
233    
234        public static final TokenSet ALL_OPERATIONS;
235    
236        static {
237            Set<IElementType> operations = new HashSet<IElementType>();
238            Precedence[] values = Precedence.values();
239            for (Precedence precedence : values) {
240                operations.addAll(Arrays.asList(precedence.getOperations().getTypes()));
241            }
242            ALL_OPERATIONS = TokenSet.create(operations.toArray(new IElementType[operations.size()]));
243        }
244    
245        static {
246            IElementType[] operations = OPERATIONS.getTypes();
247            Set<IElementType> opSet = new HashSet<IElementType>(Arrays.asList(operations));
248            IElementType[] usedOperations = ALL_OPERATIONS.getTypes();
249            Set<IElementType> usedSet = new HashSet<IElementType>(Arrays.asList(usedOperations));
250    
251            if (opSet.size() > usedSet.size()) {
252                opSet.removeAll(usedSet);
253                assert false : opSet;
254            }
255            assert usedSet.size() == opSet.size() : "Either some ops are unused, or something a non-op is used";
256    
257            usedSet.removeAll(opSet);
258    
259            assert usedSet.isEmpty() : usedSet.toString();
260        }
261    
262    
263        private final JetParsing myJetParsing;
264    
265        public JetExpressionParsing(SemanticWhitespaceAwarePsiBuilder builder, JetParsing jetParsing) {
266            super(builder);
267            myJetParsing = jetParsing;
268        }
269    
270        /*
271         * element
272         *   : annotations element
273         *   : "(" element ")" // see tupleLiteral
274         *   : literalConstant
275         *   : functionLiteral
276         *   : tupleLiteral
277         *   : "null"
278         *   : "this" ("<" type ">")?
279         *   : expressionWithPrecedences
280         *   : if
281         *   : try
282         *   : "typeof" "(" element ")"
283         *   : "new" constructorInvocation
284         *   : objectLiteral
285         *   : declaration
286         *   : jump
287         *   : loop
288         *   // block is syntactically equivalent to a functionLiteral with no parameters
289         *   ;
290         */
291        public void parseExpression() {
292            if (!atSet(EXPRESSION_FIRST)) {
293                error("Expecting an expression");
294                return;
295            }
296            parseBinaryExpression(Precedence.ASSIGNMENT);
297        }
298    
299        /*
300         * element (operation element)*
301         *
302         * see the precedence table
303         */
304        private void parseBinaryExpression(Precedence precedence) {
305            //        System.out.println(precedence.name() + " at " + myBuilder.getTokenText());
306    
307            PsiBuilder.Marker expression = mark();
308    
309            precedence.parseHigherPrecedence(this);
310    
311            while (!interruptedWithNewLine() && atSet(precedence.getOperations())) {
312                IElementType operation = tt();
313    
314                parseOperationReference();
315    
316                JetNodeType resultType = precedence.parseRightHandSide(operation, this);
317                expression.done(resultType);
318                expression = expression.precede();
319            }
320    
321            expression.drop();
322        }
323    
324        /*
325         * label prefixExpression
326         */
327        private void parseLabeledExpression() {
328            PsiBuilder.Marker expression = mark();
329            parseLabelDefinition();
330            parsePrefixExpression();
331            expression.done(LABELED_EXPRESSION);
332        }
333    
334        /*
335         * operation? prefixExpression
336         */
337        private void parsePrefixExpression() {
338            //        System.out.println("pre at "  + myBuilder.getTokenText());
339    
340            if (at(AT)) {
341                if (!parseLocalDeclaration()) {
342                    PsiBuilder.Marker expression = mark();
343                    myJetParsing.parseAnnotations(ONLY_ESCAPED_REGULAR_ANNOTATIONS);
344                    parsePrefixExpression();
345                    expression.done(ANNOTATED_EXPRESSION);
346                }
347            }
348            else {
349                myBuilder.disableJoiningComplexTokens();
350                if (isAtLabelDefinitionOrMissingIdentifier()) {
351                    myBuilder.restoreJoiningComplexTokensState();
352                    parseLabeledExpression();
353                }
354                else if (atSet(Precedence.PREFIX.getOperations())) {
355                    PsiBuilder.Marker expression = mark();
356    
357                    parseOperationReference();
358    
359                    myBuilder.restoreJoiningComplexTokensState();
360    
361                    parsePrefixExpression();
362                    expression.done(PREFIX_EXPRESSION);
363                }
364                else {
365                    myBuilder.restoreJoiningComplexTokensState();
366                    parsePostfixExpression();
367                }
368            }
369        }
370    
371        /*
372         * callableReference
373         *   : (userType "?"*)? "::" SimpleName
374         *   ;
375         */
376        private boolean parseDoubleColonExpression() {
377            PsiBuilder.Marker expression = mark();
378    
379            if (!at(COLONCOLON)) {
380                PsiBuilder.Marker typeReference = mark();
381                myJetParsing.parseUserType();
382                typeReference = myJetParsing.parseNullableTypeSuffix(typeReference);
383                typeReference.done(TYPE_REFERENCE);
384    
385                if (!at(COLONCOLON)) {
386                    expression.rollbackTo();
387                    return false;
388                }
389            }
390    
391            advance(); // COLONCOLON
392    
393            if (at(CLASS_KEYWORD)) {
394                advance(); // CLASS_KEYWORD
395                expression.done(CLASS_LITERAL_EXPRESSION);
396            }
397            else {
398                parseSimpleNameExpression();
399                expression.done(CALLABLE_REFERENCE_EXPRESSION);
400            }
401    
402            return true;
403        }
404    
405        /*
406         * postfixUnaryExpression
407         *   : atomicExpression postfixUnaryOperation*
408         *   : callableReference postfixUnaryOperation*
409         *   ;
410         *
411         * postfixUnaryOperation
412         *   : "++" : "--" : "!!"
413         *   : typeArguments? valueArguments (getEntryPoint? functionLiteral)
414         *   : typeArguments (getEntryPoint? functionLiteral)
415         *   : arrayAccess
416         *   : memberAccessOperation postfixUnaryExpression // TODO: Review
417         *   ;
418         */
419        private void parsePostfixExpression() {
420            PsiBuilder.Marker expression = mark();
421    
422            boolean firstExpressionParsed;
423            boolean doubleColonExpression = parseDoubleColonExpression();
424            if (!doubleColonExpression) {
425                firstExpressionParsed = parseAtomicExpression();
426            }
427            else {
428                firstExpressionParsed = true;
429            }
430    
431            while (true) {
432                if (interruptedWithNewLine()) {
433                    break;
434                }
435                else if (at(LBRACKET)) {
436                    parseArrayAccess();
437                    expression.done(ARRAY_ACCESS_EXPRESSION);
438                }
439                else if (!doubleColonExpression && parseCallSuffix()) {
440                    expression.done(CALL_EXPRESSION);
441                }
442                else if (at(DOT) || at(SAFE_ACCESS)) {
443                    IElementType expressionType = at(DOT) ? DOT_QUALIFIED_EXPRESSION : SAFE_ACCESS_EXPRESSION;
444                    advance(); // DOT or SAFE_ACCESS
445    
446                    if (!firstExpressionParsed) {
447                        expression.drop();
448                        expression = mark();
449                    }
450    
451                    parseCallExpression();
452    
453                    if (firstExpressionParsed) {
454                        expression.done(expressionType);
455                    }
456                    else {
457                        firstExpressionParsed = true;
458                        continue;
459                    }
460                }
461                else if (atSet(Precedence.POSTFIX.getOperations())) {
462                    parseOperationReference();
463                    expression.done(POSTFIX_EXPRESSION);
464                }
465                else {
466                    break;
467                }
468                expression = expression.precede();
469            }
470            expression.drop();
471        }
472    
473        /*
474         * callSuffix
475         *   : typeArguments? valueArguments annotatedLambda
476         *   : typeArguments annotatedLambda
477         *   ;
478         */
479        private boolean parseCallSuffix() {
480            if (parseCallWithClosure()) {
481                // do nothing
482            }
483            else if (at(LPAR)) {
484                parseValueArgumentList();
485                parseCallWithClosure();
486            }
487            else if (at(LT)) {
488                PsiBuilder.Marker typeArgumentList = mark();
489                if (myJetParsing.tryParseTypeArgumentList(TYPE_ARGUMENT_LIST_STOPPERS)) {
490                    typeArgumentList.done(TYPE_ARGUMENT_LIST);
491                    if (!myBuilder.newlineBeforeCurrentToken() && at(LPAR)) parseValueArgumentList();
492                    parseCallWithClosure();
493                }
494                else {
495                    typeArgumentList.rollbackTo();
496                    return false;
497                }
498            }
499            else {
500                return false;
501            }
502    
503            return true;
504        }
505    
506        /*
507         * atomicExpression typeParameters? valueParameters? functionLiteral*
508         */
509        private void parseCallExpression() {
510            PsiBuilder.Marker mark = mark();
511            parseAtomicExpression();
512            if (!myBuilder.newlineBeforeCurrentToken() && parseCallSuffix()) {
513                mark.done(CALL_EXPRESSION);
514            }
515            else {
516                mark.drop();
517            }
518        }
519    
520        private void parseOperationReference() {
521            PsiBuilder.Marker operationReference = mark();
522            advance(); // operation
523            operationReference.done(OPERATION_REFERENCE);
524        }
525    
526        /*
527         * annotatedLambda*
528         */
529        protected boolean parseCallWithClosure() {
530            boolean success = false;
531    
532            while (true) {
533                PsiBuilder.Marker argument = mark();
534    
535                if (!parseAnnotatedLambda(/* preferBlock = */false)) {
536                    argument.drop();
537                    break;
538                }
539    
540                argument.done(FUNCTION_LITERAL_ARGUMENT);
541                success = true;
542            }
543    
544            return success;
545        }
546    
547        /*
548         * annotatedLambda
549         *  : ("@" annotationEntry)* labelDefinition? functionLiteral
550         */
551        private boolean parseAnnotatedLambda(boolean preferBlock) {
552            PsiBuilder.Marker annotated = mark();
553    
554            boolean wereAnnotations = myJetParsing.parseAnnotations(ONLY_ESCAPED_REGULAR_ANNOTATIONS);
555            PsiBuilder.Marker labeled = mark();
556    
557            boolean wasLabel = isAtLabelDefinitionOrMissingIdentifier();
558            if (wasLabel) {
559                parseLabelDefinition();
560            }
561    
562            if (!at(LBRACE)) {
563                annotated.rollbackTo();
564                return false;
565            }
566    
567            parseFunctionLiteral(preferBlock);
568    
569            doneOrDrop(labeled, LABELED_EXPRESSION, wasLabel);
570            doneOrDrop(annotated, ANNOTATED_EXPRESSION, wereAnnotations);
571    
572            return true;
573        }
574    
575        private static void doneOrDrop(
576                @NotNull PsiBuilder.Marker marker,
577                @NotNull IElementType type,
578                boolean condition
579        ) {
580            if (condition) {
581                marker.done(type);
582            }
583            else {
584                marker.drop();
585            }
586        }
587    
588        private boolean isAtLabelDefinitionBeforeLBrace() {
589            if (at(IDENTIFIER)) {
590                if (myBuilder.rawLookup(1) != AT) return false;
591                return lookahead(2) == LBRACE;
592            }
593    
594            return at(AT) && lookahead(1) == LBRACE;
595        }
596    
597        private boolean isAtLabelDefinitionOrMissingIdentifier() {
598            return (at(IDENTIFIER) && myBuilder.rawLookup(1) == AT) || at(AT);
599        }
600    
601        /*
602         * atomicExpression
603         *   : "this" label?
604         *   : "super" ("<" type ">")? label?
605         *   : objectLiteral
606         *   : jump
607         *   : if
608         *   : when
609         *   : try
610         *   : loop
611         *   : literalConstant
612         *   : functionLiteral
613         *   : declaration
614         *   : SimpleName
615         *   : "package" // for the root package
616         *   ;
617         */
618        private boolean parseAtomicExpression() {
619            //        System.out.println("atom at "  + myBuilder.getTokenText());
620    
621            boolean ok = true;
622    
623            if (at(LPAR)) {
624                parseParenthesizedExpression();
625            }
626            else if (at(PACKAGE_KEYWORD)) {
627                parseOneTokenExpression(ROOT_PACKAGE);
628            }
629            else if (at(THIS_KEYWORD)) {
630                parseThisExpression();
631            }
632            else if (at(SUPER_KEYWORD)) {
633                parseSuperExpression();
634            }
635            else if (at(OBJECT_KEYWORD)) {
636                parseObjectLiteral();
637            }
638            else if (at(THROW_KEYWORD)) {
639                parseThrow();
640            }
641            else if (at(RETURN_KEYWORD)) {
642                parseReturn();
643            }
644            else if (at(CONTINUE_KEYWORD)) {
645                parseJump(CONTINUE);
646            }
647            else if (at(BREAK_KEYWORD)) {
648                parseJump(BREAK);
649            }
650            else if (at(IF_KEYWORD)) {
651                parseIf();
652            }
653            else if (at(WHEN_KEYWORD)) {
654                parseWhen();
655            }
656            else if (at(TRY_KEYWORD)) {
657                parseTry();
658            }
659            else if (at(FOR_KEYWORD)) {
660                parseFor();
661            }
662            else if (at(WHILE_KEYWORD)) {
663                parseWhile();
664            }
665            else if (at(DO_KEYWORD)) {
666                parseDoWhile();
667            }
668            else if (atSet(CLASS_KEYWORD, FUN_KEYWORD, VAL_KEYWORD,
669                           VAR_KEYWORD, TYPE_ALIAS_KEYWORD)) {
670                parseLocalDeclaration();
671            }
672            else if (at(FIELD_IDENTIFIER)) {
673                parseSimpleNameExpression();
674            }
675            else if (at(IDENTIFIER)) {
676                parseSimpleNameExpression();
677            }
678            else if (at(LBRACE)) {
679                parseFunctionLiteral();
680            }
681            else if (at(OPEN_QUOTE)) {
682                parseStringTemplate();
683            }
684            else if (!parseLiteralConstant()) {
685                ok = false;
686                // TODO: better recovery if FIRST(element) did not match
687                errorWithRecovery("Expecting an element", EXPRESSION_FOLLOW);
688            }
689    
690            return ok;
691        }
692    
693        /*
694         * stringTemplate
695         *   : OPEN_QUOTE stringTemplateElement* CLOSING_QUOTE
696         *   ;
697         */
698        private void parseStringTemplate() {
699            assert _at(OPEN_QUOTE);
700    
701            PsiBuilder.Marker template = mark();
702    
703            advance(); // OPEN_QUOTE
704    
705            while (!eof()) {
706                if (at(CLOSING_QUOTE) || at(DANGLING_NEWLINE)) {
707                    break;
708                }
709                parseStringTemplateElement();
710            }
711    
712            if (at(DANGLING_NEWLINE)) {
713                errorAndAdvance("Expecting '\"'");
714            }
715            else {
716                expect(CLOSING_QUOTE, "Expecting '\"'");
717            }
718            template.done(STRING_TEMPLATE);
719        }
720    
721        /*
722         * stringTemplateElement
723         *   : RegularStringPart
724         *   : ShortTemplateEntrySTART (SimpleName | "this")
725         *   : EscapeSequence
726         *   : longTemplate
727         *   ;
728         *
729         * longTemplate
730         *   : "${" expression "}"
731         *   ;
732         */
733        private void parseStringTemplateElement() {
734            if (at(REGULAR_STRING_PART)) {
735                PsiBuilder.Marker mark = mark();
736                advance(); // REGULAR_STRING_PART
737                mark.done(LITERAL_STRING_TEMPLATE_ENTRY);
738            }
739            else if (at(ESCAPE_SEQUENCE)) {
740                PsiBuilder.Marker mark = mark();
741                advance(); // ESCAPE_SEQUENCE
742                mark.done(ESCAPE_STRING_TEMPLATE_ENTRY);
743            }
744            else if (at(SHORT_TEMPLATE_ENTRY_START)) {
745                PsiBuilder.Marker entry = mark();
746                advance(); // SHORT_TEMPLATE_ENTRY_START
747    
748                if (at(THIS_KEYWORD)) {
749                    PsiBuilder.Marker thisExpression = mark();
750                    PsiBuilder.Marker reference = mark();
751                    advance(); // THIS_KEYWORD
752                    reference.done(REFERENCE_EXPRESSION);
753                    thisExpression.done(THIS_EXPRESSION);
754                }
755                else {
756                    JetToken keyword = KEYWORD_TEXTS.get(myBuilder.getTokenText());
757                    if (keyword != null) {
758                        myBuilder.remapCurrentToken(keyword);
759                        errorAndAdvance("Keyword cannot be used as a reference");
760                    }
761                    else {
762                        PsiBuilder.Marker reference = mark();
763                        expect(IDENTIFIER, "Expecting a name");
764                        reference.done(REFERENCE_EXPRESSION);
765                    }
766                }
767    
768                entry.done(SHORT_STRING_TEMPLATE_ENTRY);
769            }
770            else if (at(LONG_TEMPLATE_ENTRY_START)) {
771                PsiBuilder.Marker longTemplateEntry = mark();
772    
773                advance(); // LONG_TEMPLATE_ENTRY_START
774    
775                parseExpression();
776    
777                expect(LONG_TEMPLATE_ENTRY_END, "Expecting '}'", TokenSet.create(CLOSING_QUOTE, DANGLING_NEWLINE, REGULAR_STRING_PART, ESCAPE_SEQUENCE, SHORT_TEMPLATE_ENTRY_START));
778                longTemplateEntry.done(LONG_STRING_TEMPLATE_ENTRY);
779            }
780            else {
781                errorAndAdvance("Unexpected token in a string template");
782            }
783        }
784    
785        /*
786         * literalConstant
787         *   : "true" | "false"
788         *   : stringTemplate
789         *   : NoEscapeString
790         *   : IntegerLiteral
791         *   : LongLiteral
792         *   : CharacterLiteral
793         *   : FloatLiteral
794         *   : "null"
795         *   ;
796         */
797        private boolean parseLiteralConstant() {
798            if (at(TRUE_KEYWORD) || at(FALSE_KEYWORD)) {
799                parseOneTokenExpression(BOOLEAN_CONSTANT);
800            }
801            else if (at(INTEGER_LITERAL)) {
802                parseOneTokenExpression(INTEGER_CONSTANT);
803            }
804            else if (at(CHARACTER_LITERAL)) {
805                parseOneTokenExpression(CHARACTER_CONSTANT);
806            }
807            else if (at(FLOAT_LITERAL)) {
808                parseOneTokenExpression(FLOAT_CONSTANT);
809            }
810            else if (at(NULL_KEYWORD)) {
811                parseOneTokenExpression(NULL);
812            }
813            else {
814                return false;
815            }
816            return true;
817        }
818    
819        /*
820         * when
821         *   : "when" ("(" (modifiers "val" SimpleName "=")? element ")")? "{"
822         *         whenEntry*
823         *     "}"
824         *   ;
825         */
826        private void parseWhen() {
827            assert _at(WHEN_KEYWORD);
828    
829            PsiBuilder.Marker when = mark();
830    
831            advance(); // WHEN_KEYWORD
832    
833            // Parse condition
834            myBuilder.disableNewlines();
835            if (at(LPAR)) {
836                advanceAt(LPAR);
837    
838                int valPos = matchTokenStreamPredicate(new FirstBefore(new At(VAL_KEYWORD), new AtSet(RPAR, LBRACE, RBRACE, SEMICOLON, EQ)));
839                if (valPos >= 0) {
840                    PsiBuilder.Marker property = mark();
841                    myJetParsing.parseModifierList(ALLOW_UNESCAPED_REGULAR_ANNOTATIONS);
842                    myJetParsing.parseProperty(true);
843                    property.done(PROPERTY);
844                }
845                else {
846                    parseExpression();
847                }
848    
849                expect(RPAR, "Expecting ')'");
850            }
851            myBuilder.restoreNewlinesState();
852    
853            // Parse when block
854            myBuilder.enableNewlines();
855            if (expect(LBRACE, "Expecting '{'")) {
856                while (!eof() && !at(RBRACE)) {
857                    parseWhenEntry();
858                }
859    
860                expect(RBRACE, "Expecting '}'");
861            }
862            myBuilder.restoreNewlinesState();
863    
864            when.done(WHEN);
865        }
866    
867        /*
868         * whenEntry
869         *   // TODO : consider empty after ->
870         *   : whenCondition{","} "->" element SEMI
871         *   : "else" "->" element SEMI
872         *   ;
873         */
874        private void parseWhenEntry() {
875            PsiBuilder.Marker entry = mark();
876    
877            if (at(ELSE_KEYWORD)) {
878                advance(); // ELSE_KEYWORD
879    
880                if (!at(ARROW)) {
881                    errorUntil("Expecting '->'", TokenSet.create(ARROW, LBRACE, RBRACE, EOL_OR_SEMICOLON));
882                }
883    
884                if (at(ARROW)) {
885                    advance(); // ARROW
886    
887                    if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
888                        error("Expecting an element");
889                    }
890                    else {
891                        parseExpressionPreferringBlocks();
892                    }
893                }
894                else if (at(LBRACE)) { // no arrow, probably it's simply missing
895                    parseExpressionPreferringBlocks();
896                }
897                else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) {
898                    errorAndAdvance("Expecting '->'");
899                }
900            }
901            else {
902                parseWhenEntryNotElse();
903            }
904    
905            entry.done(WHEN_ENTRY);
906            consumeIf(SEMICOLON);
907        }
908    
909        /*
910         * : whenCondition{","} "->" element SEMI
911         */
912        private void parseWhenEntryNotElse() {
913            while (true) {
914                while (at(COMMA)) errorAndAdvance("Expecting a when-condition");
915                parseWhenCondition();
916                if (!at(COMMA)) break;
917                advance(); // COMMA
918            }
919    
920            expect(ARROW, "Expecting '->'", WHEN_CONDITION_RECOVERY_SET);
921            if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
922                error("Expecting an element");
923            }
924            else {
925                parseExpressionPreferringBlocks();
926            }
927            // SEMI is consumed in parseWhenEntry
928        }
929    
930        /*
931         * whenCondition
932         *   : expression
933         *   : ("in" | "!in") expression
934         *   : ("is" | "!is") isRHS
935         *   ;
936         */
937        private void parseWhenCondition() {
938            PsiBuilder.Marker condition = mark();
939            myBuilder.disableNewlines();
940            if (at(IN_KEYWORD) || at(NOT_IN)) {
941                PsiBuilder.Marker mark = mark();
942                advance(); // IN_KEYWORD or NOT_IN
943                mark.done(OPERATION_REFERENCE);
944    
945    
946                if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) {
947                    error("Expecting an element");
948                }
949                else {
950                    parseExpression();
951                }
952                condition.done(WHEN_CONDITION_IN_RANGE);
953            }
954            else if (at(IS_KEYWORD) || at(NOT_IS)) {
955                advance(); // IS_KEYWORD or NOT_IS
956    
957                if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) {
958                    error("Expecting a type");
959                }
960                else {
961                    myJetParsing.parseTypeRef();
962                }
963                condition.done(WHEN_CONDITION_IS_PATTERN);
964            }
965            else {
966                if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) {
967                    error("Expecting an expression, is-condition or in-condition");
968                }
969                else {
970                    parseExpression();
971                }
972                condition.done(WHEN_CONDITION_EXPRESSION);
973            }
974            myBuilder.restoreNewlinesState();
975        }
976    
977        /*
978         * arrayAccess
979         *   : "[" element{","} "]"
980         *   ;
981         */
982        private void parseArrayAccess() {
983            assert _at(LBRACKET);
984    
985            PsiBuilder.Marker indices = mark();
986    
987            myBuilder.disableNewlines();
988            advance(); // LBRACKET
989    
990            while (true) {
991                if (at(COMMA)) errorAndAdvance("Expecting an index element");
992                if (at(RBRACKET)) {
993                    error("Expecting an index element");
994                    break;
995                }
996                parseExpression();
997                if (!at(COMMA)) break;
998                advance(); // COMMA
999            }
1000    
1001            expect(RBRACKET, "Expecting ']'");
1002            myBuilder.restoreNewlinesState();
1003    
1004            indices.done(INDICES);
1005        }
1006    
1007        /*
1008         * SimpleName
1009         */
1010        public void parseSimpleNameExpression() {
1011            PsiBuilder.Marker simpleName = mark();
1012            if (at(FIELD_IDENTIFIER)) {
1013                advance(); //
1014            }
1015            else {
1016                expect(IDENTIFIER, "Expecting an identifier");
1017            }
1018            simpleName.done(REFERENCE_EXPRESSION);
1019        }
1020    
1021        /*
1022         * modifiers declarationRest
1023         */
1024        private boolean parseLocalDeclaration() {
1025            PsiBuilder.Marker decl = mark();
1026            JetParsing.ModifierDetector detector = new JetParsing.ModifierDetector();
1027            myJetParsing.parseModifierList(detector, ONLY_ESCAPED_REGULAR_ANNOTATIONS);
1028    
1029            IElementType declType = parseLocalDeclarationRest(detector.isEnumDetected());
1030    
1031            if (declType != null) {
1032                // we do not attach preceding comments (non-doc) to local variables because they are likely commenting a few statements below
1033                closeDeclarationWithCommentBinders(decl, declType,
1034                                                   declType != JetNodeTypes.PROPERTY && declType != JetNodeTypes.MULTI_VARIABLE_DECLARATION);
1035                return true;
1036            }
1037            else {
1038                decl.rollbackTo();
1039                return false;
1040            }
1041        }
1042    
1043        /*
1044         * functionLiteral  // one can use "it" as a parameter name
1045         *   : "{" expressions "}"
1046         *   : "{" (modifiers SimpleName){","} "->" statements "}"
1047         *   ;
1048         */
1049        private void parseFunctionLiteral() {
1050            parseFunctionLiteral(/* preferBlock = */false);
1051        }
1052    
1053        private void parseFunctionLiteral(boolean preferBlock) {
1054            assert _at(LBRACE);
1055    
1056            PsiBuilder.Marker literalExpression = mark();
1057    
1058            PsiBuilder.Marker literal = mark();
1059    
1060            myBuilder.enableNewlines();
1061            advance(); // LBRACE
1062    
1063            boolean paramsFound = false;
1064    
1065            if (at(ARROW)) {
1066                //   { -> ...}
1067                mark().done(VALUE_PARAMETER_LIST);
1068                advance(); // ARROW
1069                paramsFound = true;
1070            }
1071            else {
1072                if (at(IDENTIFIER) || at(COLON)) {
1073                    // Try to parse a simple name list followed by an ARROW
1074                    //   {a -> ...}
1075                    //   {a, b -> ...}
1076                    PsiBuilder.Marker rollbackMarker = mark();
1077                    boolean preferParamsToExpressions = (lookahead(1) == COMMA);
1078                    parseFunctionLiteralShorthandParameterList();
1079    
1080                    paramsFound = preferParamsToExpressions ?
1081                                  rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
1082                                  rollbackOrDropAt(rollbackMarker, ARROW);
1083                }
1084            }
1085    
1086            if (!paramsFound) {
1087                if (preferBlock) {
1088                    literal.drop();
1089                    parseStatements();
1090                    expect(RBRACE, "Expecting '}'");
1091                    literalExpression.done(BLOCK);
1092                    myBuilder.restoreNewlinesState();
1093    
1094                    return;
1095                }
1096            }
1097    
1098            PsiBuilder.Marker body = mark();
1099            parseStatements();
1100            body.done(BLOCK);
1101    
1102            expect(RBRACE, "Expecting '}'");
1103            myBuilder.restoreNewlinesState();
1104    
1105            literal.done(FUNCTION_LITERAL);
1106            literalExpression.done(FUNCTION_LITERAL_EXPRESSION);
1107        }
1108    
1109        private boolean rollbackOrDropAt(PsiBuilder.Marker rollbackMarker, IElementType dropAt) {
1110            if (at(dropAt)) {
1111                advance(); // dropAt
1112                rollbackMarker.drop();
1113                return true;
1114            }
1115            rollbackMarker.rollbackTo();
1116            return false;
1117        }
1118    
1119        private boolean rollbackOrDrop(PsiBuilder.Marker rollbackMarker,
1120                JetToken expected, String expectMessage,
1121                IElementType validForDrop) {
1122            if (at(expected)) {
1123                advance(); // dropAt
1124                rollbackMarker.drop();
1125                return true;
1126            }
1127            else if (at(validForDrop)) {
1128                rollbackMarker.drop();
1129                expect(expected, expectMessage);
1130                return true;
1131            }
1132    
1133            rollbackMarker.rollbackTo();
1134            return false;
1135        }
1136    
1137    
1138        /*
1139         * SimpleName{,}
1140         */
1141        private void parseFunctionLiteralShorthandParameterList() {
1142            PsiBuilder.Marker parameterList = mark();
1143    
1144            while (!eof()) {
1145                PsiBuilder.Marker parameter = mark();
1146    
1147                //            int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos)));
1148                //            createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false);
1149    
1150                if (at(COLON)) {
1151                    error("Expecting parameter name");
1152                }
1153                else {
1154                    expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW));
1155                }
1156    
1157                if (at(COLON)) {
1158                    advance(); // COLON
1159                    myJetParsing.parseTypeRef(TokenSet.create(ARROW, COMMA));
1160                }
1161                parameter.done(VALUE_PARAMETER);
1162    
1163                if (at(ARROW)) {
1164                    break;
1165                }
1166                else if (at(COMMA)) {
1167                    advance(); // COMMA
1168                }
1169                else {
1170                    error("Expecting '->' or ','");
1171                    break;
1172                }
1173            }
1174    
1175            parameterList.done(VALUE_PARAMETER_LIST);
1176        }
1177    
1178        /*
1179         * expressions
1180         *   : SEMI* statement{SEMI+} SEMI*
1181         */
1182        public void parseStatements() {
1183            while (at(SEMICOLON)) advance(); // SEMICOLON
1184            while (!eof() && !at(RBRACE)) {
1185                if (!atSet(STATEMENT_FIRST)) {
1186                    errorAndAdvance("Expecting an element");
1187                }
1188                if (atSet(STATEMENT_FIRST)) {
1189                    parseStatement();
1190                }
1191                if (at(SEMICOLON)) {
1192                    while (at(SEMICOLON)) advance(); // SEMICOLON
1193                }
1194                else if (at(RBRACE)) {
1195                    break;
1196                }
1197                else if (!myBuilder.newlineBeforeCurrentToken()) {
1198                    String severalStatementsError = "Unexpected tokens (use ';' to separate expressions on the same line)";
1199    
1200                    if (atSet(STATEMENT_NEW_LINE_QUICK_RECOVERY_SET)) {
1201                        error(severalStatementsError);
1202                    }
1203                    else {
1204                        errorUntil(severalStatementsError, TokenSet.create(EOL_OR_SEMICOLON, LBRACE, RBRACE));
1205                    }
1206                }
1207            }
1208        }
1209    
1210        /*
1211         * statement
1212         *  : expression
1213         *  : declaration
1214         *  ;
1215         */
1216        private void parseStatement() {
1217            if (!parseLocalDeclaration()) {
1218                if (!atSet(EXPRESSION_FIRST)) {
1219                    errorAndAdvance("Expecting a statement");
1220                }
1221                else {
1222                    parseExpression();
1223                }
1224            }
1225        }
1226    
1227        /*
1228         * declaration
1229         *   : function
1230         *   : property
1231         *   : extension
1232         *   : class
1233         *   : typeAlias
1234         *   : object
1235         *   ;
1236         */
1237        private IElementType parseLocalDeclarationRest(boolean isEnum) {
1238            IElementType keywordToken = tt();
1239            IElementType declType = null;
1240            if (keywordToken == CLASS_KEYWORD ||  keywordToken == INTERFACE_KEYWORD) {
1241                declType = myJetParsing.parseClass(isEnum, LOCAL);
1242            }
1243            else if (keywordToken == FUN_KEYWORD) {
1244                declType = myJetParsing.parseFunction();
1245            }
1246            else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) {
1247                declType = myJetParsing.parseProperty(true);
1248            }
1249            else if (keywordToken == TYPE_ALIAS_KEYWORD) {
1250                declType = myJetParsing.parseTypeAlias();
1251            }
1252            else if (keywordToken == OBJECT_KEYWORD) {
1253                // Object expression may appear at the statement position: should parse it
1254                // as expression instead of object declaration
1255                // sample:
1256                // {
1257                //   object : Thread() {
1258                //   }
1259                // }
1260                IElementType lookahead = lookahead(1);
1261                if (lookahead == COLON || lookahead == LBRACE) {
1262                    return null;
1263                }
1264    
1265                myJetParsing.parseObject(NameParsingMode.REQUIRED, true, LOCAL);
1266                declType = OBJECT_DECLARATION;
1267            }
1268            return declType;
1269        }
1270    
1271        /*
1272         * doWhile
1273         *   : "do" element "while" "(" element ")"
1274         *   ;
1275         */
1276        private void parseDoWhile() {
1277            assert _at(DO_KEYWORD);
1278    
1279            PsiBuilder.Marker loop = mark();
1280    
1281            advance(); // DO_KEYWORD
1282    
1283            if (!at(WHILE_KEYWORD)) {
1284                parseControlStructureBody();
1285            }
1286    
1287            if (expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition")) {
1288                parseCondition();
1289            }
1290    
1291            loop.done(DO_WHILE);
1292        }
1293    
1294        /*
1295         * while
1296         *   : "while" "(" element ")" element
1297         *   ;
1298         */
1299        private void parseWhile() {
1300            assert _at(WHILE_KEYWORD);
1301    
1302            PsiBuilder.Marker loop = mark();
1303    
1304            advance(); // WHILE_KEYWORD
1305    
1306            parseCondition();
1307    
1308            parseControlStructureBody();
1309    
1310            loop.done(WHILE);
1311        }
1312    
1313        /*
1314         * for
1315         *   : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression
1316         *   ;
1317         *
1318         *   TODO: empty loop body (at the end of the block)?
1319         */
1320        private void parseFor() {
1321            assert _at(FOR_KEYWORD);
1322    
1323            PsiBuilder.Marker loop = mark();
1324    
1325            advance(); // FOR_KEYWORD
1326    
1327            if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) {
1328                myBuilder.disableNewlines();
1329    
1330                if (!at(RPAR)) {
1331                    PsiBuilder.Marker parameter = mark();
1332    
1333                    if (!at(IN_KEYWORD)) {
1334                        myJetParsing.parseModifierListWithUnescapedAnnotations(
1335                                TokenSet.create(IDENTIFIER, LPAR), TokenSet.create(IN_KEYWORD, RPAR, COLON)
1336                        );
1337                    }
1338    
1339                    if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
1340    
1341                    if (at(LPAR)) {
1342                        myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
1343                        parameter.done(MULTI_VARIABLE_DECLARATION);
1344                    }
1345                    else {
1346                        expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD));
1347    
1348                        if (at(COLON)) {
1349                            advance(); // COLON
1350                            myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
1351                        }
1352                        parameter.done(VALUE_PARAMETER);
1353                    }
1354    
1355                    if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) {
1356                        PsiBuilder.Marker range = mark();
1357                        parseExpression();
1358                        range.done(LOOP_RANGE);
1359                    }
1360                }
1361                else {
1362                    error("Expecting a variable name");
1363                }
1364    
1365                expectNoAdvance(RPAR, "Expecting ')'");
1366                myBuilder.restoreNewlinesState();
1367            }
1368    
1369            parseControlStructureBody();
1370    
1371            loop.done(FOR);
1372        }
1373    
1374        /**
1375         * If it has no ->, it's a block, otherwise a function literal
1376         */
1377        private void parseExpressionPreferringBlocks() {
1378            if (!parseAnnotatedLambda(/* preferBlock = */true)) {
1379                parseExpression();
1380            }
1381        }
1382    
1383        /*
1384         * element
1385         */
1386        private void parseControlStructureBody() {
1387            PsiBuilder.Marker body = mark();
1388            if (!at(SEMICOLON)) {
1389                parseExpressionPreferringBlocks();
1390            }
1391            body.done(BODY);
1392        }
1393    
1394        /*
1395         * try
1396         *   : "try" block catchBlock* finallyBlock?
1397         *   ;
1398         * catchBlock
1399         *   : "catch" "(" annotations SimpleName ":" userType ")" block
1400         *   ;
1401         *
1402         * finallyBlock
1403         *   : "finally" block
1404         *   ;
1405         */
1406        private void parseTry() {
1407            assert _at(TRY_KEYWORD);
1408    
1409            PsiBuilder.Marker tryExpression = mark();
1410    
1411            advance(); // TRY_KEYWORD
1412    
1413            myJetParsing.parseBlock();
1414    
1415            boolean catchOrFinally = false;
1416            while (at(CATCH_KEYWORD)) {
1417                catchOrFinally = true;
1418                PsiBuilder.Marker catchBlock = mark();
1419                advance(); // CATCH_KEYWORD
1420    
1421                TokenSet recoverySet = TokenSet.create(LBRACE, RBRACE, FINALLY_KEYWORD, CATCH_KEYWORD);
1422                if (atSet(recoverySet)) {
1423                    error("Expecting exception variable declaration");
1424                }
1425                else {
1426                    PsiBuilder.Marker parameters = mark();
1427                    expect(LPAR, "Expecting '('", recoverySet);
1428                    if (!atSet(recoverySet)) {
1429                        myJetParsing.parseValueParameter(/*typeRequired = */ true);
1430                        expect(RPAR, "Expecting ')'", recoverySet);
1431                    }
1432                    else {
1433                        error("Expecting exception variable declaration");
1434                    }
1435                    parameters.done(VALUE_PARAMETER_LIST);
1436                }
1437    
1438                if (at(LBRACE)) {
1439                    myJetParsing.parseBlock();
1440                }
1441                else {
1442                    error("Expecting a block: { ... }");
1443                }
1444                catchBlock.done(CATCH);
1445            }
1446    
1447            if (at(FINALLY_KEYWORD)) {
1448                catchOrFinally = true;
1449                PsiBuilder.Marker finallyBlock = mark();
1450    
1451                advance(); // FINALLY_KEYWORD
1452    
1453                myJetParsing.parseBlock();
1454    
1455                finallyBlock.done(FINALLY);
1456            }
1457    
1458            if (!catchOrFinally) {
1459                error("Expecting 'catch' or 'finally'");
1460            }
1461    
1462            tryExpression.done(TRY);
1463        }
1464    
1465        /*
1466         * if
1467         *   : "if" "(" element ")" element SEMI? ("else" element)?
1468         *   ;
1469         */
1470        private void parseIf() {
1471            assert _at(IF_KEYWORD);
1472    
1473            PsiBuilder.Marker marker = mark();
1474    
1475            advance(); //IF_KEYWORD
1476    
1477            parseCondition();
1478    
1479            PsiBuilder.Marker thenBranch = mark();
1480            if (!at(ELSE_KEYWORD) && !at(SEMICOLON)) {
1481                parseExpressionPreferringBlocks();
1482            }
1483            if (at(SEMICOLON) && lookahead(1) == ELSE_KEYWORD) {
1484                advance(); // SEMICOLON
1485            }
1486            thenBranch.done(THEN);
1487    
1488            if (at(ELSE_KEYWORD)) {
1489                advance(); // ELSE_KEYWORD
1490    
1491                PsiBuilder.Marker elseBranch = mark();
1492                if (!at(SEMICOLON)) {
1493                    parseExpressionPreferringBlocks();
1494                }
1495                elseBranch.done(ELSE);
1496            }
1497    
1498            marker.done(IF);
1499        }
1500    
1501        /*
1502         * "(" element ")"
1503         */
1504        private void parseCondition() {
1505            myBuilder.disableNewlines();
1506    
1507            if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) {
1508                PsiBuilder.Marker condition = mark();
1509                parseExpression();
1510                condition.done(CONDITION);
1511                expect(RPAR, "Expecting ')");
1512            }
1513    
1514            myBuilder.restoreNewlinesState();
1515        }
1516    
1517        /*
1518         * : "continue" getEntryPoint?
1519         * : "break" getEntryPoint?
1520         */
1521        private void parseJump(JetNodeType type) {
1522            assert _at(BREAK_KEYWORD) || _at(CONTINUE_KEYWORD);
1523    
1524            PsiBuilder.Marker marker = mark();
1525    
1526            advance(); // BREAK_KEYWORD or CONTINUE_KEYWORD
1527    
1528            parseLabelReferenceWithNoWhitespace();
1529    
1530            marker.done(type);
1531        }
1532    
1533        /*
1534         * "return" getEntryPoint? element?
1535         */
1536        private void parseReturn() {
1537            assert _at(RETURN_KEYWORD);
1538    
1539            PsiBuilder.Marker returnExpression = mark();
1540    
1541            advance(); // RETURN_KEYWORD
1542    
1543            parseLabelReferenceWithNoWhitespace();
1544    
1545            if (atSet(EXPRESSION_FIRST) && !at(EOL_OR_SEMICOLON)) parseExpression();
1546    
1547            returnExpression.done(RETURN);
1548        }
1549    
1550        /*
1551         * labelReference?
1552         */
1553        private void parseLabelReferenceWithNoWhitespace() {
1554            if (at(AT) && !myBuilder.newlineBeforeCurrentToken()) {
1555                if (WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(-1))) {
1556                    error("There should be no space or comments before '@' in label reference");
1557                }
1558                parseLabelReference();
1559            }
1560        }
1561    
1562        /*
1563         * IDENTIFIER "@"
1564         */
1565        private void parseLabelDefinition() {
1566            if (at(AT)) {
1567                // recovery for empty label identifier
1568                errorAndAdvance("Label must be named"); // AT
1569                return;
1570            }
1571    
1572            PsiBuilder.Marker labelWrap = mark();
1573            PsiBuilder.Marker mark = mark();
1574    
1575            assert _at(IDENTIFIER) && myBuilder.rawLookup(1) == AT : "Callers must check that current token is IDENTIFIER followed with '@'";
1576    
1577            advance(); // IDENTIFIER
1578            advance(); // AT
1579    
1580            mark.done(LABEL);
1581    
1582            labelWrap.done(LABEL_QUALIFIER);
1583        }
1584    
1585        /*
1586         * "@" IDENTIFIER
1587         */
1588        private void parseLabelReference() {
1589            assert _at(AT);
1590    
1591            PsiBuilder.Marker labelWrap = mark();
1592    
1593            PsiBuilder.Marker mark = mark();
1594    
1595            if (myBuilder.rawLookup(1) != IDENTIFIER) {
1596                errorAndAdvance("Label must be named"); // AT
1597                labelWrap.drop();
1598                mark.drop();
1599                return;
1600            }
1601    
1602            advance(); // AT
1603            advance(); // IDENTIFIER
1604    
1605            mark.done(LABEL);
1606    
1607            labelWrap.done(LABEL_QUALIFIER);
1608        }
1609    
1610        /*
1611         * : "throw" element
1612         */
1613        private void parseThrow() {
1614            assert _at(THROW_KEYWORD);
1615    
1616            PsiBuilder.Marker marker = mark();
1617    
1618            advance(); // THROW_KEYWORD
1619    
1620            parseExpression();
1621    
1622            marker.done(THROW);
1623        }
1624    
1625        /*
1626         * "(" expression ")"
1627         */
1628        private void parseParenthesizedExpression() {
1629            assert _at(LPAR);
1630    
1631            PsiBuilder.Marker mark = mark();
1632    
1633            myBuilder.disableNewlines();
1634            advance(); // LPAR
1635            if (at(RPAR)) {
1636                error("Expecting an expression");
1637            }
1638            else {
1639                parseExpression();
1640            }
1641    
1642            expect(RPAR, "Expecting ')'");
1643            myBuilder.restoreNewlinesState();
1644    
1645            mark.done(PARENTHESIZED);
1646        }
1647    
1648        /*
1649         * "this" label?
1650         */
1651        private void parseThisExpression() {
1652            assert _at(THIS_KEYWORD);
1653            PsiBuilder.Marker mark = mark();
1654    
1655            PsiBuilder.Marker thisReference = mark();
1656            advance(); // THIS_KEYWORD
1657            thisReference.done(REFERENCE_EXPRESSION);
1658    
1659            parseLabelReferenceWithNoWhitespace();
1660    
1661            mark.done(THIS_EXPRESSION);
1662        }
1663    
1664        /*
1665         * "this" ("<" type ">")? label?
1666         */
1667        private void parseSuperExpression() {
1668            assert _at(SUPER_KEYWORD);
1669            PsiBuilder.Marker mark = mark();
1670    
1671            PsiBuilder.Marker superReference = mark();
1672            advance(); // SUPER_KEYWORD
1673            superReference.done(REFERENCE_EXPRESSION);
1674    
1675            if (at(LT)) {
1676                // This may be "super < foo" or "super<foo>", thus the backtracking
1677                PsiBuilder.Marker supertype = mark();
1678    
1679                myBuilder.disableNewlines();
1680                advance(); // LT
1681    
1682                myJetParsing.parseTypeRef();
1683    
1684                if (at(GT)) {
1685                    advance(); // GT
1686                    supertype.drop();
1687                }
1688                else {
1689                    supertype.rollbackTo();
1690                }
1691                myBuilder.restoreNewlinesState();
1692            }
1693            parseLabelReferenceWithNoWhitespace();
1694    
1695            mark.done(SUPER_EXPRESSION);
1696        }
1697    
1698        /*
1699         * valueArguments
1700         *   : "(" (SimpleName "=")? "*"? element{","} ")"
1701         *   ;
1702         */
1703        public void parseValueArgumentList() {
1704            PsiBuilder.Marker list = mark();
1705    
1706            myBuilder.disableNewlines();
1707    
1708            if (expect(LPAR, "Expecting an argument list", EXPRESSION_FOLLOW)) {
1709                if (!at(RPAR)) {
1710                    while (true) {
1711                        while (at(COMMA)) errorAndAdvance("Expecting an argument");
1712                        parseValueArgument();
1713                        if (!at(COMMA)) break;
1714                        advance(); // COMMA
1715                        if (at(RPAR)) {
1716                            error("Expecting an argument");
1717                            break;
1718                        }
1719                    }
1720                }
1721    
1722                expect(RPAR, "Expecting ')'", EXPRESSION_FOLLOW);
1723            }
1724    
1725            myBuilder.restoreNewlinesState();
1726    
1727            list.done(VALUE_ARGUMENT_LIST);
1728        }
1729    
1730        /*
1731         * (SimpleName "=")? "*"? element
1732         */
1733        private void parseValueArgument() {
1734            PsiBuilder.Marker argument = mark();
1735            if (at(IDENTIFIER) && lookahead(1) == EQ) {
1736                PsiBuilder.Marker argName = mark();
1737                PsiBuilder.Marker reference = mark();
1738                advance(); // IDENTIFIER
1739                reference.done(REFERENCE_EXPRESSION);
1740                argName.done(VALUE_ARGUMENT_NAME);
1741                advance(); // EQ
1742            }
1743            if (at(MUL)) {
1744                advance(); // MUL
1745            }
1746            parseExpression();
1747            argument.done(VALUE_ARGUMENT);
1748        }
1749    
1750        /*
1751         * "object" (":" delegationSpecifier{","})? classBody // Cannot make class body optional: foo(object : F, A)
1752         */
1753        public void parseObjectLiteral() {
1754            PsiBuilder.Marker literal = mark();
1755            PsiBuilder.Marker declaration = mark();
1756            myJetParsing.parseObject(NameParsingMode.PROHIBITED, false, LOCAL); // Body is not optional because of foo(object : A, B)
1757            declaration.done(OBJECT_DECLARATION);
1758            literal.done(OBJECT_LITERAL);
1759        }
1760    
1761        private void parseOneTokenExpression(JetNodeType type) {
1762            PsiBuilder.Marker mark = mark();
1763            advance();
1764            mark.done(type);
1765        }
1766    
1767        @Override
1768        protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
1769            return myJetParsing.create(builder);
1770        }
1771    
1772        private boolean interruptedWithNewLine() {
1773            return !ALLOW_NEWLINE_OPERATIONS.contains(tt()) && myBuilder.newlineBeforeCurrentToken();
1774        }
1775    }