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