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                PsiBuilder.Marker argument = mark();
520                if (!at(LBRACE)) {
521                    assert _at(LABEL_IDENTIFIER);
522                    parseLabeledExpression();
523                }
524                else {
525                    parseFunctionLiteral();
526                }
527                argument.done(FUNCTION_LITERAL_ARGUMENT);
528                success = true;
529            }
530    
531            return success;
532        }
533    
534        /*
535         * atomicExpression
536         *   : tupleLiteral // or parenthesized element
537         *   : "this" label?
538         *   : "super" ("<" type ">")? label?
539         *   : objectLiteral
540         *   : jump
541         *   : if
542         *   : when
543         *   : try
544         *   : loop
545         *   : literalConstant
546         *   : functionLiteral
547         *   : declaration
548         *   : SimpleName
549         *   : "package" // for the root package
550         *   ;
551         */
552        private void parseAtomicExpression() {
553            //        System.out.println("atom at "  + myBuilder.getTokenText());
554    
555            if (at(LPAR)) {
556                parseParenthesizedExpression();
557            }
558            else if (at(HASH)) {
559                parseTupleExpression();
560            }
561            else if (at(PACKAGE_KEYWORD)) {
562                parseOneTokenExpression(ROOT_PACKAGE);
563            }
564            else if (at(THIS_KEYWORD)) {
565                parseThisExpression();
566            }
567            else if (at(SUPER_KEYWORD)) {
568                parseSuperExpression();
569            }
570            else if (at(OBJECT_KEYWORD)) {
571                parseObjectLiteral();
572            }
573            else if (at(THROW_KEYWORD)) {
574                parseThrow();
575            }
576            else if (at(RETURN_KEYWORD)) {
577                parseReturn();
578            }
579            else if (at(CONTINUE_KEYWORD)) {
580                parseJump(CONTINUE);
581            }
582            else if (at(BREAK_KEYWORD)) {
583                parseJump(BREAK);
584            }
585            else if (at(IF_KEYWORD)) {
586                parseIf();
587            }
588            else if (at(WHEN_KEYWORD)) {
589                parseWhen();
590            }
591            else if (at(TRY_KEYWORD)) {
592                parseTry();
593            }
594            else if (at(FOR_KEYWORD)) {
595                parseFor();
596            }
597            else if (at(WHILE_KEYWORD)) {
598                parseWhile();
599            }
600            else if (at(DO_KEYWORD)) {
601                parseDoWhile();
602            }
603            else if (atSet(CLASS_KEYWORD, FUN_KEYWORD, VAL_KEYWORD,
604                           VAR_KEYWORD, TYPE_KEYWORD)) {
605                parseLocalDeclaration();
606            }
607            else if (at(FIELD_IDENTIFIER)) {
608                parseSimpleNameExpression();
609            }
610            else if (at(IDENTIFIER)) {
611                parseSimpleNameExpression();
612            }
613            else if (at(LBRACE)) {
614                parseFunctionLiteral();
615            }
616            else if (at(OPEN_QUOTE)) {
617                parseStringTemplate();
618            }
619            else if (!parseLiteralConstant()) {
620                // TODO: better recovery if FIRST(element) did not match
621                errorWithRecovery("Expecting an element", EXPRESSION_FOLLOW);
622            }
623        }
624    
625        /*
626         * stringTemplate
627         *   : OPEN_QUOTE stringTemplateElement* CLOSING_QUOTE
628         *   ;
629         */
630        private void parseStringTemplate() {
631            assert _at(OPEN_QUOTE);
632    
633            PsiBuilder.Marker template = mark();
634    
635            advance(); // OPEN_QUOTE
636    
637            while (!eof()) {
638                if (at(CLOSING_QUOTE) || at(DANGLING_NEWLINE)) {
639                    break;
640                }
641                parseStringTemplateElement();
642            }
643    
644            if (at(DANGLING_NEWLINE)) {
645                errorAndAdvance("Expecting '\"'");
646            }
647            else {
648                expect(CLOSING_QUOTE, "Expecting '\"'");
649            }
650            template.done(STRING_TEMPLATE);
651        }
652    
653        /*
654         * stringTemplateElement
655         *   : RegularStringPart
656         *   : ShortTemplateEntrySTART (SimpleName | "this")
657         *   : EscapeSequence
658         *   : longTemplate
659         *   ;
660         *
661         * longTemplate
662         *   : "${" expression "}"
663         *   ;
664         */
665        private void parseStringTemplateElement() {
666            if (at(REGULAR_STRING_PART)) {
667                PsiBuilder.Marker mark = mark();
668                advance(); // REGULAR_STRING_PART
669                mark.done(LITERAL_STRING_TEMPLATE_ENTRY);
670            }
671            else if (at(ESCAPE_SEQUENCE)) {
672                PsiBuilder.Marker mark = mark();
673                advance(); // ESCAPE_SEQUENCE
674                mark.done(ESCAPE_STRING_TEMPLATE_ENTRY);
675            }
676            else if (at(SHORT_TEMPLATE_ENTRY_START)) {
677                PsiBuilder.Marker entry = mark();
678                advance(); // SHORT_TEMPLATE_ENTRY_START
679    
680                if (at(THIS_KEYWORD)) {
681                    PsiBuilder.Marker thisExpression = mark();
682                    PsiBuilder.Marker reference = mark();
683                    advance(); // THIS_KEYWORD
684                    reference.done(REFERENCE_EXPRESSION);
685                    thisExpression.done(THIS_EXPRESSION);
686                }
687                else {
688                    JetToken keyword = KEYWORD_TEXTS.get(myBuilder.getTokenText());
689                    if (keyword != null) {
690                        myBuilder.remapCurrentToken(keyword);
691                        errorAndAdvance("Keyword cannot be used as a reference");
692                    }
693                    else {
694                        PsiBuilder.Marker reference = mark();
695                        expect(IDENTIFIER, "Expecting a name");
696                        reference.done(REFERENCE_EXPRESSION);
697                    }
698                }
699    
700                entry.done(SHORT_STRING_TEMPLATE_ENTRY);
701            }
702            else if (at(LONG_TEMPLATE_ENTRY_START)) {
703                PsiBuilder.Marker longTemplateEntry = mark();
704    
705                advance(); // LONG_TEMPLATE_ENTRY_START
706    
707                parseExpression();
708    
709                expect(LONG_TEMPLATE_ENTRY_END, "Expecting '}'", TokenSet.create(CLOSING_QUOTE, DANGLING_NEWLINE, REGULAR_STRING_PART, ESCAPE_SEQUENCE, SHORT_TEMPLATE_ENTRY_START));
710                longTemplateEntry.done(LONG_STRING_TEMPLATE_ENTRY);
711            }
712            else {
713                errorAndAdvance("Unexpected token in a string template");
714            }
715        }
716    
717        /*
718         * literalConstant
719         *   : "true" | "false"
720         *   : StringWithTemplates
721         *   : NoEscapeString
722         *   : IntegerLiteral
723         *   : LongLiteral
724         *   : CharacterLiteral
725         *   : FloatLiteral
726         *   : "null"
727         *   ;
728         */
729        private boolean parseLiteralConstant() {
730            if (at(TRUE_KEYWORD) || at(FALSE_KEYWORD)) {
731                parseOneTokenExpression(BOOLEAN_CONSTANT);
732            }
733            else if (at(INTEGER_LITERAL)) {
734                parseOneTokenExpression(INTEGER_CONSTANT);
735            }
736            else if (at(CHARACTER_LITERAL)) {
737                parseOneTokenExpression(CHARACTER_CONSTANT);
738            }
739            else if (at(FLOAT_LITERAL)) {
740                parseOneTokenExpression(FLOAT_CONSTANT);
741            }
742            else if (at(NULL_KEYWORD)) {
743                parseOneTokenExpression(NULL);
744            }
745            else {
746                return false;
747            }
748            return true;
749        }
750    
751        /*
752         * when
753         *   : "when" ("(" (modifiers "val" SimpleName "=")? element ")")? "{"
754         *         whenEntry*
755         *     "}"
756         *   ;
757         */
758        private void parseWhen() {
759            assert _at(WHEN_KEYWORD);
760    
761            PsiBuilder.Marker when = mark();
762    
763            advance(); // WHEN_KEYWORD
764    
765            // Parse condition
766            myBuilder.disableNewlines();
767            if (at(LPAR)) {
768                advanceAt(LPAR);
769    
770                int valPos = matchTokenStreamPredicate(new FirstBefore(new At(VAL_KEYWORD), new AtSet(RPAR, LBRACE, RBRACE, SEMICOLON, EQ)));
771                if (valPos >= 0) {
772                    PsiBuilder.Marker property = mark();
773                    myJetParsing.parseModifierList(MODIFIER_LIST, true);
774                    myJetParsing.parseProperty(true);
775                    property.done(PROPERTY);
776                }
777                else {
778                    parseExpression();
779                }
780    
781                expect(RPAR, "Expecting ')'");
782            }
783            myBuilder.restoreNewlinesState();
784    
785            // Parse when block
786            myBuilder.enableNewlines();
787            if (expect(LBRACE, "Expecting '{'")) {
788                while (!eof() && !at(RBRACE)) {
789                    parseWhenEntry();
790                }
791    
792                expect(RBRACE, "Expecting '}'");
793            }
794            myBuilder.restoreNewlinesState();
795    
796            when.done(WHEN);
797        }
798    
799        /*
800         * whenEntry
801         *   // TODO : consider empty after ->
802         *   : whenCondition{","} "->" element SEMI
803         *   : "else" "->" element SEMI
804         *   ;
805         */
806        private void parseWhenEntry() {
807            PsiBuilder.Marker entry = mark();
808    
809            if (at(ELSE_KEYWORD)) {
810                advance(); // ELSE_KEYWORD
811    
812                if (!at(ARROW)) {
813                    errorUntil("Expecting '->'", TokenSet.create(ARROW,
814                                                                 RBRACE, EOL_OR_SEMICOLON));
815                }
816    
817                if (at(ARROW)) {
818                    advance(); // ARROW
819    
820                    if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
821                        error("Expecting an element");
822                    }
823                    else {
824                        parseExpressionPreferringBlocks();
825                    }
826                }
827                else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) {
828                    errorAndAdvance("Expecting '->'");
829                }
830            }
831            else {
832                parseWhenEntryNotElse();
833            }
834    
835            entry.done(WHEN_ENTRY);
836            consumeIf(SEMICOLON);
837        }
838    
839        /*
840         * : whenCondition{","} "->" element SEMI
841         */
842        private void parseWhenEntryNotElse() {
843            while (true) {
844                while (at(COMMA)) errorAndAdvance("Expecting a when-condition");
845                parseWhenCondition();
846                if (!at(COMMA)) break;
847                advance(); // COMMA
848            }
849    
850            expect(ARROW, "Expecting '->' or 'when'", WHEN_CONDITION_RECOVERY_SET);
851            if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
852                error("Expecting an element");
853            }
854            else {
855                parseExpressionPreferringBlocks();
856            }
857            // SEMI is consumed in parseWhenEntry
858        }
859    
860        /*
861         * whenCondition
862         *   : expression
863         *   : ("in" | "!in") expression
864         *   : ("is" | "!is") isRHS
865         *   ;
866         */
867        private void parseWhenCondition() {
868            PsiBuilder.Marker condition = mark();
869            myBuilder.disableNewlines();
870            if (at(IN_KEYWORD) || at(NOT_IN)) {
871                PsiBuilder.Marker mark = mark();
872                advance(); // IN_KEYWORD or NOT_IN
873                mark.done(OPERATION_REFERENCE);
874    
875    
876                if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) {
877                    error("Expecting an element");
878                }
879                else {
880                    parseExpression();
881                }
882                condition.done(WHEN_CONDITION_IN_RANGE);
883            }
884            else if (at(IS_KEYWORD) || at(NOT_IS)) {
885                advance(); // IS_KEYWORD or NOT_IS
886    
887                if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) {
888                    error("Expecting a type");
889                }
890                else {
891                    myJetParsing.parseTypeRef();
892                }
893                condition.done(WHEN_CONDITION_IS_PATTERN);
894            }
895            else {
896                if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) {
897                    error("Expecting an expression, is-condition or in-condition");
898                }
899                else {
900                    parseExpression();
901                }
902                condition.done(WHEN_CONDITION_EXPRESSION);
903            }
904            myBuilder.restoreNewlinesState();
905        }
906    
907        /*
908         * arrayAccess
909         *   : "[" element{","} "]"
910         *   ;
911         */
912        private void parseArrayAccess() {
913            assert _at(LBRACKET);
914    
915            PsiBuilder.Marker indices = mark();
916    
917            myBuilder.disableNewlines();
918            advance(); // LBRACKET
919    
920            while (true) {
921                if (at(COMMA)) errorAndAdvance("Expecting an index element");
922                if (at(RBRACKET)) {
923                    error("Expecting an index element");
924                    break;
925                }
926                parseExpression();
927                if (!at(COMMA)) break;
928                advance(); // COMMA
929            }
930    
931            expect(RBRACKET, "Expecting ']'");
932            myBuilder.restoreNewlinesState();
933    
934            indices.done(INDICES);
935        }
936    
937        /*
938         * SimpleName
939         */
940        public void parseSimpleNameExpression() {
941            PsiBuilder.Marker simpleName = mark();
942            if (at(FIELD_IDENTIFIER)) {
943                advance(); //
944            }
945            else {
946                expect(IDENTIFIER, "Expecting an identifier");
947            }
948            simpleName.done(REFERENCE_EXPRESSION);
949        }
950    
951        /*
952         * modifiers declarationRest
953         */
954        private boolean parseLocalDeclaration() {
955            PsiBuilder.Marker decl = mark();
956            JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD);
957            myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector, false);
958    
959            IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected());
960    
961            if (declType != null) {
962                decl.done(declType);
963                return true;
964            }
965            else {
966                decl.rollbackTo();
967                return false;
968            }
969        }
970    
971        /*
972         * functionLiteral  // one can use "it" as a parameter name
973         *   : "{" expressions "}"
974         *   : "{" (modifiers SimpleName){","} "->" statements "}"
975         *   : "{" (type ".")? "(" (modifiers SimpleName (":" type)?){","} ")" (":" type)? "->" expressions "}"
976         *   ;
977         */
978        private void parseFunctionLiteral() {
979            parseFunctionLiteral(false);
980        }
981    
982        private void parseFunctionLiteral(boolean preferBlock) {
983            assert _at(LBRACE);
984    
985            PsiBuilder.Marker literalExpression = mark();
986    
987            PsiBuilder.Marker literal = mark();
988    
989            myBuilder.enableNewlines();
990            advance(); // LBRACE
991    
992            boolean paramsFound = false;
993    
994            if (at(ARROW)) {
995                //   { -> ...}
996                mark().done(VALUE_PARAMETER_LIST);
997                advance(); // ARROW
998                paramsFound = true;
999            }
1000            else if (at(LPAR)) {
1001                // Look for ARROW after matching RPAR
1002                //   {(a, b) -> ...}
1003    
1004                {
1005                    boolean preferParamsToExpressions = isConfirmedParametersByComma();
1006    
1007                    PsiBuilder.Marker rollbackMarker = mark();
1008                    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        // Check that position is followed by top level comma. It can't be expression and we want it be
1132        // parsed as parameters in function literal
1133        private boolean isConfirmedParametersByComma() {
1134            assert _at(LPAR);
1135            PsiBuilder.Marker lparMarker = mark();
1136            advance(); // LPAR
1137            int comma = matchTokenStreamPredicate(new FirstBefore(new At(COMMA), new AtSet(ARROW, RPAR)));
1138            lparMarker.rollbackTo();
1139            return comma > 0;
1140        }
1141    
1142        private boolean parseFunctionTypeDotParametersAndType() {
1143            PsiBuilder.Marker rollbackMarker = mark();
1144    
1145            // True when it's confirmed that body of literal can't be simple expressions and we prefer to parse
1146            // it to function params if possible.
1147            boolean preferParamsToExpressions = false;
1148    
1149            int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtSet(ARROW, RPAR)));
1150            if (lastDot >= 0) {
1151                createTruncatedBuilder(lastDot).parseTypeRef();
1152                if (at(DOT)) {
1153                    advance(); // DOT
1154    
1155                    if (at(LPAR)) {
1156                        preferParamsToExpressions = isConfirmedParametersByComma();
1157                    }
1158    
1159                    parseFunctionLiteralParametersAndType();
1160                }
1161            }
1162    
1163            return preferParamsToExpressions ?
1164                   rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
1165                   rollbackOrDropAt(rollbackMarker, ARROW);
1166        }
1167    
1168        private void parseFunctionLiteralParametersAndType() {
1169            parseFunctionLiteralParameterList();
1170            parseOptionalFunctionLiteralType();
1171        }
1172    
1173        /*
1174         * (":" type)?
1175         */
1176        private void parseOptionalFunctionLiteralType() {
1177            if (at(COLON)) {
1178                advance(); // COLON
1179                if (at(ARROW)) {
1180                    error("Expecting a type");
1181                }
1182                else {
1183                    myJetParsing.parseTypeRef();
1184                }
1185            }
1186        }
1187    
1188        /*
1189         * "(" (modifiers SimpleName (":" type)?){","} ")"
1190         */
1191        private void parseFunctionLiteralParameterList() {
1192            PsiBuilder.Marker list = mark();
1193            expect(LPAR, "Expecting a parameter list in parentheses (...)", TokenSet.create(ARROW, COLON));
1194    
1195            myBuilder.disableNewlines();
1196    
1197            if (!at(RPAR)) {
1198                while (true) {
1199                    if (at(COMMA)) errorAndAdvance("Expecting a parameter declaration");
1200    
1201                    PsiBuilder.Marker parameter = mark();
1202                    int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, ARROW)));
1203                    createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false);
1204    
1205                    expect(IDENTIFIER, "Expecting parameter declaration");
1206    
1207                    if (at(COLON)) {
1208                        advance(); // COLON
1209                        myJetParsing.parseTypeRef();
1210                    }
1211                    parameter.done(VALUE_PARAMETER);
1212                    if (!at(COMMA)) break;
1213                    advance(); // COMMA
1214    
1215                    if (at(RPAR)) {
1216                        error("Expecting a parameter declaration");
1217                        break;
1218                    }
1219                }
1220            }
1221    
1222            myBuilder.restoreNewlinesState();
1223    
1224            expect(RPAR, "Expecting ')", TokenSet.create(ARROW, COLON));
1225            list.done(VALUE_PARAMETER_LIST);
1226        }
1227    
1228        /*
1229         * expressions
1230         *   : SEMI* statement{SEMI+} SEMI*
1231         */
1232        public void parseStatements() {
1233            while (at(SEMICOLON)) advance(); // SEMICOLON
1234            while (!eof() && !at(RBRACE)) {
1235                if (!atSet(STATEMENT_FIRST)) {
1236                    errorAndAdvance("Expecting an element");
1237                }
1238                if (atSet(STATEMENT_FIRST)) {
1239                    parseStatement();
1240                }
1241                if (at(SEMICOLON)) {
1242                    while (at(SEMICOLON)) advance(); // SEMICOLON
1243                }
1244                else if (at(RBRACE)) {
1245                    break;
1246                }
1247                else if (!myBuilder.newlineBeforeCurrentToken()) {
1248                    String severalStatementsError = "Unexpected tokens (use ';' to separate expressions on the same line)";
1249    
1250                    if (atSet(STATEMENT_NEW_LINE_QUICK_RECOVERY_SET)) {
1251                        error(severalStatementsError);
1252                    }
1253                    else {
1254                        errorUntil(severalStatementsError, TokenSet.create(EOL_OR_SEMICOLON));
1255                    }
1256                }
1257            }
1258        }
1259    
1260        /*
1261         * statement
1262         *  : expression
1263         *  : declaration
1264         *  ;
1265         */
1266        private void parseStatement() {
1267            if (!parseLocalDeclaration()) {
1268                if (!atSet(EXPRESSION_FIRST)) {
1269                    errorAndAdvance("Expecting a statement");
1270                }
1271                else {
1272                    parseExpression();
1273                }
1274            }
1275        }
1276    
1277        /*
1278         * declaration
1279         *   : function
1280         *   : property
1281         *   : extension
1282         *   : class
1283         *   : typedef
1284         *   : object
1285         *   ;
1286         */
1287        private IElementType parseLocalDeclarationRest(boolean isEnum) {
1288            IElementType keywordToken = tt();
1289            IElementType declType = null;
1290            if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) {
1291                declType = myJetParsing.parseClass(isEnum);
1292            }
1293            else if (keywordToken == FUN_KEYWORD) {
1294                declType = myJetParsing.parseFunction();
1295            }
1296            else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) {
1297                declType = myJetParsing.parseProperty(true);
1298            }
1299            else if (keywordToken == TYPE_KEYWORD) {
1300                declType = myJetParsing.parseTypeDef();
1301            }
1302            else if (keywordToken == OBJECT_KEYWORD) {
1303                // Object expression may appear at the statement position: should parse it
1304                // as expression instead of object declaration
1305                // sample:
1306                // {
1307                //   object : Thread() {
1308                //   }
1309                // }
1310                IElementType lookahead = lookahead(1);
1311                if (lookahead == COLON || lookahead == LBRACE) {
1312                    return null;
1313                }
1314    
1315                myJetParsing.parseObject(true, true);
1316                declType = OBJECT_DECLARATION;
1317            }
1318            return declType;
1319        }
1320    
1321        /*
1322         * doWhile
1323         *   : "do" element "while" "(" element ")"
1324         *   ;
1325         */
1326        private void parseDoWhile() {
1327            assert _at(DO_KEYWORD);
1328    
1329            PsiBuilder.Marker loop = mark();
1330    
1331            advance(); // DO_KEYWORD
1332    
1333            if (!at(WHILE_KEYWORD)) {
1334                parseControlStructureBody();
1335            }
1336    
1337            if (expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition")) {
1338                parseCondition();
1339            }
1340    
1341            loop.done(DO_WHILE);
1342        }
1343    
1344        /*
1345         * while
1346         *   : "while" "(" element ")" element
1347         *   ;
1348         */
1349        private void parseWhile() {
1350            assert _at(WHILE_KEYWORD);
1351    
1352            PsiBuilder.Marker loop = mark();
1353    
1354            advance(); // WHILE_KEYWORD
1355    
1356            parseCondition();
1357    
1358            parseControlStructureBody();
1359    
1360            loop.done(WHILE);
1361        }
1362    
1363        /*
1364         * for
1365         *   : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression
1366         *   ;
1367         *
1368         *   TODO: empty loop body (at the end of the block)?
1369         */
1370        private void parseFor() {
1371            assert _at(FOR_KEYWORD);
1372    
1373            PsiBuilder.Marker loop = mark();
1374    
1375            advance(); // FOR_KEYWORD
1376    
1377            if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) {
1378                myBuilder.disableNewlines();
1379    
1380                if (!at(RPAR)) {
1381                    PsiBuilder.Marker parameter = mark();
1382                    if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
1383                    if (at(LPAR)) {
1384                        myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
1385                        parameter.done(MULTI_VARIABLE_DECLARATION);
1386                    }
1387                    else {
1388                        expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD));
1389    
1390                        if (at(COLON)) {
1391                            advance(); // COLON
1392                            myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
1393                        }
1394                        parameter.done(VALUE_PARAMETER);
1395                    }
1396    
1397                    if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) {
1398                        PsiBuilder.Marker range = mark();
1399                        parseExpression();
1400                        range.done(LOOP_RANGE);
1401                    }
1402                }
1403                else {
1404                    error("Expecting a variable name");
1405                }
1406    
1407                expectNoAdvance(RPAR, "Expecting ')'");
1408                myBuilder.restoreNewlinesState();
1409            }
1410    
1411            parseControlStructureBody();
1412    
1413            loop.done(FOR);
1414        }
1415    
1416        /**
1417         * If it has no ->, it's a block, otherwise a function literal
1418         */
1419        private void parseExpressionPreferringBlocks() {
1420            if (at(LBRACE)) {
1421                parseFunctionLiteral(true);
1422            }
1423            else if (at(LABEL_IDENTIFIER) && lookahead(1) == LBRACE ) {
1424                PsiBuilder.Marker mark = mark();
1425    
1426                parseLabel();
1427    
1428                parseFunctionLiteral(true);
1429    
1430                mark.done(LABELED_EXPRESSION);
1431            }
1432            else {
1433                parseExpression();
1434            }
1435        }
1436    
1437        /*
1438         * element
1439         */
1440        private void parseControlStructureBody() {
1441            PsiBuilder.Marker body = mark();
1442            if (!at(SEMICOLON)) {
1443                parseExpressionPreferringBlocks();
1444            }
1445            body.done(BODY);
1446        }
1447    
1448        /*
1449         * try
1450         *   : "try" block catchBlock* finallyBlock?
1451         *   ;
1452         * catchBlock
1453         *   : "catch" "(" attributes SimpleName ":" userType ")" block
1454         *   ;
1455         *
1456         * finallyBlock
1457         *   : "finally" block
1458         *   ;
1459         */
1460        private void parseTry() {
1461            assert _at(TRY_KEYWORD);
1462    
1463            PsiBuilder.Marker tryExpression = mark();
1464    
1465            advance(); // TRY_KEYWORD
1466    
1467            myJetParsing.parseBlock();
1468    
1469            boolean catchOrFinally = false;
1470            while (at(CATCH_KEYWORD)) {
1471                catchOrFinally = true;
1472                PsiBuilder.Marker catchBlock = mark();
1473                advance(); // CATCH_KEYWORD
1474    
1475                TokenSet recoverySet = TokenSet.create(LBRACE, FINALLY_KEYWORD, CATCH_KEYWORD);
1476                if (atSet(recoverySet)) {
1477                    error("Expecting exception variable declaration");
1478                }
1479                else {
1480                    PsiBuilder.Marker parameters = mark();
1481                    expect(LPAR, "Expecting '('", recoverySet);
1482                    if (!atSet(recoverySet)) {
1483                        myJetParsing.parseValueParameter();
1484                        expect(RPAR, "Expecting ')'", recoverySet);
1485                    }
1486                    else {
1487                        error("Expecting exception variable declaration");
1488                    }
1489                    parameters.done(VALUE_PARAMETER_LIST);
1490                }
1491    
1492                if (at(LBRACE)) {
1493                    myJetParsing.parseBlock();
1494                }
1495                else {
1496                    error("Expecting a block: { ... }");
1497                }
1498                catchBlock.done(CATCH);
1499            }
1500    
1501            if (at(FINALLY_KEYWORD)) {
1502                catchOrFinally = true;
1503                PsiBuilder.Marker finallyBlock = mark();
1504    
1505                advance(); // FINALLY_KEYWORD
1506    
1507                myJetParsing.parseBlock();
1508    
1509                finallyBlock.done(FINALLY);
1510            }
1511    
1512            if (!catchOrFinally) {
1513                error("Expecting 'catch' or 'finally'");
1514            }
1515    
1516            tryExpression.done(TRY);
1517        }
1518    
1519        /*
1520         * if
1521         *   : "if" "(" element ")" element SEMI? ("else" element)?
1522         *   ;
1523         */
1524        private void parseIf() {
1525            assert _at(IF_KEYWORD);
1526    
1527            PsiBuilder.Marker marker = mark();
1528    
1529            advance(); //IF_KEYWORD
1530    
1531            parseCondition();
1532    
1533            PsiBuilder.Marker thenBranch = mark();
1534            if (!at(ELSE_KEYWORD) && !at(SEMICOLON)) {
1535                parseExpressionPreferringBlocks();
1536            }
1537            if (at(SEMICOLON) && lookahead(1) == ELSE_KEYWORD) {
1538                advance(); // SEMICOLON
1539            }
1540            thenBranch.done(THEN);
1541    
1542            if (at(ELSE_KEYWORD)) {
1543                advance(); // ELSE_KEYWORD
1544    
1545                PsiBuilder.Marker elseBranch = mark();
1546                if (!at(SEMICOLON)) {
1547                    parseExpressionPreferringBlocks();
1548                }
1549                elseBranch.done(ELSE);
1550            }
1551    
1552            marker.done(IF);
1553        }
1554    
1555        /*
1556         * "(" element ")"
1557         */
1558        private void parseCondition() {
1559            myBuilder.disableNewlines();
1560    
1561            if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) {
1562                PsiBuilder.Marker condition = mark();
1563                parseExpression();
1564                condition.done(CONDITION);
1565                expect(RPAR, "Expecting ')");
1566            }
1567    
1568            myBuilder.restoreNewlinesState();
1569        }
1570    
1571        /*
1572         * : "continue" getEntryPoint?
1573         * : "break" getEntryPoint?
1574         */
1575        private void parseJump(JetNodeType type) {
1576            assert _at(BREAK_KEYWORD) || _at(CONTINUE_KEYWORD);
1577    
1578            PsiBuilder.Marker marker = mark();
1579    
1580            advance(); // BREAK_KEYWORD or CONTINUE_KEYWORD
1581    
1582            parseLabelOnTheSameLine();
1583    
1584            marker.done(type);
1585        }
1586    
1587        /*
1588         * "return" getEntryPoint? element?
1589         */
1590        private void parseReturn() {
1591            assert _at(RETURN_KEYWORD);
1592    
1593            PsiBuilder.Marker returnExpression = mark();
1594    
1595            advance(); // RETURN_KEYWORD
1596    
1597            parseLabelOnTheSameLine();
1598    
1599            if (atSet(EXPRESSION_FIRST) && !at(EOL_OR_SEMICOLON)) parseExpression();
1600    
1601            returnExpression.done(RETURN);
1602        }
1603    
1604        /*
1605         * label?
1606         */
1607        private void parseLabelOnTheSameLine() {
1608            if (!eol() && at(LABEL_IDENTIFIER)) {
1609                parseLabel();
1610            }
1611        }
1612    
1613        /*
1614         * label
1615         */
1616        private void parseLabel() {
1617            assert _at(LABEL_IDENTIFIER);
1618    
1619            String labelText = myBuilder.getTokenText();
1620            if ("@".equals(labelText)) {
1621                errorAndAdvance("Label must be named");
1622                return;
1623            }
1624    
1625            PsiBuilder.Marker labelWrap = mark();
1626    
1627            PsiBuilder.Marker mark = mark();
1628            advance(); // LABEL_IDENTIFIER
1629            mark.done(LABEL);
1630    
1631            labelWrap.done(LABEL_QUALIFIER);
1632        }
1633    
1634        /*
1635         * : "throw" element
1636         */
1637        private void parseThrow() {
1638            assert _at(THROW_KEYWORD);
1639    
1640            PsiBuilder.Marker marker = mark();
1641    
1642            advance(); // THROW_KEYWORD
1643    
1644            parseExpression();
1645    
1646            marker.done(THROW);
1647        }
1648    
1649        /*
1650         * "(" expression ")"
1651         */
1652        private void parseParenthesizedExpression() {
1653            assert _at(LPAR);
1654    
1655            PsiBuilder.Marker mark = mark();
1656    
1657            myBuilder.disableNewlines();
1658            advance(); // LPAR
1659            if (at(RPAR)) {
1660                error("Expecting an expression");
1661            }
1662            else {
1663                parseExpression();
1664            }
1665    
1666            expect(RPAR, "Expecting ')'");
1667            myBuilder.restoreNewlinesState();
1668    
1669            mark.done(PARENTHESIZED);
1670        }
1671    
1672        /*
1673         * tupleLiteral
1674         *   : "#" "(" (((SimpleName "=")? expression){","})? ")"
1675         *   ;
1676         */
1677        @Deprecated // Tuples are dropped, but parsing is left to minimize surprising. This code should be removed some time (in Kotlin 1.0?)
1678        private void parseTupleExpression() {
1679            assert _at(HASH);
1680            PsiBuilder.Marker mark = mark();
1681    
1682            advance(); // HASH
1683            advance(); // LPAR
1684            myBuilder.disableNewlines();
1685            if (!at(RPAR)) {
1686                while (true) {
1687                    while (at(COMMA)) {
1688                        advance();
1689                    }
1690    
1691                    if (at(IDENTIFIER) && lookahead(1) == EQ) {
1692                        advance(); // IDENTIFIER
1693                        advance(); // EQ
1694                        parseExpression();
1695                    }
1696                    else {
1697                        parseExpression();
1698                    }
1699    
1700                    if (!at(COMMA)) break;
1701                    advance(); // COMMA
1702    
1703                    if (at(RPAR)) {
1704                        break;
1705                    }
1706                }
1707    
1708            }
1709            consumeIf(RPAR);
1710            myBuilder.restoreNewlinesState();
1711    
1712            mark.error("Tuples are not supported. Use data classes instead.");
1713        }
1714    
1715        /*
1716         * "this" label?
1717         */
1718        private void parseThisExpression() {
1719            assert _at(THIS_KEYWORD);
1720            PsiBuilder.Marker mark = mark();
1721    
1722            PsiBuilder.Marker thisReference = mark();
1723            advance(); // THIS_KEYWORD
1724            thisReference.done(REFERENCE_EXPRESSION);
1725    
1726            parseLabelOnTheSameLine();
1727    
1728            mark.done(THIS_EXPRESSION);
1729        }
1730    
1731        /*
1732         * "this" ("<" type ">")? label?
1733         */
1734        private void parseSuperExpression() {
1735            assert _at(SUPER_KEYWORD);
1736            PsiBuilder.Marker mark = mark();
1737    
1738            PsiBuilder.Marker superReference = mark();
1739            advance(); // SUPER_KEYWORD
1740            superReference.done(REFERENCE_EXPRESSION);
1741    
1742            if (at(LT)) {
1743                // This may be "super < foo" or "super<foo>", thus the backtracking
1744                PsiBuilder.Marker supertype = mark();
1745    
1746                myBuilder.disableNewlines();
1747                advance(); // LT
1748    
1749                myJetParsing.parseTypeRef();
1750    
1751                if (at(GT)) {
1752                    advance(); // GT
1753                    supertype.drop();
1754                }
1755                else {
1756                    supertype.rollbackTo();
1757                }
1758                myBuilder.restoreNewlinesState();
1759            }
1760            parseLabelOnTheSameLine();
1761    
1762            mark.done(SUPER_EXPRESSION);
1763        }
1764    
1765        /*
1766         * valueArguments
1767         *   : "(" (SimpleName "=")? "*"? element{","} ")"
1768         *   ;
1769         */
1770        public void parseValueArgumentList() {
1771            PsiBuilder.Marker list = mark();
1772    
1773            myBuilder.disableNewlines();
1774    
1775            if (expect(LPAR, "Expecting an argument list", EXPRESSION_FOLLOW)) {
1776                if (!at(RPAR)) {
1777                    while (true) {
1778                        while (at(COMMA)) errorAndAdvance("Expecting an argument");
1779                        parseValueArgument();
1780                        if (!at(COMMA)) break;
1781                        advance(); // COMMA
1782                        if (at(RPAR)) {
1783                            error("Expecting an argument");
1784                            break;
1785                        }
1786                    }
1787                }
1788    
1789                expect(RPAR, "Expecting ')'", EXPRESSION_FOLLOW);
1790            }
1791    
1792            myBuilder.restoreNewlinesState();
1793    
1794            list.done(VALUE_ARGUMENT_LIST);
1795        }
1796    
1797        /*
1798         * (SimpleName "=")? "*"? element
1799         */
1800        private void parseValueArgument() {
1801            PsiBuilder.Marker argument = mark();
1802            if (at(IDENTIFIER) && lookahead(1) == EQ) {
1803                PsiBuilder.Marker argName = mark();
1804                PsiBuilder.Marker reference = mark();
1805                advance(); // IDENTIFIER
1806                reference.done(REFERENCE_EXPRESSION);
1807                argName.done(VALUE_ARGUMENT_NAME);
1808                advance(); // EQ
1809            }
1810            if (at(MUL)) {
1811                advance(); // MUL
1812            }
1813            parseExpression();
1814            argument.done(VALUE_ARGUMENT);
1815        }
1816    
1817        /*
1818         * "object" (":" delegationSpecifier{","})? classBody // Cannot make class body optional: foo(object : F, A)
1819         */
1820        public void parseObjectLiteral() {
1821            PsiBuilder.Marker literal = mark();
1822            PsiBuilder.Marker declaration = mark();
1823            myJetParsing.parseObject(false, false); // Body is not optional because of foo(object : A, B)
1824            declaration.done(OBJECT_DECLARATION);
1825            literal.done(OBJECT_LITERAL);
1826        }
1827    
1828        private void parseOneTokenExpression(JetNodeType type) {
1829            PsiBuilder.Marker mark = mark();
1830            advance();
1831            mark.done(type);
1832        }
1833    
1834        @Override
1835        protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
1836            return myJetParsing.create(builder);
1837        }
1838    
1839        private boolean interruptedWithNewLine() {
1840            return !ALLOW_NEWLINE_OPERATIONS.contains(tt()) && myBuilder.newlineBeforeCurrentToken();
1841        }
1842    }