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