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