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