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 029 import java.util.Arrays; 030 import java.util.HashSet; 031 import java.util.Set; 032 033 import static org.jetbrains.kotlin.JetNodeTypes.*; 034 import static org.jetbrains.kotlin.lexer.JetTokens.*; 035 import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.REGULAR_ANNOTATIONS_ALLOW_SHORTS; 036 import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS; 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 '->'", 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 PsiBuilder.Marker rollbackMarker = mark(); 1007 boolean preferParamsToExpressions = parseFunctionLiteralParametersAndType(); 1008 1009 paramsFound = preferParamsToExpressions ? 1010 rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : 1011 rollbackOrDropAt(rollbackMarker, ARROW); 1012 } 1013 1014 if (!paramsFound) { 1015 // If not found, try a typeRef DOT and then LPAR .. RPAR ARROW 1016 // {((A) -> B).(x) -> ... } 1017 paramsFound = parseFunctionTypeDotParametersAndType(); 1018 } 1019 } 1020 else { 1021 if (at(IDENTIFIER)) { 1022 // Try to parse a simple name list followed by an ARROW 1023 // {a -> ...} 1024 // {a, b -> ...} 1025 PsiBuilder.Marker rollbackMarker = mark(); 1026 boolean preferParamsToExpressions = (lookahead(1) == COMMA); 1027 parseFunctionLiteralShorthandParameterList(); 1028 parseOptionalFunctionLiteralType(); 1029 1030 paramsFound = preferParamsToExpressions ? 1031 rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : 1032 rollbackOrDropAt(rollbackMarker, ARROW); 1033 } 1034 if (!paramsFound && atSet(JetParsing.TYPE_REF_FIRST)) { 1035 // Try to parse a type DOT valueParameterList ARROW 1036 // {A.(b) -> ...} 1037 paramsFound = parseFunctionTypeDotParametersAndType(); 1038 } 1039 } 1040 1041 if (!paramsFound) { 1042 if (preferBlock) { 1043 literal.drop(); 1044 parseStatements(); 1045 expect(RBRACE, "Expecting '}'"); 1046 literalExpression.done(BLOCK); 1047 myBuilder.restoreNewlinesState(); 1048 1049 return; 1050 } 1051 } 1052 1053 PsiBuilder.Marker body = mark(); 1054 parseStatements(); 1055 body.done(BLOCK); 1056 1057 expect(RBRACE, "Expecting '}'"); 1058 myBuilder.restoreNewlinesState(); 1059 1060 literal.done(FUNCTION_LITERAL); 1061 literalExpression.done(FUNCTION_LITERAL_EXPRESSION); 1062 } 1063 1064 private boolean rollbackOrDropAt(PsiBuilder.Marker rollbackMarker, IElementType dropAt) { 1065 if (at(dropAt)) { 1066 advance(); // dropAt 1067 rollbackMarker.drop(); 1068 return true; 1069 } 1070 rollbackMarker.rollbackTo(); 1071 return false; 1072 } 1073 1074 private boolean rollbackOrDrop(PsiBuilder.Marker rollbackMarker, 1075 JetToken expected, String expectMessage, 1076 IElementType validForDrop) { 1077 if (at(expected)) { 1078 advance(); // dropAt 1079 rollbackMarker.drop(); 1080 return true; 1081 } 1082 else if (at(validForDrop)) { 1083 rollbackMarker.drop(); 1084 expect(expected, expectMessage); 1085 return true; 1086 } 1087 1088 rollbackMarker.rollbackTo(); 1089 return false; 1090 } 1091 1092 1093 /* 1094 * SimpleName{,} 1095 */ 1096 private void parseFunctionLiteralShorthandParameterList() { 1097 PsiBuilder.Marker parameterList = mark(); 1098 1099 while (!eof()) { 1100 PsiBuilder.Marker parameter = mark(); 1101 1102 // int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos))); 1103 // createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false); 1104 1105 expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW)); 1106 1107 parameter.done(VALUE_PARAMETER); 1108 1109 if (at(COLON)) { 1110 PsiBuilder.Marker errorMarker = mark(); 1111 advance(); // COLON 1112 myJetParsing.parseTypeRef(); 1113 errorMarker.error("To specify a type of a parameter or a return type, use the full notation: {(parameter : Type) : ReturnType -> ...}"); 1114 } 1115 else if (at(ARROW)) { 1116 break; 1117 } 1118 else if (at(COMMA)) { 1119 advance(); // COMMA 1120 } 1121 else { 1122 error("Expecting '->' or ','"); 1123 break; 1124 } 1125 } 1126 1127 parameterList.done(VALUE_PARAMETER_LIST); 1128 } 1129 1130 private boolean parseFunctionTypeDotParametersAndType() { 1131 PsiBuilder.Marker rollbackMarker = mark(); 1132 1133 // True when it's confirmed that body of literal can't be simple expressions and we prefer to parse 1134 // it to function params if possible. 1135 boolean preferParamsToExpressions = false; 1136 1137 // Last dot before ARROW and RPAR, but also stop at top-level keywords and '{', '}' 1138 int lastDot = matchTokenStreamPredicate(new LastBefore( 1139 new At(DOT), 1140 new AtSet(TokenSet.orSet( 1141 TokenSet.create(ARROW, RPAR), 1142 TokenSet.orSet( 1143 TokenSet.create(LBRACE, RBRACE), 1144 TokenSet.andNot( 1145 KEYWORDS, 1146 TokenSet.create(CAPITALIZED_THIS_KEYWORD) 1147 ) 1148 ) 1149 )) 1150 )); 1151 1152 if (lastDot >= 0) { 1153 createTruncatedBuilder(lastDot).parseTypeRef(); 1154 if (at(DOT)) { 1155 advance(); // DOT 1156 preferParamsToExpressions = parseFunctionLiteralParametersAndType(); 1157 } 1158 } 1159 1160 return preferParamsToExpressions ? 1161 rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : 1162 rollbackOrDropAt(rollbackMarker, ARROW); 1163 } 1164 1165 private boolean parseFunctionLiteralParametersAndType() { 1166 boolean hasCommaInParametersList = parseFunctionLiteralParameterList(); 1167 parseOptionalFunctionLiteralType(); 1168 return hasCommaInParametersList; 1169 } 1170 1171 /* 1172 * (":" type)? 1173 */ 1174 private void parseOptionalFunctionLiteralType() { 1175 if (at(COLON)) { 1176 advance(); // COLON 1177 if (at(ARROW)) { 1178 error("Expecting a type"); 1179 } 1180 else { 1181 myJetParsing.parseTypeRef(); 1182 } 1183 } 1184 } 1185 1186 /** 1187 * "(" (modifiers SimpleName (":" type)?){","} ")" 1188 * 1189 * @return true if at least one comma was found 1190 */ 1191 private boolean parseFunctionLiteralParameterList() { 1192 PsiBuilder.Marker list = mark(); 1193 expect(LPAR, "Expecting a parameter list in parentheses (...)", TokenSet.create(ARROW, COLON)); 1194 1195 boolean hasComma = false; 1196 1197 myBuilder.disableNewlines(); 1198 1199 if (!at(RPAR)) { 1200 while (true) { 1201 if (at(COMMA)) errorAndAdvance("Expecting a parameter declaration"); 1202 1203 PsiBuilder.Marker parameter = mark(); 1204 int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, ARROW, RBRACE, LBRACE))); 1205 createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); 1206 1207 expect(IDENTIFIER, "Expecting parameter declaration"); 1208 1209 if (at(COLON)) { 1210 advance(); // COLON 1211 myJetParsing.parseTypeRef(); 1212 } 1213 parameter.done(VALUE_PARAMETER); 1214 if (!at(COMMA)) break; 1215 advance(); // COMMA 1216 1217 hasComma = true; 1218 1219 if (at(RPAR)) { 1220 error("Expecting a parameter declaration"); 1221 break; 1222 } 1223 } 1224 } 1225 1226 myBuilder.restoreNewlinesState(); 1227 1228 expect(RPAR, "Expecting ')'", TokenSet.create(ARROW, COLON)); 1229 list.done(VALUE_PARAMETER_LIST); 1230 1231 return hasComma; 1232 } 1233 1234 /* 1235 * expressions 1236 * : SEMI* statement{SEMI+} SEMI* 1237 */ 1238 public void parseStatements() { 1239 while (at(SEMICOLON)) advance(); // SEMICOLON 1240 while (!eof() && !at(RBRACE)) { 1241 if (!atSet(STATEMENT_FIRST)) { 1242 errorAndAdvance("Expecting an element"); 1243 } 1244 if (atSet(STATEMENT_FIRST)) { 1245 parseStatement(); 1246 } 1247 if (at(SEMICOLON)) { 1248 while (at(SEMICOLON)) advance(); // SEMICOLON 1249 } 1250 else if (at(RBRACE)) { 1251 break; 1252 } 1253 else if (!myBuilder.newlineBeforeCurrentToken()) { 1254 String severalStatementsError = "Unexpected tokens (use ';' to separate expressions on the same line)"; 1255 1256 if (atSet(STATEMENT_NEW_LINE_QUICK_RECOVERY_SET)) { 1257 error(severalStatementsError); 1258 } 1259 else { 1260 errorUntil(severalStatementsError, TokenSet.create(EOL_OR_SEMICOLON, LBRACE, RBRACE)); 1261 } 1262 } 1263 } 1264 } 1265 1266 /* 1267 * statement 1268 * : expression 1269 * : declaration 1270 * ; 1271 */ 1272 private void parseStatement() { 1273 if (!parseLocalDeclaration()) { 1274 if (!atSet(EXPRESSION_FIRST)) { 1275 errorAndAdvance("Expecting a statement"); 1276 } 1277 else { 1278 parseExpression(); 1279 } 1280 } 1281 } 1282 1283 /* 1284 * declaration 1285 * : function 1286 * : property 1287 * : extension 1288 * : class 1289 * : typeAlias 1290 * : object 1291 * ; 1292 */ 1293 private IElementType parseLocalDeclarationRest(boolean isEnum) { 1294 IElementType keywordToken = tt(); 1295 IElementType declType = null; 1296 if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) { 1297 declType = myJetParsing.parseClass(isEnum); 1298 } 1299 else if (keywordToken == FUN_KEYWORD) { 1300 declType = myJetParsing.parseFunction(); 1301 } 1302 else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) { 1303 declType = myJetParsing.parseProperty(true); 1304 } 1305 else if (keywordToken == TYPE_ALIAS_KEYWORD) { 1306 declType = myJetParsing.parseTypeAlias(); 1307 } 1308 else if (keywordToken == OBJECT_KEYWORD) { 1309 // Object expression may appear at the statement position: should parse it 1310 // as expression instead of object declaration 1311 // sample: 1312 // { 1313 // object : Thread() { 1314 // } 1315 // } 1316 IElementType lookahead = lookahead(1); 1317 if (lookahead == COLON || lookahead == LBRACE) { 1318 return null; 1319 } 1320 1321 myJetParsing.parseObject(true, true); 1322 declType = OBJECT_DECLARATION; 1323 } 1324 return declType; 1325 } 1326 1327 /* 1328 * doWhile 1329 * : "do" element "while" "(" element ")" 1330 * ; 1331 */ 1332 private void parseDoWhile() { 1333 assert _at(DO_KEYWORD); 1334 1335 PsiBuilder.Marker loop = mark(); 1336 1337 advance(); // DO_KEYWORD 1338 1339 if (!at(WHILE_KEYWORD)) { 1340 parseControlStructureBody(); 1341 } 1342 1343 if (expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition")) { 1344 parseCondition(); 1345 } 1346 1347 loop.done(DO_WHILE); 1348 } 1349 1350 /* 1351 * while 1352 * : "while" "(" element ")" element 1353 * ; 1354 */ 1355 private void parseWhile() { 1356 assert _at(WHILE_KEYWORD); 1357 1358 PsiBuilder.Marker loop = mark(); 1359 1360 advance(); // WHILE_KEYWORD 1361 1362 parseCondition(); 1363 1364 parseControlStructureBody(); 1365 1366 loop.done(WHILE); 1367 } 1368 1369 /* 1370 * for 1371 * : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression 1372 * ; 1373 * 1374 * TODO: empty loop body (at the end of the block)? 1375 */ 1376 private void parseFor() { 1377 assert _at(FOR_KEYWORD); 1378 1379 PsiBuilder.Marker loop = mark(); 1380 1381 advance(); // FOR_KEYWORD 1382 1383 if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) { 1384 myBuilder.disableNewlines(); 1385 1386 if (!at(RPAR)) { 1387 PsiBuilder.Marker parameter = mark(); 1388 if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD 1389 if (at(LPAR)) { 1390 myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE)); 1391 parameter.done(MULTI_VARIABLE_DECLARATION); 1392 } 1393 else { 1394 expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD)); 1395 1396 if (at(COLON)) { 1397 advance(); // COLON 1398 myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD)); 1399 } 1400 parameter.done(VALUE_PARAMETER); 1401 } 1402 1403 if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) { 1404 PsiBuilder.Marker range = mark(); 1405 parseExpression(); 1406 range.done(LOOP_RANGE); 1407 } 1408 } 1409 else { 1410 error("Expecting a variable name"); 1411 } 1412 1413 expectNoAdvance(RPAR, "Expecting ')'"); 1414 myBuilder.restoreNewlinesState(); 1415 } 1416 1417 parseControlStructureBody(); 1418 1419 loop.done(FOR); 1420 } 1421 1422 /** 1423 * If it has no ->, it's a block, otherwise a function literal 1424 */ 1425 private void parseExpressionPreferringBlocks() { 1426 if (at(LBRACE)) { 1427 parseFunctionLiteral(true); 1428 } 1429 else if (at(LABEL_IDENTIFIER) && lookahead(1) == LBRACE ) { 1430 PsiBuilder.Marker mark = mark(); 1431 1432 parseLabel(); 1433 1434 parseFunctionLiteral(true); 1435 1436 mark.done(LABELED_EXPRESSION); 1437 } 1438 else { 1439 parseExpression(); 1440 } 1441 } 1442 1443 /* 1444 * element 1445 */ 1446 private void parseControlStructureBody() { 1447 PsiBuilder.Marker body = mark(); 1448 if (!at(SEMICOLON)) { 1449 parseExpressionPreferringBlocks(); 1450 } 1451 body.done(BODY); 1452 } 1453 1454 /* 1455 * try 1456 * : "try" block catchBlock* finallyBlock? 1457 * ; 1458 * catchBlock 1459 * : "catch" "(" annotations SimpleName ":" userType ")" block 1460 * ; 1461 * 1462 * finallyBlock 1463 * : "finally" block 1464 * ; 1465 */ 1466 private void parseTry() { 1467 assert _at(TRY_KEYWORD); 1468 1469 PsiBuilder.Marker tryExpression = mark(); 1470 1471 advance(); // TRY_KEYWORD 1472 1473 myJetParsing.parseBlock(); 1474 1475 boolean catchOrFinally = false; 1476 while (at(CATCH_KEYWORD)) { 1477 catchOrFinally = true; 1478 PsiBuilder.Marker catchBlock = mark(); 1479 advance(); // CATCH_KEYWORD 1480 1481 TokenSet recoverySet = TokenSet.create(LBRACE, FINALLY_KEYWORD, CATCH_KEYWORD); 1482 if (atSet(recoverySet)) { 1483 error("Expecting exception variable declaration"); 1484 } 1485 else { 1486 PsiBuilder.Marker parameters = mark(); 1487 expect(LPAR, "Expecting '('", recoverySet); 1488 if (!atSet(recoverySet)) { 1489 myJetParsing.parseValueParameter(); 1490 expect(RPAR, "Expecting ')'", recoverySet); 1491 } 1492 else { 1493 error("Expecting exception variable declaration"); 1494 } 1495 parameters.done(VALUE_PARAMETER_LIST); 1496 } 1497 1498 if (at(LBRACE)) { 1499 myJetParsing.parseBlock(); 1500 } 1501 else { 1502 error("Expecting a block: { ... }"); 1503 } 1504 catchBlock.done(CATCH); 1505 } 1506 1507 if (at(FINALLY_KEYWORD)) { 1508 catchOrFinally = true; 1509 PsiBuilder.Marker finallyBlock = mark(); 1510 1511 advance(); // FINALLY_KEYWORD 1512 1513 myJetParsing.parseBlock(); 1514 1515 finallyBlock.done(FINALLY); 1516 } 1517 1518 if (!catchOrFinally) { 1519 error("Expecting 'catch' or 'finally'"); 1520 } 1521 1522 tryExpression.done(TRY); 1523 } 1524 1525 /* 1526 * if 1527 * : "if" "(" element ")" element SEMI? ("else" element)? 1528 * ; 1529 */ 1530 private void parseIf() { 1531 assert _at(IF_KEYWORD); 1532 1533 PsiBuilder.Marker marker = mark(); 1534 1535 advance(); //IF_KEYWORD 1536 1537 parseCondition(); 1538 1539 PsiBuilder.Marker thenBranch = mark(); 1540 if (!at(ELSE_KEYWORD) && !at(SEMICOLON)) { 1541 parseExpressionPreferringBlocks(); 1542 } 1543 if (at(SEMICOLON) && lookahead(1) == ELSE_KEYWORD) { 1544 advance(); // SEMICOLON 1545 } 1546 thenBranch.done(THEN); 1547 1548 if (at(ELSE_KEYWORD)) { 1549 advance(); // ELSE_KEYWORD 1550 1551 PsiBuilder.Marker elseBranch = mark(); 1552 if (!at(SEMICOLON)) { 1553 parseExpressionPreferringBlocks(); 1554 } 1555 elseBranch.done(ELSE); 1556 } 1557 1558 marker.done(IF); 1559 } 1560 1561 /* 1562 * "(" element ")" 1563 */ 1564 private void parseCondition() { 1565 myBuilder.disableNewlines(); 1566 1567 if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) { 1568 PsiBuilder.Marker condition = mark(); 1569 parseExpression(); 1570 condition.done(CONDITION); 1571 expect(RPAR, "Expecting ')"); 1572 } 1573 1574 myBuilder.restoreNewlinesState(); 1575 } 1576 1577 /* 1578 * : "continue" getEntryPoint? 1579 * : "break" getEntryPoint? 1580 */ 1581 private void parseJump(JetNodeType type) { 1582 assert _at(BREAK_KEYWORD) || _at(CONTINUE_KEYWORD); 1583 1584 PsiBuilder.Marker marker = mark(); 1585 1586 advance(); // BREAK_KEYWORD or CONTINUE_KEYWORD 1587 1588 parseLabelOnTheSameLine(); 1589 1590 marker.done(type); 1591 } 1592 1593 /* 1594 * "return" getEntryPoint? element? 1595 */ 1596 private void parseReturn() { 1597 assert _at(RETURN_KEYWORD); 1598 1599 PsiBuilder.Marker returnExpression = mark(); 1600 1601 advance(); // RETURN_KEYWORD 1602 1603 parseLabelOnTheSameLine(); 1604 1605 if (atSet(EXPRESSION_FIRST) && !at(EOL_OR_SEMICOLON)) parseExpression(); 1606 1607 returnExpression.done(RETURN); 1608 } 1609 1610 /* 1611 * label? 1612 */ 1613 private void parseLabelOnTheSameLine() { 1614 if (!eol() && at(LABEL_IDENTIFIER)) { 1615 parseLabel(); 1616 } 1617 } 1618 1619 /* 1620 * label 1621 */ 1622 private void parseLabel() { 1623 assert _at(LABEL_IDENTIFIER); 1624 1625 String labelText = myBuilder.getTokenText(); 1626 if ("@".equals(labelText)) { 1627 errorAndAdvance("Label must be named"); 1628 return; 1629 } 1630 1631 PsiBuilder.Marker labelWrap = mark(); 1632 1633 PsiBuilder.Marker mark = mark(); 1634 advance(); // LABEL_IDENTIFIER 1635 mark.done(LABEL); 1636 1637 labelWrap.done(LABEL_QUALIFIER); 1638 } 1639 1640 /* 1641 * : "throw" element 1642 */ 1643 private void parseThrow() { 1644 assert _at(THROW_KEYWORD); 1645 1646 PsiBuilder.Marker marker = mark(); 1647 1648 advance(); // THROW_KEYWORD 1649 1650 parseExpression(); 1651 1652 marker.done(THROW); 1653 } 1654 1655 /* 1656 * "(" expression ")" 1657 */ 1658 private void parseParenthesizedExpression() { 1659 assert _at(LPAR); 1660 1661 PsiBuilder.Marker mark = mark(); 1662 1663 myBuilder.disableNewlines(); 1664 advance(); // LPAR 1665 if (at(RPAR)) { 1666 error("Expecting an expression"); 1667 } 1668 else { 1669 parseExpression(); 1670 } 1671 1672 expect(RPAR, "Expecting ')'"); 1673 myBuilder.restoreNewlinesState(); 1674 1675 mark.done(PARENTHESIZED); 1676 } 1677 1678 /* 1679 * tupleLiteral 1680 * : "#" "(" (((SimpleName "=")? expression){","})? ")" 1681 * ; 1682 */ 1683 @Deprecated // Tuples are dropped, but parsing is left to minimize surprising. This code should be removed some time (in Kotlin 1.0?) 1684 private void parseTupleExpression() { 1685 assert _at(HASH); 1686 PsiBuilder.Marker mark = mark(); 1687 1688 advance(); // HASH 1689 advance(); // LPAR 1690 myBuilder.disableNewlines(); 1691 if (!at(RPAR)) { 1692 while (true) { 1693 while (at(COMMA)) { 1694 advance(); 1695 } 1696 1697 if (at(IDENTIFIER) && lookahead(1) == EQ) { 1698 advance(); // IDENTIFIER 1699 advance(); // EQ 1700 parseExpression(); 1701 } 1702 else { 1703 parseExpression(); 1704 } 1705 1706 if (!at(COMMA)) break; 1707 advance(); // COMMA 1708 1709 if (at(RPAR)) { 1710 break; 1711 } 1712 } 1713 1714 } 1715 consumeIf(RPAR); 1716 myBuilder.restoreNewlinesState(); 1717 1718 mark.error("Tuples are not supported. Use data classes instead."); 1719 } 1720 1721 /* 1722 * "this" label? 1723 */ 1724 private void parseThisExpression() { 1725 assert _at(THIS_KEYWORD); 1726 PsiBuilder.Marker mark = mark(); 1727 1728 PsiBuilder.Marker thisReference = mark(); 1729 advance(); // THIS_KEYWORD 1730 thisReference.done(REFERENCE_EXPRESSION); 1731 1732 parseLabelOnTheSameLine(); 1733 1734 mark.done(THIS_EXPRESSION); 1735 } 1736 1737 /* 1738 * "this" ("<" type ">")? label? 1739 */ 1740 private void parseSuperExpression() { 1741 assert _at(SUPER_KEYWORD); 1742 PsiBuilder.Marker mark = mark(); 1743 1744 PsiBuilder.Marker superReference = mark(); 1745 advance(); // SUPER_KEYWORD 1746 superReference.done(REFERENCE_EXPRESSION); 1747 1748 if (at(LT)) { 1749 // This may be "super < foo" or "super<foo>", thus the backtracking 1750 PsiBuilder.Marker supertype = mark(); 1751 1752 myBuilder.disableNewlines(); 1753 advance(); // LT 1754 1755 myJetParsing.parseTypeRef(); 1756 1757 if (at(GT)) { 1758 advance(); // GT 1759 supertype.drop(); 1760 } 1761 else { 1762 supertype.rollbackTo(); 1763 } 1764 myBuilder.restoreNewlinesState(); 1765 } 1766 parseLabelOnTheSameLine(); 1767 1768 mark.done(SUPER_EXPRESSION); 1769 } 1770 1771 /* 1772 * valueArguments 1773 * : "(" (SimpleName "=")? "*"? element{","} ")" 1774 * ; 1775 */ 1776 public void parseValueArgumentList() { 1777 PsiBuilder.Marker list = mark(); 1778 1779 myBuilder.disableNewlines(); 1780 1781 if (expect(LPAR, "Expecting an argument list", EXPRESSION_FOLLOW)) { 1782 if (!at(RPAR)) { 1783 while (true) { 1784 while (at(COMMA)) errorAndAdvance("Expecting an argument"); 1785 parseValueArgument(); 1786 if (!at(COMMA)) break; 1787 advance(); // COMMA 1788 if (at(RPAR)) { 1789 error("Expecting an argument"); 1790 break; 1791 } 1792 } 1793 } 1794 1795 expect(RPAR, "Expecting ')'", EXPRESSION_FOLLOW); 1796 } 1797 1798 myBuilder.restoreNewlinesState(); 1799 1800 list.done(VALUE_ARGUMENT_LIST); 1801 } 1802 1803 /* 1804 * (SimpleName "=")? "*"? element 1805 */ 1806 private void parseValueArgument() { 1807 PsiBuilder.Marker argument = mark(); 1808 if (at(IDENTIFIER) && lookahead(1) == EQ) { 1809 PsiBuilder.Marker argName = mark(); 1810 PsiBuilder.Marker reference = mark(); 1811 advance(); // IDENTIFIER 1812 reference.done(REFERENCE_EXPRESSION); 1813 argName.done(VALUE_ARGUMENT_NAME); 1814 advance(); // EQ 1815 } 1816 if (at(MUL)) { 1817 advance(); // MUL 1818 } 1819 parseExpression(); 1820 argument.done(VALUE_ARGUMENT); 1821 } 1822 1823 /* 1824 * "object" (":" delegationSpecifier{","})? classBody // Cannot make class body optional: foo(object : F, A) 1825 */ 1826 public void parseObjectLiteral() { 1827 PsiBuilder.Marker literal = mark(); 1828 PsiBuilder.Marker declaration = mark(); 1829 myJetParsing.parseObject(false, false); // Body is not optional because of foo(object : A, B) 1830 declaration.done(OBJECT_DECLARATION); 1831 literal.done(OBJECT_LITERAL); 1832 } 1833 1834 private void parseOneTokenExpression(JetNodeType type) { 1835 PsiBuilder.Marker mark = mark(); 1836 advance(); 1837 mark.done(type); 1838 } 1839 1840 @Override 1841 protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) { 1842 return myJetParsing.create(builder); 1843 } 1844 1845 private boolean interruptedWithNewLine() { 1846 return !ALLOW_NEWLINE_OPERATIONS.contains(tt()) && myBuilder.newlineBeforeCurrentToken(); 1847 } 1848 }