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