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