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