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