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