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