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