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