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