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            while (at(SEMICOLON)) advance(); // SEMICOLON
1185            while (!eof() && !at(RBRACE)) {
1186                if (!atSet(STATEMENT_FIRST)) {
1187                    errorAndAdvance("Expecting an element");
1188                }
1189                if (atSet(STATEMENT_FIRST)) {
1190                    parseStatement();
1191                }
1192                if (at(SEMICOLON)) {
1193                    while (at(SEMICOLON)) advance(); // SEMICOLON
1194                }
1195                else if (at(RBRACE)) {
1196                    break;
1197                }
1198                else if (!myBuilder.newlineBeforeCurrentToken()) {
1199                    String severalStatementsError = "Unexpected tokens (use ';' to separate expressions on the same line)";
1200    
1201                    if (atSet(STATEMENT_NEW_LINE_QUICK_RECOVERY_SET)) {
1202                        error(severalStatementsError);
1203                    }
1204                    else {
1205                        errorUntil(severalStatementsError, TokenSet.create(EOL_OR_SEMICOLON, LBRACE, RBRACE));
1206                    }
1207                }
1208            }
1209        }
1210    
1211        /*
1212         * statement
1213         *  : expression
1214         *  : declaration
1215         *  ;
1216         */
1217        private void parseStatement() {
1218            if (!parseLocalDeclaration()) {
1219                if (!atSet(EXPRESSION_FIRST)) {
1220                    errorAndAdvance("Expecting a statement");
1221                }
1222                else {
1223                    parseExpression();
1224                }
1225            }
1226        }
1227    
1228        /*
1229         * declaration
1230         *   : function
1231         *   : property
1232         *   : extension
1233         *   : class
1234         *   : typeAlias
1235         *   : object
1236         *   ;
1237         */
1238        private IElementType parseLocalDeclarationRest(boolean isEnum) {
1239            IElementType keywordToken = tt();
1240            IElementType declType = null;
1241            if (keywordToken == CLASS_KEYWORD ||  keywordToken == INTERFACE_KEYWORD) {
1242                declType = myJetParsing.parseClass(isEnum);
1243            }
1244            else if (keywordToken == FUN_KEYWORD) {
1245                declType = myJetParsing.parseFunction();
1246            }
1247            else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) {
1248                declType = myJetParsing.parseProperty(true);
1249            }
1250            else if (keywordToken == TYPE_ALIAS_KEYWORD) {
1251                declType = myJetParsing.parseTypeAlias();
1252            }
1253            else if (keywordToken == OBJECT_KEYWORD) {
1254                // Object expression may appear at the statement position: should parse it
1255                // as expression instead of object declaration
1256                // sample:
1257                // {
1258                //   object : Thread() {
1259                //   }
1260                // }
1261                IElementType lookahead = lookahead(1);
1262                if (lookahead == COLON || lookahead == LBRACE) {
1263                    return null;
1264                }
1265    
1266                myJetParsing.parseObject(NameParsingMode.REQUIRED, true);
1267                declType = OBJECT_DECLARATION;
1268            }
1269            return declType;
1270        }
1271    
1272        /*
1273         * doWhile
1274         *   : "do" element "while" "(" element ")"
1275         *   ;
1276         */
1277        private void parseDoWhile() {
1278            assert _at(DO_KEYWORD);
1279    
1280            PsiBuilder.Marker loop = mark();
1281    
1282            advance(); // DO_KEYWORD
1283    
1284            if (!at(WHILE_KEYWORD)) {
1285                parseControlStructureBody();
1286            }
1287    
1288            if (expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition")) {
1289                parseCondition();
1290            }
1291    
1292            loop.done(DO_WHILE);
1293        }
1294    
1295        /*
1296         * while
1297         *   : "while" "(" element ")" element
1298         *   ;
1299         */
1300        private void parseWhile() {
1301            assert _at(WHILE_KEYWORD);
1302    
1303            PsiBuilder.Marker loop = mark();
1304    
1305            advance(); // WHILE_KEYWORD
1306    
1307            parseCondition();
1308    
1309            parseControlStructureBody();
1310    
1311            loop.done(WHILE);
1312        }
1313    
1314        /*
1315         * for
1316         *   : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression
1317         *   ;
1318         *
1319         *   TODO: empty loop body (at the end of the block)?
1320         */
1321        private void parseFor() {
1322            assert _at(FOR_KEYWORD);
1323    
1324            PsiBuilder.Marker loop = mark();
1325    
1326            advance(); // FOR_KEYWORD
1327    
1328            if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) {
1329                myBuilder.disableNewlines();
1330    
1331                if (!at(RPAR)) {
1332                    PsiBuilder.Marker parameter = mark();
1333    
1334                    if (!at(IN_KEYWORD)) {
1335                        myJetParsing.parseModifierList(DEFAULT, TokenSet.create(IN_KEYWORD, RPAR, COLON));
1336                    }
1337    
1338                    if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
1339    
1340                    if (at(LPAR)) {
1341                        myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
1342                        parameter.done(MULTI_VARIABLE_DECLARATION);
1343                    }
1344                    else {
1345                        expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD));
1346    
1347                        if (at(COLON)) {
1348                            advance(); // COLON
1349                            myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
1350                        }
1351                        parameter.done(VALUE_PARAMETER);
1352                    }
1353    
1354                    if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) {
1355                        PsiBuilder.Marker range = mark();
1356                        parseExpression();
1357                        range.done(LOOP_RANGE);
1358                    }
1359                }
1360                else {
1361                    error("Expecting a variable name");
1362                }
1363    
1364                expectNoAdvance(RPAR, "Expecting ')'");
1365                myBuilder.restoreNewlinesState();
1366            }
1367    
1368            parseControlStructureBody();
1369    
1370            loop.done(FOR);
1371        }
1372    
1373        /**
1374         * If it has no ->, it's a block, otherwise a function literal
1375         */
1376        private void parseExpressionPreferringBlocks() {
1377            if (!parseAnnotatedLambda(/* preferBlock = */true)) {
1378                parseExpression();
1379            }
1380        }
1381    
1382        /*
1383         * element
1384         */
1385        private void parseControlStructureBody() {
1386            PsiBuilder.Marker body = mark();
1387            if (!at(SEMICOLON)) {
1388                parseExpressionPreferringBlocks();
1389            }
1390            body.done(BODY);
1391        }
1392    
1393        /*
1394         * try
1395         *   : "try" block catchBlock* finallyBlock?
1396         *   ;
1397         * catchBlock
1398         *   : "catch" "(" annotations SimpleName ":" userType ")" block
1399         *   ;
1400         *
1401         * finallyBlock
1402         *   : "finally" block
1403         *   ;
1404         */
1405        private void parseTry() {
1406            assert _at(TRY_KEYWORD);
1407    
1408            PsiBuilder.Marker tryExpression = mark();
1409    
1410            advance(); // TRY_KEYWORD
1411    
1412            myJetParsing.parseBlock();
1413    
1414            boolean catchOrFinally = false;
1415            while (at(CATCH_KEYWORD)) {
1416                catchOrFinally = true;
1417                PsiBuilder.Marker catchBlock = mark();
1418                advance(); // CATCH_KEYWORD
1419    
1420                TokenSet recoverySet = TokenSet.create(LBRACE, RBRACE, FINALLY_KEYWORD, CATCH_KEYWORD);
1421                if (atSet(recoverySet)) {
1422                    error("Expecting exception variable declaration");
1423                }
1424                else {
1425                    PsiBuilder.Marker parameters = mark();
1426                    expect(LPAR, "Expecting '('", recoverySet);
1427                    if (!atSet(recoverySet)) {
1428                        myJetParsing.parseValueParameter(/*typeRequired = */ true);
1429                        expect(RPAR, "Expecting ')'", recoverySet);
1430                    }
1431                    else {
1432                        error("Expecting exception variable declaration");
1433                    }
1434                    parameters.done(VALUE_PARAMETER_LIST);
1435                }
1436    
1437                if (at(LBRACE)) {
1438                    myJetParsing.parseBlock();
1439                }
1440                else {
1441                    error("Expecting a block: { ... }");
1442                }
1443                catchBlock.done(CATCH);
1444            }
1445    
1446            if (at(FINALLY_KEYWORD)) {
1447                catchOrFinally = true;
1448                PsiBuilder.Marker finallyBlock = mark();
1449    
1450                advance(); // FINALLY_KEYWORD
1451    
1452                myJetParsing.parseBlock();
1453    
1454                finallyBlock.done(FINALLY);
1455            }
1456    
1457            if (!catchOrFinally) {
1458                error("Expecting 'catch' or 'finally'");
1459            }
1460    
1461            tryExpression.done(TRY);
1462        }
1463    
1464        /*
1465         * if
1466         *   : "if" "(" element ")" element SEMI? ("else" element)?
1467         *   ;
1468         */
1469        private void parseIf() {
1470            assert _at(IF_KEYWORD);
1471    
1472            PsiBuilder.Marker marker = mark();
1473    
1474            advance(); //IF_KEYWORD
1475    
1476            parseCondition();
1477    
1478            PsiBuilder.Marker thenBranch = mark();
1479            if (!at(ELSE_KEYWORD) && !at(SEMICOLON)) {
1480                parseExpressionPreferringBlocks();
1481            }
1482            if (at(SEMICOLON) && lookahead(1) == ELSE_KEYWORD) {
1483                advance(); // SEMICOLON
1484            }
1485            thenBranch.done(THEN);
1486    
1487            if (at(ELSE_KEYWORD)) {
1488                advance(); // ELSE_KEYWORD
1489    
1490                PsiBuilder.Marker elseBranch = mark();
1491                if (!at(SEMICOLON)) {
1492                    parseExpressionPreferringBlocks();
1493                }
1494                elseBranch.done(ELSE);
1495            }
1496    
1497            marker.done(IF);
1498        }
1499    
1500        /*
1501         * "(" element ")"
1502         */
1503        private void parseCondition() {
1504            myBuilder.disableNewlines();
1505    
1506            if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) {
1507                PsiBuilder.Marker condition = mark();
1508                parseExpression();
1509                condition.done(CONDITION);
1510                expect(RPAR, "Expecting ')");
1511            }
1512    
1513            myBuilder.restoreNewlinesState();
1514        }
1515    
1516        /*
1517         * : "continue" getEntryPoint?
1518         * : "break" getEntryPoint?
1519         */
1520        private void parseJump(KtNodeType type) {
1521            assert _at(BREAK_KEYWORD) || _at(CONTINUE_KEYWORD);
1522    
1523            PsiBuilder.Marker marker = mark();
1524    
1525            advance(); // BREAK_KEYWORD or CONTINUE_KEYWORD
1526    
1527            parseLabelReferenceWithNoWhitespace();
1528    
1529            marker.done(type);
1530        }
1531    
1532        /*
1533         * "return" getEntryPoint? element?
1534         */
1535        private void parseReturn() {
1536            assert _at(RETURN_KEYWORD);
1537    
1538            PsiBuilder.Marker returnExpression = mark();
1539    
1540            advance(); // RETURN_KEYWORD
1541    
1542            parseLabelReferenceWithNoWhitespace();
1543    
1544            if (atSet(EXPRESSION_FIRST) && !at(EOL_OR_SEMICOLON)) parseExpression();
1545    
1546            returnExpression.done(RETURN);
1547        }
1548    
1549        /*
1550         * labelReference?
1551         */
1552        private void parseLabelReferenceWithNoWhitespace() {
1553            if (at(AT) && !myBuilder.newlineBeforeCurrentToken()) {
1554                if (WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(-1))) {
1555                    error("There should be no space or comments before '@' in label reference");
1556                }
1557                parseLabelReference();
1558            }
1559        }
1560    
1561        /*
1562         * IDENTIFIER "@"
1563         */
1564        private void parseLabelDefinition() {
1565            if (at(AT)) {
1566                // recovery for empty label identifier
1567                errorAndAdvance("Label must be named"); // AT
1568                return;
1569            }
1570    
1571            PsiBuilder.Marker labelWrap = mark();
1572            PsiBuilder.Marker mark = mark();
1573    
1574            assert _at(IDENTIFIER) && myBuilder.rawLookup(1) == AT : "Callers must check that current token is IDENTIFIER followed with '@'";
1575    
1576            advance(); // IDENTIFIER
1577            advance(); // AT
1578    
1579            mark.done(LABEL);
1580    
1581            labelWrap.done(LABEL_QUALIFIER);
1582        }
1583    
1584        /*
1585         * "@" IDENTIFIER
1586         */
1587        private void parseLabelReference() {
1588            assert _at(AT);
1589    
1590            PsiBuilder.Marker labelWrap = mark();
1591    
1592            PsiBuilder.Marker mark = mark();
1593    
1594            if (myBuilder.rawLookup(1) != IDENTIFIER) {
1595                errorAndAdvance("Label must be named"); // AT
1596                labelWrap.drop();
1597                mark.drop();
1598                return;
1599            }
1600    
1601            advance(); // AT
1602            advance(); // IDENTIFIER
1603    
1604            mark.done(LABEL);
1605    
1606            labelWrap.done(LABEL_QUALIFIER);
1607        }
1608    
1609        /*
1610         * : "throw" element
1611         */
1612        private void parseThrow() {
1613            assert _at(THROW_KEYWORD);
1614    
1615            PsiBuilder.Marker marker = mark();
1616    
1617            advance(); // THROW_KEYWORD
1618    
1619            parseExpression();
1620    
1621            marker.done(THROW);
1622        }
1623    
1624        /*
1625         * "(" expression ")"
1626         */
1627        private void parseParenthesizedExpression() {
1628            assert _at(LPAR);
1629    
1630            PsiBuilder.Marker mark = mark();
1631    
1632            myBuilder.disableNewlines();
1633            advance(); // LPAR
1634            if (at(RPAR)) {
1635                error("Expecting an expression");
1636            }
1637            else {
1638                parseExpression();
1639            }
1640    
1641            expect(RPAR, "Expecting ')'");
1642            myBuilder.restoreNewlinesState();
1643    
1644            mark.done(PARENTHESIZED);
1645        }
1646    
1647        /*
1648         * "this" label?
1649         */
1650        private void parseThisExpression() {
1651            assert _at(THIS_KEYWORD);
1652            PsiBuilder.Marker mark = mark();
1653    
1654            PsiBuilder.Marker thisReference = mark();
1655            advance(); // THIS_KEYWORD
1656            thisReference.done(REFERENCE_EXPRESSION);
1657    
1658            parseLabelReferenceWithNoWhitespace();
1659    
1660            mark.done(THIS_EXPRESSION);
1661        }
1662    
1663        /*
1664         * "this" ("<" type ">")? label?
1665         */
1666        private void parseSuperExpression() {
1667            assert _at(SUPER_KEYWORD);
1668            PsiBuilder.Marker mark = mark();
1669    
1670            PsiBuilder.Marker superReference = mark();
1671            advance(); // SUPER_KEYWORD
1672            superReference.done(REFERENCE_EXPRESSION);
1673    
1674            if (at(LT)) {
1675                // This may be "super < foo" or "super<foo>", thus the backtracking
1676                PsiBuilder.Marker supertype = mark();
1677    
1678                myBuilder.disableNewlines();
1679                advance(); // LT
1680    
1681                myJetParsing.parseTypeRef();
1682    
1683                if (at(GT)) {
1684                    advance(); // GT
1685                    supertype.drop();
1686                }
1687                else {
1688                    supertype.rollbackTo();
1689                }
1690                myBuilder.restoreNewlinesState();
1691            }
1692            parseLabelReferenceWithNoWhitespace();
1693    
1694            mark.done(SUPER_EXPRESSION);
1695        }
1696    
1697        /*
1698         * valueArguments
1699         *   : "(" (SimpleName "=")? "*"? element{","} ")"
1700         *   ;
1701         */
1702        public void parseValueArgumentList() {
1703            PsiBuilder.Marker list = mark();
1704    
1705            myBuilder.disableNewlines();
1706    
1707            if (expect(LPAR, "Expecting an argument list", EXPRESSION_FOLLOW)) {
1708                if (!at(RPAR)) {
1709                    while (true) {
1710                        while (at(COMMA)) errorAndAdvance("Expecting an argument");
1711                        parseValueArgument();
1712                        if (at(COLON) && lookahead(1) == IDENTIFIER) {
1713                            errorAndAdvance("Unexpected type specification", 2);
1714                        }
1715                        if (!at(COMMA)) break;
1716                        advance(); // COMMA
1717                        if (at(RPAR)) {
1718                            error("Expecting an argument");
1719                            break;
1720                        }
1721                    }
1722                }
1723    
1724                expect(RPAR, "Expecting ')'", EXPRESSION_FOLLOW);
1725            }
1726    
1727            myBuilder.restoreNewlinesState();
1728    
1729            list.done(VALUE_ARGUMENT_LIST);
1730        }
1731    
1732        /*
1733         * (SimpleName "=")? "*"? element
1734         */
1735        private void parseValueArgument() {
1736            PsiBuilder.Marker argument = mark();
1737            if (at(IDENTIFIER) && lookahead(1) == EQ) {
1738                PsiBuilder.Marker argName = mark();
1739                PsiBuilder.Marker reference = mark();
1740                advance(); // IDENTIFIER
1741                reference.done(REFERENCE_EXPRESSION);
1742                argName.done(VALUE_ARGUMENT_NAME);
1743                advance(); // EQ
1744            }
1745            if (at(MUL)) {
1746                advance(); // MUL
1747            }
1748            parseExpression();
1749            argument.done(VALUE_ARGUMENT);
1750        }
1751    
1752        /*
1753         * "object" (":" delegationSpecifier{","})? classBody // Cannot make class body optional: foo(object : F, A)
1754         */
1755        public void parseObjectLiteral() {
1756            PsiBuilder.Marker literal = mark();
1757            PsiBuilder.Marker declaration = mark();
1758            myJetParsing.parseObject(NameParsingMode.PROHIBITED, false); // Body is not optional because of foo(object : A, B)
1759            declaration.done(OBJECT_DECLARATION);
1760            literal.done(OBJECT_LITERAL);
1761        }
1762    
1763        private void parseOneTokenExpression(KtNodeType type) {
1764            PsiBuilder.Marker mark = mark();
1765            advance();
1766            mark.done(type);
1767        }
1768    
1769        @Override
1770        protected KotlinParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
1771            return myJetParsing.create(builder);
1772        }
1773    
1774        private boolean interruptedWithNewLine() {
1775            return !ALLOW_NEWLINE_OPERATIONS.contains(tt()) && myBuilder.newlineBeforeCurrentToken();
1776        }
1777    }