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