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 }