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