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