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