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