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 PsiBuilder.Marker argument = mark(); 520 if (!at(LBRACE)) { 521 assert _at(LABEL_IDENTIFIER); 522 parseLabeledExpression(); 523 } 524 else { 525 parseFunctionLiteral(); 526 } 527 argument.done(FUNCTION_LITERAL_ARGUMENT); 528 success = true; 529 } 530 531 return success; 532 } 533 534 /* 535 * atomicExpression 536 * : tupleLiteral // or parenthesized element 537 * : "this" label? 538 * : "super" ("<" type ">")? label? 539 * : objectLiteral 540 * : jump 541 * : if 542 * : when 543 * : try 544 * : loop 545 * : literalConstant 546 * : functionLiteral 547 * : declaration 548 * : SimpleName 549 * : "package" // for the root package 550 * ; 551 */ 552 private void parseAtomicExpression() { 553 // System.out.println("atom at " + myBuilder.getTokenText()); 554 555 if (at(LPAR)) { 556 parseParenthesizedExpression(); 557 } 558 else if (at(HASH)) { 559 parseTupleExpression(); 560 } 561 else if (at(PACKAGE_KEYWORD)) { 562 parseOneTokenExpression(ROOT_PACKAGE); 563 } 564 else if (at(THIS_KEYWORD)) { 565 parseThisExpression(); 566 } 567 else if (at(SUPER_KEYWORD)) { 568 parseSuperExpression(); 569 } 570 else if (at(OBJECT_KEYWORD)) { 571 parseObjectLiteral(); 572 } 573 else if (at(THROW_KEYWORD)) { 574 parseThrow(); 575 } 576 else if (at(RETURN_KEYWORD)) { 577 parseReturn(); 578 } 579 else if (at(CONTINUE_KEYWORD)) { 580 parseJump(CONTINUE); 581 } 582 else if (at(BREAK_KEYWORD)) { 583 parseJump(BREAK); 584 } 585 else if (at(IF_KEYWORD)) { 586 parseIf(); 587 } 588 else if (at(WHEN_KEYWORD)) { 589 parseWhen(); 590 } 591 else if (at(TRY_KEYWORD)) { 592 parseTry(); 593 } 594 else if (at(FOR_KEYWORD)) { 595 parseFor(); 596 } 597 else if (at(WHILE_KEYWORD)) { 598 parseWhile(); 599 } 600 else if (at(DO_KEYWORD)) { 601 parseDoWhile(); 602 } 603 else if (atSet(CLASS_KEYWORD, FUN_KEYWORD, VAL_KEYWORD, 604 VAR_KEYWORD, TYPE_KEYWORD)) { 605 parseLocalDeclaration(); 606 } 607 else if (at(FIELD_IDENTIFIER)) { 608 parseSimpleNameExpression(); 609 } 610 else if (at(IDENTIFIER)) { 611 parseSimpleNameExpression(); 612 } 613 else if (at(LBRACE)) { 614 parseFunctionLiteral(); 615 } 616 else if (at(OPEN_QUOTE)) { 617 parseStringTemplate(); 618 } 619 else if (!parseLiteralConstant()) { 620 // TODO: better recovery if FIRST(element) did not match 621 errorWithRecovery("Expecting an element", EXPRESSION_FOLLOW); 622 } 623 } 624 625 /* 626 * stringTemplate 627 * : OPEN_QUOTE stringTemplateElement* CLOSING_QUOTE 628 * ; 629 */ 630 private void parseStringTemplate() { 631 assert _at(OPEN_QUOTE); 632 633 PsiBuilder.Marker template = mark(); 634 635 advance(); // OPEN_QUOTE 636 637 while (!eof()) { 638 if (at(CLOSING_QUOTE) || at(DANGLING_NEWLINE)) { 639 break; 640 } 641 parseStringTemplateElement(); 642 } 643 644 if (at(DANGLING_NEWLINE)) { 645 errorAndAdvance("Expecting '\"'"); 646 } 647 else { 648 expect(CLOSING_QUOTE, "Expecting '\"'"); 649 } 650 template.done(STRING_TEMPLATE); 651 } 652 653 /* 654 * stringTemplateElement 655 * : RegularStringPart 656 * : ShortTemplateEntrySTART (SimpleName | "this") 657 * : EscapeSequence 658 * : longTemplate 659 * ; 660 * 661 * longTemplate 662 * : "${" expression "}" 663 * ; 664 */ 665 private void parseStringTemplateElement() { 666 if (at(REGULAR_STRING_PART)) { 667 PsiBuilder.Marker mark = mark(); 668 advance(); // REGULAR_STRING_PART 669 mark.done(LITERAL_STRING_TEMPLATE_ENTRY); 670 } 671 else if (at(ESCAPE_SEQUENCE)) { 672 PsiBuilder.Marker mark = mark(); 673 advance(); // ESCAPE_SEQUENCE 674 mark.done(ESCAPE_STRING_TEMPLATE_ENTRY); 675 } 676 else if (at(SHORT_TEMPLATE_ENTRY_START)) { 677 PsiBuilder.Marker entry = mark(); 678 advance(); // SHORT_TEMPLATE_ENTRY_START 679 680 if (at(THIS_KEYWORD)) { 681 PsiBuilder.Marker thisExpression = mark(); 682 PsiBuilder.Marker reference = mark(); 683 advance(); // THIS_KEYWORD 684 reference.done(REFERENCE_EXPRESSION); 685 thisExpression.done(THIS_EXPRESSION); 686 } 687 else { 688 JetToken keyword = KEYWORD_TEXTS.get(myBuilder.getTokenText()); 689 if (keyword != null) { 690 myBuilder.remapCurrentToken(keyword); 691 errorAndAdvance("Keyword cannot be used as a reference"); 692 } 693 else { 694 PsiBuilder.Marker reference = mark(); 695 expect(IDENTIFIER, "Expecting a name"); 696 reference.done(REFERENCE_EXPRESSION); 697 } 698 } 699 700 entry.done(SHORT_STRING_TEMPLATE_ENTRY); 701 } 702 else if (at(LONG_TEMPLATE_ENTRY_START)) { 703 PsiBuilder.Marker longTemplateEntry = mark(); 704 705 advance(); // LONG_TEMPLATE_ENTRY_START 706 707 parseExpression(); 708 709 expect(LONG_TEMPLATE_ENTRY_END, "Expecting '}'", TokenSet.create(CLOSING_QUOTE, DANGLING_NEWLINE, REGULAR_STRING_PART, ESCAPE_SEQUENCE, SHORT_TEMPLATE_ENTRY_START)); 710 longTemplateEntry.done(LONG_STRING_TEMPLATE_ENTRY); 711 } 712 else { 713 errorAndAdvance("Unexpected token in a string template"); 714 } 715 } 716 717 /* 718 * literalConstant 719 * : "true" | "false" 720 * : StringWithTemplates 721 * : NoEscapeString 722 * : IntegerLiteral 723 * : LongLiteral 724 * : CharacterLiteral 725 * : FloatLiteral 726 * : "null" 727 * ; 728 */ 729 private boolean parseLiteralConstant() { 730 if (at(TRUE_KEYWORD) || at(FALSE_KEYWORD)) { 731 parseOneTokenExpression(BOOLEAN_CONSTANT); 732 } 733 else if (at(INTEGER_LITERAL)) { 734 parseOneTokenExpression(INTEGER_CONSTANT); 735 } 736 else if (at(CHARACTER_LITERAL)) { 737 parseOneTokenExpression(CHARACTER_CONSTANT); 738 } 739 else if (at(FLOAT_LITERAL)) { 740 parseOneTokenExpression(FLOAT_CONSTANT); 741 } 742 else if (at(NULL_KEYWORD)) { 743 parseOneTokenExpression(NULL); 744 } 745 else { 746 return false; 747 } 748 return true; 749 } 750 751 /* 752 * when 753 * : "when" ("(" (modifiers "val" SimpleName "=")? element ")")? "{" 754 * whenEntry* 755 * "}" 756 * ; 757 */ 758 private void parseWhen() { 759 assert _at(WHEN_KEYWORD); 760 761 PsiBuilder.Marker when = mark(); 762 763 advance(); // WHEN_KEYWORD 764 765 // Parse condition 766 myBuilder.disableNewlines(); 767 if (at(LPAR)) { 768 advanceAt(LPAR); 769 770 int valPos = matchTokenStreamPredicate(new FirstBefore(new At(VAL_KEYWORD), new AtSet(RPAR, LBRACE, RBRACE, SEMICOLON, EQ))); 771 if (valPos >= 0) { 772 PsiBuilder.Marker property = mark(); 773 myJetParsing.parseModifierList(MODIFIER_LIST, true); 774 myJetParsing.parseProperty(true); 775 property.done(PROPERTY); 776 } 777 else { 778 parseExpression(); 779 } 780 781 expect(RPAR, "Expecting ')'"); 782 } 783 myBuilder.restoreNewlinesState(); 784 785 // Parse when block 786 myBuilder.enableNewlines(); 787 if (expect(LBRACE, "Expecting '{'")) { 788 while (!eof() && !at(RBRACE)) { 789 parseWhenEntry(); 790 } 791 792 expect(RBRACE, "Expecting '}'"); 793 } 794 myBuilder.restoreNewlinesState(); 795 796 when.done(WHEN); 797 } 798 799 /* 800 * whenEntry 801 * // TODO : consider empty after -> 802 * : whenCondition{","} "->" element SEMI 803 * : "else" "->" element SEMI 804 * ; 805 */ 806 private void parseWhenEntry() { 807 PsiBuilder.Marker entry = mark(); 808 809 if (at(ELSE_KEYWORD)) { 810 advance(); // ELSE_KEYWORD 811 812 if (!at(ARROW)) { 813 errorUntil("Expecting '->'", TokenSet.create(ARROW, 814 RBRACE, EOL_OR_SEMICOLON)); 815 } 816 817 if (at(ARROW)) { 818 advance(); // ARROW 819 820 if (atSet(WHEN_CONDITION_RECOVERY_SET)) { 821 error("Expecting an element"); 822 } 823 else { 824 parseExpressionPreferringBlocks(); 825 } 826 } 827 else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) { 828 errorAndAdvance("Expecting '->'"); 829 } 830 } 831 else { 832 parseWhenEntryNotElse(); 833 } 834 835 entry.done(WHEN_ENTRY); 836 consumeIf(SEMICOLON); 837 } 838 839 /* 840 * : whenCondition{","} "->" element SEMI 841 */ 842 private void parseWhenEntryNotElse() { 843 while (true) { 844 while (at(COMMA)) errorAndAdvance("Expecting a when-condition"); 845 parseWhenCondition(); 846 if (!at(COMMA)) break; 847 advance(); // COMMA 848 } 849 850 expect(ARROW, "Expecting '->' or 'when'", WHEN_CONDITION_RECOVERY_SET); 851 if (atSet(WHEN_CONDITION_RECOVERY_SET)) { 852 error("Expecting an element"); 853 } 854 else { 855 parseExpressionPreferringBlocks(); 856 } 857 // SEMI is consumed in parseWhenEntry 858 } 859 860 /* 861 * whenCondition 862 * : expression 863 * : ("in" | "!in") expression 864 * : ("is" | "!is") isRHS 865 * ; 866 */ 867 private void parseWhenCondition() { 868 PsiBuilder.Marker condition = mark(); 869 myBuilder.disableNewlines(); 870 if (at(IN_KEYWORD) || at(NOT_IN)) { 871 PsiBuilder.Marker mark = mark(); 872 advance(); // IN_KEYWORD or NOT_IN 873 mark.done(OPERATION_REFERENCE); 874 875 876 if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) { 877 error("Expecting an element"); 878 } 879 else { 880 parseExpression(); 881 } 882 condition.done(WHEN_CONDITION_IN_RANGE); 883 } 884 else if (at(IS_KEYWORD) || at(NOT_IS)) { 885 advance(); // IS_KEYWORD or NOT_IS 886 887 if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) { 888 error("Expecting a type"); 889 } 890 else { 891 myJetParsing.parseTypeRef(); 892 } 893 condition.done(WHEN_CONDITION_IS_PATTERN); 894 } 895 else { 896 if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) { 897 error("Expecting an expression, is-condition or in-condition"); 898 } 899 else { 900 parseExpression(); 901 } 902 condition.done(WHEN_CONDITION_EXPRESSION); 903 } 904 myBuilder.restoreNewlinesState(); 905 } 906 907 /* 908 * arrayAccess 909 * : "[" element{","} "]" 910 * ; 911 */ 912 private void parseArrayAccess() { 913 assert _at(LBRACKET); 914 915 PsiBuilder.Marker indices = mark(); 916 917 myBuilder.disableNewlines(); 918 advance(); // LBRACKET 919 920 while (true) { 921 if (at(COMMA)) errorAndAdvance("Expecting an index element"); 922 if (at(RBRACKET)) { 923 error("Expecting an index element"); 924 break; 925 } 926 parseExpression(); 927 if (!at(COMMA)) break; 928 advance(); // COMMA 929 } 930 931 expect(RBRACKET, "Expecting ']'"); 932 myBuilder.restoreNewlinesState(); 933 934 indices.done(INDICES); 935 } 936 937 /* 938 * SimpleName 939 */ 940 public void parseSimpleNameExpression() { 941 PsiBuilder.Marker simpleName = mark(); 942 if (at(FIELD_IDENTIFIER)) { 943 advance(); // 944 } 945 else { 946 expect(IDENTIFIER, "Expecting an identifier"); 947 } 948 simpleName.done(REFERENCE_EXPRESSION); 949 } 950 951 /* 952 * modifiers declarationRest 953 */ 954 private boolean parseLocalDeclaration() { 955 PsiBuilder.Marker decl = mark(); 956 JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD); 957 myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector, false); 958 959 IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected()); 960 961 if (declType != null) { 962 decl.done(declType); 963 return true; 964 } 965 else { 966 decl.rollbackTo(); 967 return false; 968 } 969 } 970 971 /* 972 * functionLiteral // one can use "it" as a parameter name 973 * : "{" expressions "}" 974 * : "{" (modifiers SimpleName){","} "->" statements "}" 975 * : "{" (type ".")? "(" (modifiers SimpleName (":" type)?){","} ")" (":" type)? "->" expressions "}" 976 * ; 977 */ 978 private void parseFunctionLiteral() { 979 parseFunctionLiteral(false); 980 } 981 982 private void parseFunctionLiteral(boolean preferBlock) { 983 assert _at(LBRACE); 984 985 PsiBuilder.Marker literalExpression = mark(); 986 987 PsiBuilder.Marker literal = mark(); 988 989 myBuilder.enableNewlines(); 990 advance(); // LBRACE 991 992 boolean paramsFound = false; 993 994 if (at(ARROW)) { 995 // { -> ...} 996 mark().done(VALUE_PARAMETER_LIST); 997 advance(); // ARROW 998 paramsFound = true; 999 } 1000 else if (at(LPAR)) { 1001 // Look for ARROW after matching RPAR 1002 // {(a, b) -> ...} 1003 1004 { 1005 boolean preferParamsToExpressions = isConfirmedParametersByComma(); 1006 1007 PsiBuilder.Marker rollbackMarker = mark(); 1008 parseFunctionLiteralParametersAndType(); 1009 1010 paramsFound = preferParamsToExpressions ? 1011 rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : 1012 rollbackOrDropAt(rollbackMarker, ARROW); 1013 } 1014 1015 if (!paramsFound) { 1016 // If not found, try a typeRef DOT and then LPAR .. RPAR ARROW 1017 // {((A) -> B).(x) -> ... } 1018 paramsFound = parseFunctionTypeDotParametersAndType(); 1019 } 1020 } 1021 else { 1022 if (at(IDENTIFIER)) { 1023 // Try to parse a simple name list followed by an ARROW 1024 // {a -> ...} 1025 // {a, b -> ...} 1026 PsiBuilder.Marker rollbackMarker = mark(); 1027 boolean preferParamsToExpressions = (lookahead(1) == COMMA); 1028 parseFunctionLiteralShorthandParameterList(); 1029 parseOptionalFunctionLiteralType(); 1030 1031 paramsFound = preferParamsToExpressions ? 1032 rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : 1033 rollbackOrDropAt(rollbackMarker, ARROW); 1034 } 1035 if (!paramsFound && atSet(JetParsing.TYPE_REF_FIRST)) { 1036 // Try to parse a type DOT valueParameterList ARROW 1037 // {A.(b) -> ...} 1038 paramsFound = parseFunctionTypeDotParametersAndType(); 1039 } 1040 } 1041 1042 if (!paramsFound) { 1043 if (preferBlock) { 1044 literal.drop(); 1045 parseStatements(); 1046 expect(RBRACE, "Expecting '}'"); 1047 literalExpression.done(BLOCK); 1048 myBuilder.restoreNewlinesState(); 1049 1050 return; 1051 } 1052 } 1053 1054 PsiBuilder.Marker body = mark(); 1055 parseStatements(); 1056 body.done(BLOCK); 1057 1058 expect(RBRACE, "Expecting '}'"); 1059 myBuilder.restoreNewlinesState(); 1060 1061 literal.done(FUNCTION_LITERAL); 1062 literalExpression.done(FUNCTION_LITERAL_EXPRESSION); 1063 } 1064 1065 private boolean rollbackOrDropAt(PsiBuilder.Marker rollbackMarker, IElementType dropAt) { 1066 if (at(dropAt)) { 1067 advance(); // dropAt 1068 rollbackMarker.drop(); 1069 return true; 1070 } 1071 rollbackMarker.rollbackTo(); 1072 return false; 1073 } 1074 1075 private boolean rollbackOrDrop(PsiBuilder.Marker rollbackMarker, 1076 JetToken expected, String expectMessage, 1077 IElementType validForDrop) { 1078 if (at(expected)) { 1079 advance(); // dropAt 1080 rollbackMarker.drop(); 1081 return true; 1082 } 1083 else if (at(validForDrop)) { 1084 rollbackMarker.drop(); 1085 expect(expected, expectMessage); 1086 return true; 1087 } 1088 1089 rollbackMarker.rollbackTo(); 1090 return false; 1091 } 1092 1093 1094 /* 1095 * SimpleName{,} 1096 */ 1097 private void parseFunctionLiteralShorthandParameterList() { 1098 PsiBuilder.Marker parameterList = mark(); 1099 1100 while (!eof()) { 1101 PsiBuilder.Marker parameter = mark(); 1102 1103 // int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos))); 1104 // createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false); 1105 1106 expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW)); 1107 1108 parameter.done(VALUE_PARAMETER); 1109 1110 if (at(COLON)) { 1111 PsiBuilder.Marker errorMarker = mark(); 1112 advance(); // COLON 1113 myJetParsing.parseTypeRef(); 1114 errorMarker.error("To specify a type of a parameter or a return type, use the full notation: {(parameter : Type) : ReturnType -> ...}"); 1115 } 1116 else if (at(ARROW)) { 1117 break; 1118 } 1119 else if (at(COMMA)) { 1120 advance(); // COMMA 1121 } 1122 else { 1123 error("Expecting '->' or ','"); 1124 break; 1125 } 1126 } 1127 1128 parameterList.done(VALUE_PARAMETER_LIST); 1129 } 1130 1131 // Check that position is followed by top level comma. It can't be expression and we want it be 1132 // parsed as parameters in function literal 1133 private boolean isConfirmedParametersByComma() { 1134 assert _at(LPAR); 1135 PsiBuilder.Marker lparMarker = mark(); 1136 advance(); // LPAR 1137 int comma = matchTokenStreamPredicate(new FirstBefore(new At(COMMA), new AtSet(ARROW, RPAR))); 1138 lparMarker.rollbackTo(); 1139 return comma > 0; 1140 } 1141 1142 private boolean parseFunctionTypeDotParametersAndType() { 1143 PsiBuilder.Marker rollbackMarker = mark(); 1144 1145 // True when it's confirmed that body of literal can't be simple expressions and we prefer to parse 1146 // it to function params if possible. 1147 boolean preferParamsToExpressions = false; 1148 1149 int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtSet(ARROW, RPAR))); 1150 if (lastDot >= 0) { 1151 createTruncatedBuilder(lastDot).parseTypeRef(); 1152 if (at(DOT)) { 1153 advance(); // DOT 1154 1155 if (at(LPAR)) { 1156 preferParamsToExpressions = isConfirmedParametersByComma(); 1157 } 1158 1159 parseFunctionLiteralParametersAndType(); 1160 } 1161 } 1162 1163 return preferParamsToExpressions ? 1164 rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : 1165 rollbackOrDropAt(rollbackMarker, ARROW); 1166 } 1167 1168 private void parseFunctionLiteralParametersAndType() { 1169 parseFunctionLiteralParameterList(); 1170 parseOptionalFunctionLiteralType(); 1171 } 1172 1173 /* 1174 * (":" type)? 1175 */ 1176 private void parseOptionalFunctionLiteralType() { 1177 if (at(COLON)) { 1178 advance(); // COLON 1179 if (at(ARROW)) { 1180 error("Expecting a type"); 1181 } 1182 else { 1183 myJetParsing.parseTypeRef(); 1184 } 1185 } 1186 } 1187 1188 /* 1189 * "(" (modifiers SimpleName (":" type)?){","} ")" 1190 */ 1191 private void parseFunctionLiteralParameterList() { 1192 PsiBuilder.Marker list = mark(); 1193 expect(LPAR, "Expecting a parameter list in parentheses (...)", TokenSet.create(ARROW, COLON)); 1194 1195 myBuilder.disableNewlines(); 1196 1197 if (!at(RPAR)) { 1198 while (true) { 1199 if (at(COMMA)) errorAndAdvance("Expecting a parameter declaration"); 1200 1201 PsiBuilder.Marker parameter = mark(); 1202 int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, ARROW))); 1203 createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false); 1204 1205 expect(IDENTIFIER, "Expecting parameter declaration"); 1206 1207 if (at(COLON)) { 1208 advance(); // COLON 1209 myJetParsing.parseTypeRef(); 1210 } 1211 parameter.done(VALUE_PARAMETER); 1212 if (!at(COMMA)) break; 1213 advance(); // COMMA 1214 1215 if (at(RPAR)) { 1216 error("Expecting a parameter declaration"); 1217 break; 1218 } 1219 } 1220 } 1221 1222 myBuilder.restoreNewlinesState(); 1223 1224 expect(RPAR, "Expecting ')", TokenSet.create(ARROW, COLON)); 1225 list.done(VALUE_PARAMETER_LIST); 1226 } 1227 1228 /* 1229 * expressions 1230 * : SEMI* statement{SEMI+} SEMI* 1231 */ 1232 public void parseStatements() { 1233 while (at(SEMICOLON)) advance(); // SEMICOLON 1234 while (!eof() && !at(RBRACE)) { 1235 if (!atSet(STATEMENT_FIRST)) { 1236 errorAndAdvance("Expecting an element"); 1237 } 1238 if (atSet(STATEMENT_FIRST)) { 1239 parseStatement(); 1240 } 1241 if (at(SEMICOLON)) { 1242 while (at(SEMICOLON)) advance(); // SEMICOLON 1243 } 1244 else if (at(RBRACE)) { 1245 break; 1246 } 1247 else if (!myBuilder.newlineBeforeCurrentToken()) { 1248 String severalStatementsError = "Unexpected tokens (use ';' to separate expressions on the same line)"; 1249 1250 if (atSet(STATEMENT_NEW_LINE_QUICK_RECOVERY_SET)) { 1251 error(severalStatementsError); 1252 } 1253 else { 1254 errorUntil(severalStatementsError, TokenSet.create(EOL_OR_SEMICOLON)); 1255 } 1256 } 1257 } 1258 } 1259 1260 /* 1261 * statement 1262 * : expression 1263 * : declaration 1264 * ; 1265 */ 1266 private void parseStatement() { 1267 if (!parseLocalDeclaration()) { 1268 if (!atSet(EXPRESSION_FIRST)) { 1269 errorAndAdvance("Expecting a statement"); 1270 } 1271 else { 1272 parseExpression(); 1273 } 1274 } 1275 } 1276 1277 /* 1278 * declaration 1279 * : function 1280 * : property 1281 * : extension 1282 * : class 1283 * : typedef 1284 * : object 1285 * ; 1286 */ 1287 private IElementType parseLocalDeclarationRest(boolean isEnum) { 1288 IElementType keywordToken = tt(); 1289 IElementType declType = null; 1290 if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) { 1291 declType = myJetParsing.parseClass(isEnum); 1292 } 1293 else if (keywordToken == FUN_KEYWORD) { 1294 declType = myJetParsing.parseFunction(); 1295 } 1296 else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) { 1297 declType = myJetParsing.parseProperty(true); 1298 } 1299 else if (keywordToken == TYPE_KEYWORD) { 1300 declType = myJetParsing.parseTypeDef(); 1301 } 1302 else if (keywordToken == OBJECT_KEYWORD) { 1303 // Object expression may appear at the statement position: should parse it 1304 // as expression instead of object declaration 1305 // sample: 1306 // { 1307 // object : Thread() { 1308 // } 1309 // } 1310 IElementType lookahead = lookahead(1); 1311 if (lookahead == COLON || lookahead == LBRACE) { 1312 return null; 1313 } 1314 1315 myJetParsing.parseObject(true, true); 1316 declType = OBJECT_DECLARATION; 1317 } 1318 return declType; 1319 } 1320 1321 /* 1322 * doWhile 1323 * : "do" element "while" "(" element ")" 1324 * ; 1325 */ 1326 private void parseDoWhile() { 1327 assert _at(DO_KEYWORD); 1328 1329 PsiBuilder.Marker loop = mark(); 1330 1331 advance(); // DO_KEYWORD 1332 1333 if (!at(WHILE_KEYWORD)) { 1334 parseControlStructureBody(); 1335 } 1336 1337 if (expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition")) { 1338 parseCondition(); 1339 } 1340 1341 loop.done(DO_WHILE); 1342 } 1343 1344 /* 1345 * while 1346 * : "while" "(" element ")" element 1347 * ; 1348 */ 1349 private void parseWhile() { 1350 assert _at(WHILE_KEYWORD); 1351 1352 PsiBuilder.Marker loop = mark(); 1353 1354 advance(); // WHILE_KEYWORD 1355 1356 parseCondition(); 1357 1358 parseControlStructureBody(); 1359 1360 loop.done(WHILE); 1361 } 1362 1363 /* 1364 * for 1365 * : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression 1366 * ; 1367 * 1368 * TODO: empty loop body (at the end of the block)? 1369 */ 1370 private void parseFor() { 1371 assert _at(FOR_KEYWORD); 1372 1373 PsiBuilder.Marker loop = mark(); 1374 1375 advance(); // FOR_KEYWORD 1376 1377 if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) { 1378 myBuilder.disableNewlines(); 1379 1380 if (!at(RPAR)) { 1381 PsiBuilder.Marker parameter = mark(); 1382 if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD 1383 if (at(LPAR)) { 1384 myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE)); 1385 parameter.done(MULTI_VARIABLE_DECLARATION); 1386 } 1387 else { 1388 expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD)); 1389 1390 if (at(COLON)) { 1391 advance(); // COLON 1392 myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD)); 1393 } 1394 parameter.done(VALUE_PARAMETER); 1395 } 1396 1397 if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) { 1398 PsiBuilder.Marker range = mark(); 1399 parseExpression(); 1400 range.done(LOOP_RANGE); 1401 } 1402 } 1403 else { 1404 error("Expecting a variable name"); 1405 } 1406 1407 expectNoAdvance(RPAR, "Expecting ')'"); 1408 myBuilder.restoreNewlinesState(); 1409 } 1410 1411 parseControlStructureBody(); 1412 1413 loop.done(FOR); 1414 } 1415 1416 /** 1417 * If it has no ->, it's a block, otherwise a function literal 1418 */ 1419 private void parseExpressionPreferringBlocks() { 1420 if (at(LBRACE)) { 1421 parseFunctionLiteral(true); 1422 } 1423 else if (at(LABEL_IDENTIFIER) && lookahead(1) == LBRACE ) { 1424 PsiBuilder.Marker mark = mark(); 1425 1426 parseLabel(); 1427 1428 parseFunctionLiteral(true); 1429 1430 mark.done(LABELED_EXPRESSION); 1431 } 1432 else { 1433 parseExpression(); 1434 } 1435 } 1436 1437 /* 1438 * element 1439 */ 1440 private void parseControlStructureBody() { 1441 PsiBuilder.Marker body = mark(); 1442 if (!at(SEMICOLON)) { 1443 parseExpressionPreferringBlocks(); 1444 } 1445 body.done(BODY); 1446 } 1447 1448 /* 1449 * try 1450 * : "try" block catchBlock* finallyBlock? 1451 * ; 1452 * catchBlock 1453 * : "catch" "(" attributes SimpleName ":" userType ")" block 1454 * ; 1455 * 1456 * finallyBlock 1457 * : "finally" block 1458 * ; 1459 */ 1460 private void parseTry() { 1461 assert _at(TRY_KEYWORD); 1462 1463 PsiBuilder.Marker tryExpression = mark(); 1464 1465 advance(); // TRY_KEYWORD 1466 1467 myJetParsing.parseBlock(); 1468 1469 boolean catchOrFinally = false; 1470 while (at(CATCH_KEYWORD)) { 1471 catchOrFinally = true; 1472 PsiBuilder.Marker catchBlock = mark(); 1473 advance(); // CATCH_KEYWORD 1474 1475 TokenSet recoverySet = TokenSet.create(LBRACE, FINALLY_KEYWORD, CATCH_KEYWORD); 1476 if (atSet(recoverySet)) { 1477 error("Expecting exception variable declaration"); 1478 } 1479 else { 1480 PsiBuilder.Marker parameters = mark(); 1481 expect(LPAR, "Expecting '('", recoverySet); 1482 if (!atSet(recoverySet)) { 1483 myJetParsing.parseValueParameter(); 1484 expect(RPAR, "Expecting ')'", recoverySet); 1485 } 1486 else { 1487 error("Expecting exception variable declaration"); 1488 } 1489 parameters.done(VALUE_PARAMETER_LIST); 1490 } 1491 1492 if (at(LBRACE)) { 1493 myJetParsing.parseBlock(); 1494 } 1495 else { 1496 error("Expecting a block: { ... }"); 1497 } 1498 catchBlock.done(CATCH); 1499 } 1500 1501 if (at(FINALLY_KEYWORD)) { 1502 catchOrFinally = true; 1503 PsiBuilder.Marker finallyBlock = mark(); 1504 1505 advance(); // FINALLY_KEYWORD 1506 1507 myJetParsing.parseBlock(); 1508 1509 finallyBlock.done(FINALLY); 1510 } 1511 1512 if (!catchOrFinally) { 1513 error("Expecting 'catch' or 'finally'"); 1514 } 1515 1516 tryExpression.done(TRY); 1517 } 1518 1519 /* 1520 * if 1521 * : "if" "(" element ")" element SEMI? ("else" element)? 1522 * ; 1523 */ 1524 private void parseIf() { 1525 assert _at(IF_KEYWORD); 1526 1527 PsiBuilder.Marker marker = mark(); 1528 1529 advance(); //IF_KEYWORD 1530 1531 parseCondition(); 1532 1533 PsiBuilder.Marker thenBranch = mark(); 1534 if (!at(ELSE_KEYWORD) && !at(SEMICOLON)) { 1535 parseExpressionPreferringBlocks(); 1536 } 1537 if (at(SEMICOLON) && lookahead(1) == ELSE_KEYWORD) { 1538 advance(); // SEMICOLON 1539 } 1540 thenBranch.done(THEN); 1541 1542 if (at(ELSE_KEYWORD)) { 1543 advance(); // ELSE_KEYWORD 1544 1545 PsiBuilder.Marker elseBranch = mark(); 1546 if (!at(SEMICOLON)) { 1547 parseExpressionPreferringBlocks(); 1548 } 1549 elseBranch.done(ELSE); 1550 } 1551 1552 marker.done(IF); 1553 } 1554 1555 /* 1556 * "(" element ")" 1557 */ 1558 private void parseCondition() { 1559 myBuilder.disableNewlines(); 1560 1561 if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) { 1562 PsiBuilder.Marker condition = mark(); 1563 parseExpression(); 1564 condition.done(CONDITION); 1565 expect(RPAR, "Expecting ')"); 1566 } 1567 1568 myBuilder.restoreNewlinesState(); 1569 } 1570 1571 /* 1572 * : "continue" getEntryPoint? 1573 * : "break" getEntryPoint? 1574 */ 1575 private void parseJump(JetNodeType type) { 1576 assert _at(BREAK_KEYWORD) || _at(CONTINUE_KEYWORD); 1577 1578 PsiBuilder.Marker marker = mark(); 1579 1580 advance(); // BREAK_KEYWORD or CONTINUE_KEYWORD 1581 1582 parseLabelOnTheSameLine(); 1583 1584 marker.done(type); 1585 } 1586 1587 /* 1588 * "return" getEntryPoint? element? 1589 */ 1590 private void parseReturn() { 1591 assert _at(RETURN_KEYWORD); 1592 1593 PsiBuilder.Marker returnExpression = mark(); 1594 1595 advance(); // RETURN_KEYWORD 1596 1597 parseLabelOnTheSameLine(); 1598 1599 if (atSet(EXPRESSION_FIRST) && !at(EOL_OR_SEMICOLON)) parseExpression(); 1600 1601 returnExpression.done(RETURN); 1602 } 1603 1604 /* 1605 * label? 1606 */ 1607 private void parseLabelOnTheSameLine() { 1608 if (!eol() && at(LABEL_IDENTIFIER)) { 1609 parseLabel(); 1610 } 1611 } 1612 1613 /* 1614 * label 1615 */ 1616 private void parseLabel() { 1617 assert _at(LABEL_IDENTIFIER); 1618 1619 String labelText = myBuilder.getTokenText(); 1620 if ("@".equals(labelText)) { 1621 errorAndAdvance("Label must be named"); 1622 return; 1623 } 1624 1625 PsiBuilder.Marker labelWrap = mark(); 1626 1627 PsiBuilder.Marker mark = mark(); 1628 advance(); // LABEL_IDENTIFIER 1629 mark.done(LABEL); 1630 1631 labelWrap.done(LABEL_QUALIFIER); 1632 } 1633 1634 /* 1635 * : "throw" element 1636 */ 1637 private void parseThrow() { 1638 assert _at(THROW_KEYWORD); 1639 1640 PsiBuilder.Marker marker = mark(); 1641 1642 advance(); // THROW_KEYWORD 1643 1644 parseExpression(); 1645 1646 marker.done(THROW); 1647 } 1648 1649 /* 1650 * "(" expression ")" 1651 */ 1652 private void parseParenthesizedExpression() { 1653 assert _at(LPAR); 1654 1655 PsiBuilder.Marker mark = mark(); 1656 1657 myBuilder.disableNewlines(); 1658 advance(); // LPAR 1659 if (at(RPAR)) { 1660 error("Expecting an expression"); 1661 } 1662 else { 1663 parseExpression(); 1664 } 1665 1666 expect(RPAR, "Expecting ')'"); 1667 myBuilder.restoreNewlinesState(); 1668 1669 mark.done(PARENTHESIZED); 1670 } 1671 1672 /* 1673 * tupleLiteral 1674 * : "#" "(" (((SimpleName "=")? expression){","})? ")" 1675 * ; 1676 */ 1677 @Deprecated // Tuples are dropped, but parsing is left to minimize surprising. This code should be removed some time (in Kotlin 1.0?) 1678 private void parseTupleExpression() { 1679 assert _at(HASH); 1680 PsiBuilder.Marker mark = mark(); 1681 1682 advance(); // HASH 1683 advance(); // LPAR 1684 myBuilder.disableNewlines(); 1685 if (!at(RPAR)) { 1686 while (true) { 1687 while (at(COMMA)) { 1688 advance(); 1689 } 1690 1691 if (at(IDENTIFIER) && lookahead(1) == EQ) { 1692 advance(); // IDENTIFIER 1693 advance(); // EQ 1694 parseExpression(); 1695 } 1696 else { 1697 parseExpression(); 1698 } 1699 1700 if (!at(COMMA)) break; 1701 advance(); // COMMA 1702 1703 if (at(RPAR)) { 1704 break; 1705 } 1706 } 1707 1708 } 1709 consumeIf(RPAR); 1710 myBuilder.restoreNewlinesState(); 1711 1712 mark.error("Tuples are not supported. Use data classes instead."); 1713 } 1714 1715 /* 1716 * "this" label? 1717 */ 1718 private void parseThisExpression() { 1719 assert _at(THIS_KEYWORD); 1720 PsiBuilder.Marker mark = mark(); 1721 1722 PsiBuilder.Marker thisReference = mark(); 1723 advance(); // THIS_KEYWORD 1724 thisReference.done(REFERENCE_EXPRESSION); 1725 1726 parseLabelOnTheSameLine(); 1727 1728 mark.done(THIS_EXPRESSION); 1729 } 1730 1731 /* 1732 * "this" ("<" type ">")? label? 1733 */ 1734 private void parseSuperExpression() { 1735 assert _at(SUPER_KEYWORD); 1736 PsiBuilder.Marker mark = mark(); 1737 1738 PsiBuilder.Marker superReference = mark(); 1739 advance(); // SUPER_KEYWORD 1740 superReference.done(REFERENCE_EXPRESSION); 1741 1742 if (at(LT)) { 1743 // This may be "super < foo" or "super<foo>", thus the backtracking 1744 PsiBuilder.Marker supertype = mark(); 1745 1746 myBuilder.disableNewlines(); 1747 advance(); // LT 1748 1749 myJetParsing.parseTypeRef(); 1750 1751 if (at(GT)) { 1752 advance(); // GT 1753 supertype.drop(); 1754 } 1755 else { 1756 supertype.rollbackTo(); 1757 } 1758 myBuilder.restoreNewlinesState(); 1759 } 1760 parseLabelOnTheSameLine(); 1761 1762 mark.done(SUPER_EXPRESSION); 1763 } 1764 1765 /* 1766 * valueArguments 1767 * : "(" (SimpleName "=")? "*"? element{","} ")" 1768 * ; 1769 */ 1770 public void parseValueArgumentList() { 1771 PsiBuilder.Marker list = mark(); 1772 1773 myBuilder.disableNewlines(); 1774 1775 if (expect(LPAR, "Expecting an argument list", EXPRESSION_FOLLOW)) { 1776 if (!at(RPAR)) { 1777 while (true) { 1778 while (at(COMMA)) errorAndAdvance("Expecting an argument"); 1779 parseValueArgument(); 1780 if (!at(COMMA)) break; 1781 advance(); // COMMA 1782 if (at(RPAR)) { 1783 error("Expecting an argument"); 1784 break; 1785 } 1786 } 1787 } 1788 1789 expect(RPAR, "Expecting ')'", EXPRESSION_FOLLOW); 1790 } 1791 1792 myBuilder.restoreNewlinesState(); 1793 1794 list.done(VALUE_ARGUMENT_LIST); 1795 } 1796 1797 /* 1798 * (SimpleName "=")? "*"? element 1799 */ 1800 private void parseValueArgument() { 1801 PsiBuilder.Marker argument = mark(); 1802 if (at(IDENTIFIER) && lookahead(1) == EQ) { 1803 PsiBuilder.Marker argName = mark(); 1804 PsiBuilder.Marker reference = mark(); 1805 advance(); // IDENTIFIER 1806 reference.done(REFERENCE_EXPRESSION); 1807 argName.done(VALUE_ARGUMENT_NAME); 1808 advance(); // EQ 1809 } 1810 if (at(MUL)) { 1811 advance(); // MUL 1812 } 1813 parseExpression(); 1814 argument.done(VALUE_ARGUMENT); 1815 } 1816 1817 /* 1818 * "object" (":" delegationSpecifier{","})? classBody // Cannot make class body optional: foo(object : F, A) 1819 */ 1820 public void parseObjectLiteral() { 1821 PsiBuilder.Marker literal = mark(); 1822 PsiBuilder.Marker declaration = mark(); 1823 myJetParsing.parseObject(false, false); // Body is not optional because of foo(object : A, B) 1824 declaration.done(OBJECT_DECLARATION); 1825 literal.done(OBJECT_LITERAL); 1826 } 1827 1828 private void parseOneTokenExpression(JetNodeType type) { 1829 PsiBuilder.Marker mark = mark(); 1830 advance(); 1831 mark.done(type); 1832 } 1833 1834 @Override 1835 protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) { 1836 return myJetParsing.create(builder); 1837 } 1838 1839 private boolean interruptedWithNewLine() { 1840 return !ALLOW_NEWLINE_OPERATIONS.contains(tt()) && myBuilder.newlineBeforeCurrentToken(); 1841 } 1842 }