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