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