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