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