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