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