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