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 }