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