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