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