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