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