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