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