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