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