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