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