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