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