OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.parser; | 5 library dart2js.parser; |
6 | 6 |
7 import '../options.dart' show | 7 import '../options.dart' show ParserOptions; |
8 ParserOptions; | |
9 import '../common.dart'; | 8 import '../common.dart'; |
10 import '../tokens/keyword.dart' show | 9 import '../tokens/keyword.dart' show Keyword; |
11 Keyword; | 10 import '../tokens/precedence.dart' show PrecedenceInfo; |
12 import '../tokens/precedence.dart' show | 11 import '../tokens/precedence_constants.dart' |
13 PrecedenceInfo; | 12 show |
14 import '../tokens/precedence_constants.dart' show | 13 AS_INFO, |
15 AS_INFO, | 14 ASSIGNMENT_PRECEDENCE, |
16 ASSIGNMENT_PRECEDENCE, | 15 CASCADE_PRECEDENCE, |
17 CASCADE_PRECEDENCE, | 16 EQUALITY_PRECEDENCE, |
18 EQUALITY_PRECEDENCE, | 17 GT_INFO, |
19 GT_INFO, | 18 GT_GT_INFO, |
20 GT_GT_INFO, | 19 IS_INFO, |
21 IS_INFO, | 20 MINUS_MINUS_INFO, |
22 MINUS_MINUS_INFO, | 21 OPEN_PAREN_INFO, |
23 OPEN_PAREN_INFO, | 22 OPEN_SQUARE_BRACKET_INFO, |
24 OPEN_SQUARE_BRACKET_INFO, | 23 PERIOD_INFO, |
25 PERIOD_INFO, | 24 PLUS_PLUS_INFO, |
26 PLUS_PLUS_INFO, | 25 POSTFIX_PRECEDENCE, |
27 POSTFIX_PRECEDENCE, | 26 QUESTION_INFO, |
28 QUESTION_INFO, | 27 QUESTION_PERIOD_INFO, |
29 QUESTION_PERIOD_INFO, | 28 RELATIONAL_PRECEDENCE; |
30 RELATIONAL_PRECEDENCE; | 29 import '../tokens/token.dart' |
31 import '../tokens/token.dart' show | 30 show |
32 BeginGroupToken, | 31 BeginGroupToken, |
33 isUserDefinableOperator, | 32 isUserDefinableOperator, |
34 KeywordToken, | 33 KeywordToken, |
35 SymbolToken, | 34 SymbolToken, |
36 Token; | 35 Token; |
37 import '../tokens/token_constants.dart' show | 36 import '../tokens/token_constants.dart' |
38 BAD_INPUT_TOKEN, | 37 show |
39 COMMA_TOKEN, | 38 BAD_INPUT_TOKEN, |
40 DOUBLE_TOKEN, | 39 COMMA_TOKEN, |
41 EOF_TOKEN, | 40 DOUBLE_TOKEN, |
42 EQ_TOKEN, | 41 EOF_TOKEN, |
43 FUNCTION_TOKEN, | 42 EQ_TOKEN, |
44 HASH_TOKEN, | 43 FUNCTION_TOKEN, |
45 HEXADECIMAL_TOKEN, | 44 HASH_TOKEN, |
46 IDENTIFIER_TOKEN, | 45 HEXADECIMAL_TOKEN, |
47 INT_TOKEN, | 46 IDENTIFIER_TOKEN, |
48 KEYWORD_TOKEN, | 47 INT_TOKEN, |
49 LT_TOKEN, | 48 KEYWORD_TOKEN, |
50 OPEN_CURLY_BRACKET_TOKEN, | 49 LT_TOKEN, |
51 OPEN_PAREN_TOKEN, | 50 OPEN_CURLY_BRACKET_TOKEN, |
52 OPEN_SQUARE_BRACKET_TOKEN, | 51 OPEN_PAREN_TOKEN, |
53 PERIOD_TOKEN, | 52 OPEN_SQUARE_BRACKET_TOKEN, |
54 SEMICOLON_TOKEN, | 53 PERIOD_TOKEN, |
55 STRING_INTERPOLATION_IDENTIFIER_TOKEN, | 54 SEMICOLON_TOKEN, |
56 STRING_INTERPOLATION_TOKEN, | 55 STRING_INTERPOLATION_IDENTIFIER_TOKEN, |
57 STRING_TOKEN; | 56 STRING_INTERPOLATION_TOKEN, |
58 import '../util/characters.dart' as Characters show | 57 STRING_TOKEN; |
59 $CLOSE_CURLY_BRACKET; | 58 import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET; |
60 import '../util/util.dart' show | 59 import '../util/util.dart' show Link; |
61 Link; | |
62 | 60 |
63 import 'listener.dart' show | 61 import 'listener.dart' show Listener; |
64 Listener; | |
65 | 62 |
66 class FormalParameterType { | 63 class FormalParameterType { |
67 final String type; | 64 final String type; |
68 const FormalParameterType(this.type); | 65 const FormalParameterType(this.type); |
69 bool get isRequired => this == REQUIRED; | 66 bool get isRequired => this == REQUIRED; |
70 bool get isPositional => this == POSITIONAL; | 67 bool get isPositional => this == POSITIONAL; |
71 bool get isNamed => this == NAMED; | 68 bool get isNamed => this == NAMED; |
72 static final REQUIRED = const FormalParameterType('required'); | 69 static final REQUIRED = const FormalParameterType('required'); |
73 static final POSITIONAL = const FormalParameterType('positional'); | 70 static final POSITIONAL = const FormalParameterType('positional'); |
74 static final NAMED = const FormalParameterType('named'); | 71 static final NAMED = const FormalParameterType('named'); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 listener.endTopLevelDeclaration(token); | 111 listener.endTopLevelDeclaration(token); |
115 count++; | 112 count++; |
116 } | 113 } |
117 listener.endCompilationUnit(count, token); | 114 listener.endCompilationUnit(count, token); |
118 return token; | 115 return token; |
119 } | 116 } |
120 | 117 |
121 Token parseTopLevelDeclaration(Token token) { | 118 Token parseTopLevelDeclaration(Token token) { |
122 token = parseMetadataStar(token); | 119 token = parseMetadataStar(token); |
123 final String value = token.stringValue; | 120 final String value = token.stringValue; |
124 if ((identical(value, 'abstract') && optional('class', token.next)) | 121 if ((identical(value, 'abstract') && optional('class', token.next)) || |
125 || identical(value, 'class')) { | 122 identical(value, 'class')) { |
126 return parseClassOrNamedMixinApplication(token); | 123 return parseClassOrNamedMixinApplication(token); |
127 } else if (identical(value, 'enum')) { | 124 } else if (identical(value, 'enum')) { |
128 return parseEnum(token); | 125 return parseEnum(token); |
129 } else if (identical(value, 'typedef')) { | 126 } else if (identical(value, 'typedef')) { |
130 return parseTypedef(token); | 127 return parseTypedef(token); |
131 } else if (identical(value, 'library')) { | 128 } else if (identical(value, 'library')) { |
132 return parseLibraryName(token); | 129 return parseLibraryName(token); |
133 } else if (identical(value, 'import')) { | 130 } else if (identical(value, 'import')) { |
134 return parseImport(token); | 131 return parseImport(token); |
135 } else if (identical(value, 'export')) { | 132 } else if (identical(value, 'export')) { |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 token = parseFormalParameters(token); | 460 token = parseFormalParameters(token); |
464 listener.handleFunctionTypedFormalParameter(token); | 461 listener.handleFunctionTypedFormalParameter(token); |
465 } | 462 } |
466 String value = token.stringValue; | 463 String value = token.stringValue; |
467 if ((identical('=', value)) || (identical(':', value))) { | 464 if ((identical('=', value)) || (identical(':', value))) { |
468 // TODO(ahe): Validate that these are only used for optional parameters. | 465 // TODO(ahe): Validate that these are only used for optional parameters. |
469 Token equal = token; | 466 Token equal = token; |
470 token = parseExpression(token.next); | 467 token = parseExpression(token.next); |
471 listener.handleValuedFormalParameter(equal, token); | 468 listener.handleValuedFormalParameter(equal, token); |
472 if (type.isRequired) { | 469 if (type.isRequired) { |
473 listener.reportError(equal, | 470 listener.reportError( |
474 MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); | 471 equal, MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); |
475 } else if (type.isNamed && identical('=', value)) { | 472 } else if (type.isNamed && identical('=', value)) { |
476 listener.reportError(equal, MessageKind.NAMED_PARAMETER_WITH_EQUALS); | 473 listener.reportError(equal, MessageKind.NAMED_PARAMETER_WITH_EQUALS); |
477 } else if (type.isPositional && identical(':', value)) { | 474 } else if (type.isPositional && identical(':', value)) { |
478 listener.reportError(equal, | 475 listener.reportError( |
479 MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); | 476 equal, MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); |
480 } | 477 } |
481 } | 478 } |
482 listener.endFormalParameter(thisKeyword); | 479 listener.endFormalParameter(thisKeyword); |
483 return token; | 480 return token; |
484 } | 481 } |
485 | 482 |
486 Token parseOptionalFormalParameters(Token token, bool isNamed) { | 483 Token parseOptionalFormalParameters(Token token, bool isNamed) { |
487 Token begin = token; | 484 Token begin = token; |
488 listener.beginOptionalFormalParameters(begin); | 485 listener.beginOptionalFormalParameters(begin); |
489 assert((isNamed && optional('{', token)) || optional('[', token)); | 486 assert((isNamed && optional('{', token)) || optional('[', token)); |
490 int parameterCount = 0; | 487 int parameterCount = 0; |
491 do { | 488 do { |
492 token = token.next; | 489 token = token.next; |
493 var type = isNamed ? FormalParameterType.NAMED | 490 var type = |
494 : FormalParameterType.POSITIONAL; | 491 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
495 token = parseFormalParameter(token, type); | 492 token = parseFormalParameter(token, type); |
496 ++parameterCount; | 493 ++parameterCount; |
497 } while (optional(',', token)); | 494 } while (optional(',', token)); |
498 listener.endOptionalFormalParameters(parameterCount, begin, token); | 495 listener.endOptionalFormalParameters(parameterCount, begin, token); |
499 if (isNamed) { | 496 if (isNamed) { |
500 return expect('}', token); | 497 return expect('}', token); |
501 } else { | 498 } else { |
502 return expect(']', token); | 499 return expect(']', token); |
503 } | 500 } |
504 } | 501 } |
505 | 502 |
506 Token parseTypeOpt(Token token) { | 503 Token parseTypeOpt(Token token) { |
507 Token peek = peekAfterIfType(token); | 504 Token peek = peekAfterIfType(token); |
508 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { | 505 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { |
509 return parseType(token); | 506 return parseType(token); |
510 } | 507 } |
511 listener.handleNoType(token); | 508 listener.handleNoType(token); |
512 return token; | 509 return token; |
513 } | 510 } |
514 | 511 |
515 bool isValidTypeReference(Token token) { | 512 bool isValidTypeReference(Token token) { |
516 final kind = token.kind; | 513 final kind = token.kind; |
517 if (identical(kind, IDENTIFIER_TOKEN)) return true; | 514 if (identical(kind, IDENTIFIER_TOKEN)) return true; |
518 if (identical(kind, KEYWORD_TOKEN)) { | 515 if (identical(kind, KEYWORD_TOKEN)) { |
519 Keyword keyword = (token as KeywordToken).keyword; | 516 Keyword keyword = (token as KeywordToken).keyword; |
520 String value = keyword.syntax; | 517 String value = keyword.syntax; |
521 return keyword.isPseudo | 518 return keyword.isPseudo || |
522 || (identical(value, 'dynamic')) | 519 (identical(value, 'dynamic')) || |
523 || (identical(value, 'void')); | 520 (identical(value, 'void')); |
524 } | 521 } |
525 return false; | 522 return false; |
526 } | 523 } |
527 | 524 |
528 Token parseQualified(Token token) { | 525 Token parseQualified(Token token) { |
529 token = parseIdentifier(token); | 526 token = parseIdentifier(token); |
530 while (optional('.', token)) { | 527 while (optional('.', token)) { |
531 token = parseQualifiedRest(token); | 528 token = parseQualifiedRest(token); |
532 } | 529 } |
533 return token; | 530 return token; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 } | 618 } |
622 } | 619 } |
623 | 620 |
624 Token parseNamedMixinApplication(Token token, Token classKeyword) { | 621 Token parseNamedMixinApplication(Token token, Token classKeyword) { |
625 token = parseMixinApplication(token); | 622 token = parseMixinApplication(token); |
626 Token implementsKeyword = null; | 623 Token implementsKeyword = null; |
627 if (optional('implements', token)) { | 624 if (optional('implements', token)) { |
628 implementsKeyword = token; | 625 implementsKeyword = token; |
629 token = parseTypeList(token.next); | 626 token = parseTypeList(token.next); |
630 } | 627 } |
631 listener.endNamedMixinApplication( | 628 listener.endNamedMixinApplication(classKeyword, implementsKeyword, token); |
632 classKeyword, implementsKeyword, token); | |
633 return expect(';', token); | 629 return expect(';', token); |
634 } | 630 } |
635 | 631 |
636 Token parseClass(Token begin, Token classKeyword) { | 632 Token parseClass(Token begin, Token classKeyword) { |
637 Token token = parseIdentifier(classKeyword.next); | 633 Token token = parseIdentifier(classKeyword.next); |
638 token = parseTypeVariablesOpt(token); | 634 token = parseTypeVariablesOpt(token); |
639 Token extendsKeyword; | 635 Token extendsKeyword; |
640 if (optional('extends', token)) { | 636 if (optional('extends', token)) { |
641 extendsKeyword = token; | 637 extendsKeyword = token; |
642 if (optional('with', peekAfterType(token.next))) { | 638 if (optional('with', peekAfterType(token.next))) { |
643 token = parseMixinApplication(token.next); | 639 token = parseMixinApplication(token.next); |
644 } else { | 640 } else { |
645 token = parseType(token.next); | 641 token = parseType(token.next); |
646 } | 642 } |
647 } else { | 643 } else { |
648 extendsKeyword = null; | 644 extendsKeyword = null; |
649 listener.handleNoType(token); | 645 listener.handleNoType(token); |
650 } | 646 } |
651 Token implementsKeyword; | 647 Token implementsKeyword; |
652 int interfacesCount = 0; | 648 int interfacesCount = 0; |
653 if (optional('implements', token)) { | 649 if (optional('implements', token)) { |
654 implementsKeyword = token; | 650 implementsKeyword = token; |
655 do { | 651 do { |
656 token = parseType(token.next); | 652 token = parseType(token.next); |
657 ++interfacesCount; | 653 ++interfacesCount; |
658 } while (optional(',', token)); | 654 } while (optional(',', token)); |
659 } | 655 } |
660 token = parseClassBody(token); | 656 token = parseClassBody(token); |
661 listener.endClassDeclaration(interfacesCount, begin, extendsKeyword, | 657 listener.endClassDeclaration( |
662 implementsKeyword, token); | 658 interfacesCount, begin, extendsKeyword, implementsKeyword, token); |
663 return token.next; | 659 return token.next; |
664 } | 660 } |
665 | 661 |
666 Token parseStringPart(Token token) { | 662 Token parseStringPart(Token token) { |
667 if (identical(token.kind, STRING_TOKEN)) { | 663 if (identical(token.kind, STRING_TOKEN)) { |
668 listener.handleStringPart(token); | 664 listener.handleStringPart(token); |
669 return token.next; | 665 return token.next; |
670 } else { | 666 } else { |
671 return listener.expected('string', token); | 667 return listener.expected('string', token); |
672 } | 668 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 bool optional(String value, Token token) { | 701 bool optional(String value, Token token) { |
706 return identical(value, token.stringValue); | 702 return identical(value, token.stringValue); |
707 } | 703 } |
708 | 704 |
709 /** | 705 /** |
710 * Returns true if the stringValue of the [token] is either [value1], | 706 * Returns true if the stringValue of the [token] is either [value1], |
711 * [value2], or [value3]. | 707 * [value2], or [value3]. |
712 */ | 708 */ |
713 bool isOneOf3(Token token, String value1, String value2, String value3) { | 709 bool isOneOf3(Token token, String value1, String value2, String value3) { |
714 String stringValue = token.stringValue; | 710 String stringValue = token.stringValue; |
715 return | 711 return value1 == stringValue || |
716 value1 == stringValue || | |
717 value2 == stringValue || | 712 value2 == stringValue || |
718 value3 == stringValue; | 713 value3 == stringValue; |
719 } | 714 } |
720 | 715 |
721 /** | 716 /** |
722 * Returns true if the stringValue of the [token] is either [value1], | 717 * Returns true if the stringValue of the [token] is either [value1], |
723 * [value2], [value3], or [value4]. | 718 * [value2], [value3], or [value4]. |
724 */ | 719 */ |
725 bool isOneOf4(Token token, | 720 bool isOneOf4( |
726 String value1, String value2, String value3, String value4) { | 721 Token token, String value1, String value2, String value3, String value4) { |
727 String stringValue = token.stringValue; | 722 String stringValue = token.stringValue; |
728 return value1 == stringValue || | 723 return value1 == stringValue || |
729 value2 == stringValue || | 724 value2 == stringValue || |
730 value3 == stringValue || | 725 value3 == stringValue || |
731 value4 == stringValue; | 726 value4 == stringValue; |
732 } | 727 } |
733 | 728 |
734 bool notEofOrValue(String value, Token token) { | 729 bool notEofOrValue(String value, Token token) { |
735 return !identical(token.kind, EOF_TOKEN) && | 730 return !identical(token.kind, EOF_TOKEN) && |
736 !identical(value, token.stringValue); | 731 !identical(value, token.stringValue); |
737 } | 732 } |
738 | 733 |
739 Token parseType(Token token) { | 734 Token parseType(Token token) { |
740 Token begin = token; | 735 Token begin = token; |
741 if (isValidTypeReference(token)) { | 736 if (isValidTypeReference(token)) { |
742 token = parseIdentifier(token); | 737 token = parseIdentifier(token); |
743 token = parseQualifiedRestOpt(token); | 738 token = parseQualifiedRestOpt(token); |
744 } else { | 739 } else { |
745 token = listener.expectedType(token); | 740 token = listener.expectedType(token); |
746 } | 741 } |
747 token = parseTypeArgumentsOpt(token); | 742 token = parseTypeArgumentsOpt(token); |
748 listener.endType(begin, token); | 743 listener.endType(begin, token); |
749 return token; | 744 return token; |
750 } | 745 } |
751 | 746 |
752 Token parseTypeArgumentsOpt(Token token) { | 747 Token parseTypeArgumentsOpt(Token token) { |
753 return parseStuff(token, | 748 return parseStuff( |
754 (t) => listener.beginTypeArguments(t), | 749 token, |
755 (t) => parseType(t), | 750 (t) => listener.beginTypeArguments(t), |
756 (c, bt, et) => listener.endTypeArguments(c, bt, et), | 751 (t) => parseType(t), |
757 (t) => listener.handleNoTypeArguments(t)); | 752 (c, bt, et) => listener.endTypeArguments(c, bt, et), |
| 753 (t) => listener.handleNoTypeArguments(t)); |
758 } | 754 } |
759 | 755 |
760 Token parseTypeVariablesOpt(Token token) { | 756 Token parseTypeVariablesOpt(Token token) { |
761 return parseStuff(token, | 757 return parseStuff( |
762 (t) => listener.beginTypeVariables(t), | 758 token, |
763 (t) => parseTypeVariable(t), | 759 (t) => listener.beginTypeVariables(t), |
764 (c, bt, et) => listener.endTypeVariables(c, bt, et), | 760 (t) => parseTypeVariable(t), |
765 (t) => listener.handleNoTypeVariables(t)); | 761 (c, bt, et) => listener.endTypeVariables(c, bt, et), |
| 762 (t) => listener.handleNoTypeVariables(t)); |
766 } | 763 } |
767 | 764 |
768 // TODO(ahe): Clean this up. | 765 // TODO(ahe): Clean this up. |
769 Token parseStuff(Token token, Function beginStuff, Function stuffParser, | 766 Token parseStuff(Token token, Function beginStuff, Function stuffParser, |
770 Function endStuff, Function handleNoStuff) { | 767 Function endStuff, Function handleNoStuff) { |
771 if (optional('<', token)) { | 768 if (optional('<', token)) { |
772 Token begin = token; | 769 Token begin = token; |
773 beginStuff(begin); | 770 beginStuff(begin); |
774 int count = 0; | 771 int count = 0; |
775 do { | 772 do { |
776 token = stuffParser(token.next); | 773 token = stuffParser(token.next); |
777 ++count; | 774 ++count; |
778 } while (optional(',', token)); | 775 } while (optional(',', token)); |
779 Token next = token.next; | 776 Token next = token.next; |
780 if (identical(token.stringValue, '>>')) { | 777 if (identical(token.stringValue, '>>')) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 identifiers = identifiers.tail; | 817 identifiers = identifiers.tail; |
821 } | 818 } |
822 } | 819 } |
823 | 820 |
824 token = afterName; | 821 token = afterName; |
825 bool isField; | 822 bool isField; |
826 while (true) { | 823 while (true) { |
827 // Loop to allow the listener to rewrite the token stream for | 824 // Loop to allow the listener to rewrite the token stream for |
828 // error handling. | 825 // error handling. |
829 final String value = token.stringValue; | 826 final String value = token.stringValue; |
830 if ((identical(value, '(')) || (identical(value, '{')) | 827 if ((identical(value, '(')) || |
831 || (identical(value, '=>'))) { | 828 (identical(value, '{')) || |
| 829 (identical(value, '=>'))) { |
832 isField = false; | 830 isField = false; |
833 break; | 831 break; |
834 } else if ((identical(value, '=')) || (identical(value, ','))) { | 832 } else if ((identical(value, '=')) || (identical(value, ','))) { |
835 isField = true; | 833 isField = true; |
836 break; | 834 break; |
837 } else if (identical(value, ';')) { | 835 } else if (identical(value, ';')) { |
838 if (getOrSet != null) { | 836 if (getOrSet != null) { |
839 // If we found a "get" keyword, this must be an abstract | 837 // If we found a "get" keyword, this must be an abstract |
840 // getter. | 838 // getter. |
841 isField = (!identical(getOrSet.stringValue, 'get')); | 839 isField = (!identical(getOrSet.stringValue, 'get')); |
842 // TODO(ahe): This feels like a hack. | 840 // TODO(ahe): This feels like a hack. |
843 } else { | 841 } else { |
844 isField = true; | 842 isField = true; |
845 } | 843 } |
846 break; | 844 break; |
847 } else { | 845 } else { |
848 token = listener.unexpected(token); | 846 token = listener.unexpected(token); |
849 if (identical(token.kind, EOF_TOKEN)) return token; | 847 if (identical(token.kind, EOF_TOKEN)) return token; |
850 } | 848 } |
851 } | 849 } |
852 var modifiers = identifiers.reverse(); | 850 var modifiers = identifiers.reverse(); |
853 return isField | 851 return isField |
854 ? parseFields(start, modifiers, type, getOrSet, name, true) | 852 ? parseFields(start, modifiers, type, getOrSet, name, true) |
855 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); | 853 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); |
856 } | 854 } |
857 | 855 |
858 bool isVarFinalOrConst(Token token) { | 856 bool isVarFinalOrConst(Token token) { |
859 String value = token.stringValue; | 857 String value = token.stringValue; |
860 return identical('var', value) | 858 return identical('var', value) || |
861 || identical('final', value) | 859 identical('final', value) || |
862 || identical('const', value); | 860 identical('const', value); |
863 } | 861 } |
864 | 862 |
865 Token expectVarFinalOrConst(Link<Token> modifiers, | 863 Token expectVarFinalOrConst( |
866 bool hasType, | 864 Link<Token> modifiers, bool hasType, bool allowStatic) { |
867 bool allowStatic) { | |
868 int modifierCount = 0; | 865 int modifierCount = 0; |
869 Token staticModifier; | 866 Token staticModifier; |
870 if (allowStatic && !modifiers.isEmpty | 867 if (allowStatic && |
871 && optional('static', modifiers.head)) { | 868 !modifiers.isEmpty && |
| 869 optional('static', modifiers.head)) { |
872 staticModifier = modifiers.head; | 870 staticModifier = modifiers.head; |
873 modifierCount++; | 871 modifierCount++; |
874 parseModifier(staticModifier); | 872 parseModifier(staticModifier); |
875 modifiers = modifiers.tail; | 873 modifiers = modifiers.tail; |
876 } | 874 } |
877 if (modifiers.isEmpty) { | 875 if (modifiers.isEmpty) { |
878 listener.handleModifiers(modifierCount); | 876 listener.handleModifiers(modifierCount); |
879 return null; | 877 return null; |
880 } | 878 } |
881 if (modifiers.tail.isEmpty) { | 879 if (modifiers.tail.isEmpty) { |
882 Token modifier = modifiers.head; | 880 Token modifier = modifiers.head; |
883 if (isVarFinalOrConst(modifier)) { | 881 if (isVarFinalOrConst(modifier)) { |
884 modifierCount++; | 882 modifierCount++; |
885 parseModifier(modifier); | 883 parseModifier(modifier); |
886 listener.handleModifiers(modifierCount); | 884 listener.handleModifiers(modifierCount); |
887 // TODO(ahe): The caller checks for "var Type name", perhaps we should | 885 // TODO(ahe): The caller checks for "var Type name", perhaps we should |
888 // check here instead. | 886 // check here instead. |
889 return modifier; | 887 return modifier; |
890 } | 888 } |
891 } | 889 } |
892 | 890 |
893 // Slow case to report errors. | 891 // Slow case to report errors. |
894 List<Token> modifierList = modifiers.toList(); | 892 List<Token> modifierList = modifiers.toList(); |
895 Token varFinalOrConst = | 893 Token varFinalOrConst = |
896 modifierList.firstWhere(isVarFinalOrConst, orElse: () => null); | 894 modifierList.firstWhere(isVarFinalOrConst, orElse: () => null); |
897 if (allowStatic && staticModifier == null) { | 895 if (allowStatic && staticModifier == null) { |
898 staticModifier = | 896 staticModifier = modifierList.firstWhere( |
899 modifierList.firstWhere( | 897 (modifier) => optional('static', modifier), |
900 (modifier) => optional('static', modifier), orElse: () => null); | 898 orElse: () => null); |
901 if (staticModifier != null) { | 899 if (staticModifier != null) { |
902 modifierCount++; | 900 modifierCount++; |
903 parseModifier(staticModifier); | 901 parseModifier(staticModifier); |
904 modifierList.remove(staticModifier); | 902 modifierList.remove(staticModifier); |
905 } | 903 } |
906 } | 904 } |
907 bool hasTypeOrModifier = hasType; | 905 bool hasTypeOrModifier = hasType; |
908 if (varFinalOrConst != null) { | 906 if (varFinalOrConst != null) { |
909 parseModifier(varFinalOrConst); | 907 parseModifier(varFinalOrConst); |
910 modifierCount++; | 908 modifierCount++; |
911 hasTypeOrModifier = true; | 909 hasTypeOrModifier = true; |
912 modifierList.remove(varFinalOrConst); | 910 modifierList.remove(varFinalOrConst); |
913 } | 911 } |
914 listener.handleModifiers(modifierCount); | 912 listener.handleModifiers(modifierCount); |
915 var kind = hasTypeOrModifier | 913 var kind = hasTypeOrModifier |
916 ? MessageKind.EXTRANEOUS_MODIFIER | 914 ? MessageKind.EXTRANEOUS_MODIFIER |
917 : MessageKind.EXTRANEOUS_MODIFIER_REPLACE; | 915 : MessageKind.EXTRANEOUS_MODIFIER_REPLACE; |
918 for (Token modifier in modifierList) { | 916 for (Token modifier in modifierList) { |
919 listener.reportError(modifier, kind, {'modifier': modifier}); | 917 listener.reportError(modifier, kind, {'modifier': modifier}); |
920 } | 918 } |
921 return null; | 919 return null; |
922 } | 920 } |
923 | 921 |
924 Token parseFields(Token start, | 922 Token parseFields(Token start, Link<Token> modifiers, Token type, |
925 Link<Token> modifiers, | 923 Token getOrSet, Token name, bool isTopLevel) { |
926 Token type, | |
927 Token getOrSet, | |
928 Token name, | |
929 bool isTopLevel) { | |
930 bool hasType = type != null; | 924 bool hasType = type != null; |
931 Token varFinalOrConst = | 925 Token varFinalOrConst = |
932 expectVarFinalOrConst(modifiers, hasType, !isTopLevel); | 926 expectVarFinalOrConst(modifiers, hasType, !isTopLevel); |
933 bool isVar = false; | 927 bool isVar = false; |
934 bool hasModifier = false; | 928 bool hasModifier = false; |
935 if (varFinalOrConst != null) { | 929 if (varFinalOrConst != null) { |
936 hasModifier = true; | 930 hasModifier = true; |
937 isVar = optional('var', varFinalOrConst); | 931 isVar = optional('var', varFinalOrConst); |
938 } | 932 } |
939 | 933 |
940 if (getOrSet != null) { | 934 if (getOrSet != null) { |
941 var kind = (hasModifier || hasType) | 935 var kind = (hasModifier || hasType) |
942 ? MessageKind.EXTRANEOUS_MODIFIER | 936 ? MessageKind.EXTRANEOUS_MODIFIER |
943 : MessageKind.EXTRANEOUS_MODIFIER_REPLACE; | 937 : MessageKind.EXTRANEOUS_MODIFIER_REPLACE; |
944 listener.reportError(getOrSet, kind, {'modifier': getOrSet}); | 938 listener.reportError(getOrSet, kind, {'modifier': getOrSet}); |
945 } | 939 } |
946 | 940 |
947 if (!hasType) { | 941 if (!hasType) { |
948 listener.handleNoType(name); | 942 listener.handleNoType(name); |
949 } else if (optional('void', type)) { | 943 } else if (optional('void', type)) { |
950 listener.handleNoType(name); | 944 listener.handleNoType(name); |
951 // TODO(ahe): This error is reported twice, second time is from | 945 // TODO(ahe): This error is reported twice, second time is from |
952 // [parseVariablesDeclarationMaybeSemicolon] via | 946 // [parseVariablesDeclarationMaybeSemicolon] via |
953 // [PartialFieldListElement.parseNode]. | 947 // [PartialFieldListElement.parseNode]. |
954 listener.reportError(type, MessageKind.VOID_NOT_ALLOWED); | 948 listener.reportError(type, MessageKind.VOID_NOT_ALLOWED); |
955 } else { | 949 } else { |
956 parseType(type); | 950 parseType(type); |
957 if (isVar) { | 951 if (isVar) { |
958 listener.reportError( | 952 listener.reportError(modifiers.head, MessageKind.EXTRANEOUS_MODIFIER, |
959 modifiers.head, MessageKind.EXTRANEOUS_MODIFIER, | |
960 {'modifier': modifiers.head}); | 953 {'modifier': modifiers.head}); |
961 } | 954 } |
962 } | 955 } |
963 | 956 |
964 Token token = parseIdentifier(name); | 957 Token token = parseIdentifier(name); |
965 | 958 |
966 int fieldCount = 1; | 959 int fieldCount = 1; |
967 token = parseVariableInitializerOpt(token); | 960 token = parseVariableInitializerOpt(token); |
968 while (optional(',', token)) { | 961 while (optional(',', token)) { |
969 token = parseIdentifier(token.next); | 962 token = parseIdentifier(token.next); |
970 token = parseVariableInitializerOpt(token); | 963 token = parseVariableInitializerOpt(token); |
971 ++fieldCount; | 964 ++fieldCount; |
972 } | 965 } |
973 Token semicolon = token; | 966 Token semicolon = token; |
974 token = expectSemicolon(token); | 967 token = expectSemicolon(token); |
975 if (isTopLevel) { | 968 if (isTopLevel) { |
976 listener.endTopLevelFields(fieldCount, start, semicolon); | 969 listener.endTopLevelFields(fieldCount, start, semicolon); |
977 } else { | 970 } else { |
978 listener.endFields(fieldCount, start, semicolon); | 971 listener.endFields(fieldCount, start, semicolon); |
979 } | 972 } |
980 return token; | 973 return token; |
981 } | 974 } |
982 | 975 |
983 Token parseTopLevelMethod(Token start, | 976 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, |
984 Link<Token> modifiers, | 977 Token getOrSet, Token name) { |
985 Token type, | |
986 Token getOrSet, | |
987 Token name) { | |
988 | |
989 Token externalModifier; | 978 Token externalModifier; |
990 // TODO(johnniwinther): Move error reporting to resolution to give more | 979 // TODO(johnniwinther): Move error reporting to resolution to give more |
991 // specific error messages. | 980 // specific error messages. |
992 for (Token modifier in modifiers) { | 981 for (Token modifier in modifiers) { |
993 if (externalModifier == null && optional('external', modifier)) { | 982 if (externalModifier == null && optional('external', modifier)) { |
994 externalModifier = modifier; | 983 externalModifier = modifier; |
995 } else { | 984 } else { |
996 listener.reportError( | 985 listener.reportError( |
997 modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); | 986 modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); |
998 } | 987 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 | 1044 |
1056 // `true` if 'get' has been seen. | 1045 // `true` if 'get' has been seen. |
1057 bool isGetter = false; | 1046 bool isGetter = false; |
1058 // `true` if an identifier has been seen after 'get'. | 1047 // `true` if an identifier has been seen after 'get'. |
1059 bool hasName = false; | 1048 bool hasName = false; |
1060 | 1049 |
1061 while (token.kind != EOF_TOKEN) { | 1050 while (token.kind != EOF_TOKEN) { |
1062 String value = token.stringValue; | 1051 String value = token.stringValue; |
1063 if (value == 'get') { | 1052 if (value == 'get') { |
1064 isGetter = true; | 1053 isGetter = true; |
1065 } else if (hasName && | 1054 } else if (hasName && (value == 'sync' || value == 'async')) { |
1066 (value == 'sync' || value == 'async')) { | |
1067 // Skip. | 1055 // Skip. |
1068 token = token.next; | 1056 token = token.next; |
1069 value = token.stringValue; | 1057 value = token.stringValue; |
1070 if (value == '*') { | 1058 if (value == '*') { |
1071 // Skip. | 1059 // Skip. |
1072 token = token.next; | 1060 token = token.next; |
1073 } | 1061 } |
1074 continue; | 1062 continue; |
1075 } else if (value == '(' || | 1063 } else if (value == '(' || value == '{' || value == '=>') { |
1076 value == '{' || | |
1077 value == '=>') { | |
1078 // A method. | 1064 // A method. |
1079 identifiers = identifiers.prepend(token); | 1065 identifiers = identifiers.prepend(token); |
1080 return identifiers; | 1066 return identifiers; |
1081 } else if (value == '=' || | 1067 } else if (value == '=' || value == ';' || value == ',') { |
1082 value == ';' || | |
1083 value == ',') { | |
1084 // A field or abstract getter. | 1068 // A field or abstract getter. |
1085 identifiers = identifiers.prepend(token); | 1069 identifiers = identifiers.prepend(token); |
1086 return identifiers; | 1070 return identifiers; |
1087 } else if (isGetter) { | 1071 } else if (isGetter) { |
1088 hasName = true; | 1072 hasName = true; |
1089 } | 1073 } |
1090 identifiers = identifiers.prepend(token); | 1074 identifiers = identifiers.prepend(token); |
1091 if (isValidTypeReference(token)) { | 1075 if (isValidTypeReference(token)) { |
1092 // type ... | 1076 // type ... |
1093 if (optional('.', token.next)) { | 1077 if (optional('.', token.next)) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 } | 1140 } |
1157 } | 1141 } |
1158 | 1142 |
1159 Token expectSemicolon(Token token) { | 1143 Token expectSemicolon(Token token) { |
1160 return expect(';', token); | 1144 return expect(';', token); |
1161 } | 1145 } |
1162 | 1146 |
1163 bool isModifier(Token token) { | 1147 bool isModifier(Token token) { |
1164 final String value = token.stringValue; | 1148 final String value = token.stringValue; |
1165 return (identical('final', value)) || | 1149 return (identical('final', value)) || |
1166 (identical('var', value)) || | 1150 (identical('var', value)) || |
1167 (identical('const', value)) || | 1151 (identical('const', value)) || |
1168 (identical('abstract', value)) || | 1152 (identical('abstract', value)) || |
1169 (identical('static', value)) || | 1153 (identical('static', value)) || |
1170 (identical('external', value)); | 1154 (identical('external', value)); |
1171 } | 1155 } |
1172 | 1156 |
1173 Token parseModifier(Token token) { | 1157 Token parseModifier(Token token) { |
1174 assert(isModifier(token)); | 1158 assert(isModifier(token)); |
1175 listener.handleModifier(token); | 1159 listener.handleModifier(token); |
1176 return token.next; | 1160 return token.next; |
1177 } | 1161 } |
1178 | 1162 |
1179 void parseModifierList(Link<Token> tokens) { | 1163 void parseModifierList(Link<Token> tokens) { |
1180 int count = 0; | 1164 int count = 0; |
1181 for (; !tokens.isEmpty; tokens = tokens.tail) { | 1165 for (; !tokens.isEmpty; tokens = tokens.tail) { |
1182 Token token = tokens.head; | 1166 Token token = tokens.head; |
1183 if (isModifier(token)) { | 1167 if (isModifier(token)) { |
1184 parseModifier(token); | 1168 parseModifier(token); |
1185 } else { | 1169 } else { |
1186 listener.unexpected(token); | 1170 listener.unexpected(token); |
1187 // Skip the remaining modifiers. | 1171 // Skip the remaining modifiers. |
1188 break; | 1172 break; |
1189 } | 1173 } |
1190 count++; | 1174 count++; |
1191 } | 1175 } |
1192 listener.handleModifiers(count); | 1176 listener.handleModifiers(count); |
1193 } | 1177 } |
1194 | 1178 |
1195 Token parseModifiers(Token token) { | 1179 Token parseModifiers(Token token) { |
1196 int count = 0; | 1180 int count = 0; |
1197 while (identical(token.kind, KEYWORD_TOKEN)) { | 1181 while (identical(token.kind, KEYWORD_TOKEN)) { |
1198 if (!isModifier(token)) | 1182 if (!isModifier(token)) break; |
1199 break; | |
1200 token = parseModifier(token); | 1183 token = parseModifier(token); |
1201 count++; | 1184 count++; |
1202 } | 1185 } |
1203 listener.handleModifiers(count); | 1186 listener.handleModifiers(count); |
1204 return token; | 1187 return token; |
1205 } | 1188 } |
1206 | 1189 |
1207 /** | 1190 /** |
1208 * Returns the first token after the type starting at [token]. | 1191 * Returns the first token after the type starting at [token]. |
1209 * This method assumes that [token] is an identifier (or void). | 1192 * This method assumes that [token] is an identifier (or void). |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1311 identifiers = identifiers.tail; | 1294 identifiers = identifiers.tail; |
1312 } | 1295 } |
1313 } | 1296 } |
1314 | 1297 |
1315 token = afterName; | 1298 token = afterName; |
1316 bool isField; | 1299 bool isField; |
1317 while (true) { | 1300 while (true) { |
1318 // Loop to allow the listener to rewrite the token stream for | 1301 // Loop to allow the listener to rewrite the token stream for |
1319 // error handling. | 1302 // error handling. |
1320 final String value = token.stringValue; | 1303 final String value = token.stringValue; |
1321 if ((identical(value, '(')) || (identical(value, '.')) | 1304 if ((identical(value, '(')) || |
1322 || (identical(value, '{')) || (identical(value, '=>'))) { | 1305 (identical(value, '.')) || |
| 1306 (identical(value, '{')) || |
| 1307 (identical(value, '=>'))) { |
1323 isField = false; | 1308 isField = false; |
1324 break; | 1309 break; |
1325 } else if (identical(value, ';')) { | 1310 } else if (identical(value, ';')) { |
1326 if (getOrSet != null) { | 1311 if (getOrSet != null) { |
1327 // If we found a "get" keyword, this must be an abstract | 1312 // If we found a "get" keyword, this must be an abstract |
1328 // getter. | 1313 // getter. |
1329 isField = (!identical(getOrSet.stringValue, 'get')); | 1314 isField = (!identical(getOrSet.stringValue, 'get')); |
1330 // TODO(ahe): This feels like a hack. | 1315 // TODO(ahe): This feels like a hack. |
1331 } else { | 1316 } else { |
1332 isField = true; | 1317 isField = true; |
1333 } | 1318 } |
1334 break; | 1319 break; |
1335 } else if ((identical(value, '=')) || (identical(value, ','))) { | 1320 } else if ((identical(value, '=')) || (identical(value, ','))) { |
1336 isField = true; | 1321 isField = true; |
1337 break; | 1322 break; |
1338 } else { | 1323 } else { |
1339 token = listener.unexpected(token); | 1324 token = listener.unexpected(token); |
1340 if (identical(token.kind, EOF_TOKEN)) { | 1325 if (identical(token.kind, EOF_TOKEN)) { |
1341 // TODO(ahe): This is a hack, see parseTopLevelMember. | 1326 // TODO(ahe): This is a hack, see parseTopLevelMember. |
1342 listener.endFields(1, start, token); | 1327 listener.endFields(1, start, token); |
1343 return token; | 1328 return token; |
1344 } | 1329 } |
1345 } | 1330 } |
1346 } | 1331 } |
1347 | 1332 |
1348 var modifiers = identifiers.reverse(); | 1333 var modifiers = identifiers.reverse(); |
1349 return isField | 1334 return isField |
1350 ? parseFields(start, modifiers, type, getOrSet, name, false) | 1335 ? parseFields(start, modifiers, type, getOrSet, name, false) |
1351 : parseMethod(start, modifiers, type, getOrSet, name); | 1336 : parseMethod(start, modifiers, type, getOrSet, name); |
1352 | |
1353 } | 1337 } |
1354 | 1338 |
1355 Token parseMethod(Token start, | 1339 Token parseMethod(Token start, Link<Token> modifiers, Token type, |
1356 Link<Token> modifiers, | 1340 Token getOrSet, Token name) { |
1357 Token type, | |
1358 Token getOrSet, | |
1359 Token name) { | |
1360 Token externalModifier; | 1341 Token externalModifier; |
1361 Token staticModifier; | 1342 Token staticModifier; |
1362 Token constModifier; | 1343 Token constModifier; |
1363 int modifierCount = 0; | 1344 int modifierCount = 0; |
1364 int allowedModifierCount = 1; | 1345 int allowedModifierCount = 1; |
1365 // TODO(johnniwinther): Move error reporting to resolution to give more | 1346 // TODO(johnniwinther): Move error reporting to resolution to give more |
1366 // specific error messages. | 1347 // specific error messages. |
1367 for (Token modifier in modifiers) { | 1348 for (Token modifier in modifiers) { |
1368 if (externalModifier == null && optional('external', modifier)) { | 1349 if (externalModifier == null && optional('external', modifier)) { |
1369 modifierCount++; | 1350 modifierCount++; |
1370 externalModifier = modifier; | 1351 externalModifier = modifier; |
1371 if (modifierCount != allowedModifierCount) { | 1352 if (modifierCount != allowedModifierCount) { |
1372 listener.reportError( | 1353 listener.reportError(modifier, MessageKind.EXTRANEOUS_MODIFIER, |
1373 modifier, | 1354 {'modifier': modifier}); |
1374 MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); | |
1375 } | 1355 } |
1376 allowedModifierCount++; | 1356 allowedModifierCount++; |
1377 } else if (staticModifier == null && optional('static', modifier)) { | 1357 } else if (staticModifier == null && optional('static', modifier)) { |
1378 modifierCount++; | 1358 modifierCount++; |
1379 staticModifier = modifier; | 1359 staticModifier = modifier; |
1380 if (modifierCount != allowedModifierCount) { | 1360 if (modifierCount != allowedModifierCount) { |
1381 listener.reportError( | 1361 listener.reportError(modifier, MessageKind.EXTRANEOUS_MODIFIER, |
1382 modifier, | 1362 {'modifier': modifier}); |
1383 MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); | |
1384 } | 1363 } |
1385 } else if (constModifier == null && optional('const', modifier)) { | 1364 } else if (constModifier == null && optional('const', modifier)) { |
1386 modifierCount++; | 1365 modifierCount++; |
1387 constModifier = modifier; | 1366 constModifier = modifier; |
1388 if (modifierCount != allowedModifierCount) { | 1367 if (modifierCount != allowedModifierCount) { |
1389 listener.reportError( | 1368 listener.reportError(modifier, MessageKind.EXTRANEOUS_MODIFIER, |
1390 modifier, | 1369 {'modifier': modifier}); |
1391 MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); | |
1392 } | 1370 } |
1393 } else { | 1371 } else { |
1394 listener.reportError( | 1372 listener.reportError( |
1395 modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); | 1373 modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); |
1396 } | 1374 } |
1397 } | 1375 } |
1398 if (getOrSet != null && constModifier != null) { | 1376 if (getOrSet != null && constModifier != null) { |
1399 listener.reportError( | 1377 listener.reportError(constModifier, MessageKind.EXTRANEOUS_MODIFIER, |
1400 constModifier, MessageKind.EXTRANEOUS_MODIFIER, | |
1401 {'modifier': constModifier}); | 1378 {'modifier': constModifier}); |
1402 } | 1379 } |
1403 parseModifierList(modifiers); | 1380 parseModifierList(modifiers); |
1404 | 1381 |
1405 if (type == null) { | 1382 if (type == null) { |
1406 listener.handleNoType(name); | 1383 listener.handleNoType(name); |
1407 } else { | 1384 } else { |
1408 parseReturnTypeOpt(type); | 1385 parseReturnTypeOpt(type); |
1409 } | 1386 } |
1410 Token token; | 1387 Token token; |
1411 if (optional('operator', name)) { | 1388 if (optional('operator', name)) { |
1412 token = parseOperatorName(name); | 1389 token = parseOperatorName(name); |
1413 if (staticModifier != null) { | 1390 if (staticModifier != null) { |
1414 listener.reportError( | 1391 listener.reportError(staticModifier, MessageKind.EXTRANEOUS_MODIFIER, |
1415 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, | |
1416 {'modifier': staticModifier}); | 1392 {'modifier': staticModifier}); |
1417 } | 1393 } |
1418 } else { | 1394 } else { |
1419 token = parseIdentifier(name); | 1395 token = parseIdentifier(name); |
1420 } | 1396 } |
1421 | 1397 |
1422 token = parseQualifiedRestOpt(token); | 1398 token = parseQualifiedRestOpt(token); |
1423 token = parseFormalParametersOpt(token); | 1399 token = parseFormalParametersOpt(token); |
1424 token = parseInitializersOpt(token); | 1400 token = parseInitializersOpt(token); |
1425 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1401 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1631 token = token.next; | 1607 token = token.next; |
1632 } | 1608 } |
1633 } else if (optional('sync', token)) { | 1609 } else if (optional('sync', token)) { |
1634 async = token; | 1610 async = token; |
1635 token = token.next; | 1611 token = token.next; |
1636 if (optional('*', token)) { | 1612 if (optional('*', token)) { |
1637 asyncAwaitKeywordsEnabled = true; | 1613 asyncAwaitKeywordsEnabled = true; |
1638 star = token; | 1614 star = token; |
1639 token = token.next; | 1615 token = token.next; |
1640 } else { | 1616 } else { |
1641 listener.reportError(async, | 1617 listener.reportError(async, MessageKind.INVALID_SYNC_MODIFIER); |
1642 MessageKind.INVALID_SYNC_MODIFIER); | |
1643 } | 1618 } |
1644 } | 1619 } |
1645 listener.handleAsyncModifier(async, star); | 1620 listener.handleAsyncModifier(async, star); |
1646 return token; | 1621 return token; |
1647 } | 1622 } |
1648 | 1623 |
1649 Token parseStatement(Token token) { | 1624 Token parseStatement(Token token) { |
1650 final value = token.stringValue; | 1625 final value = token.stringValue; |
1651 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 1626 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
1652 return parseExpressionStatementOrDeclaration(token); | 1627 return parseExpressionStatementOrDeclaration(token); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1708 Token starToken; | 1683 Token starToken; |
1709 if (optional('*', token)) { | 1684 if (optional('*', token)) { |
1710 starToken = token; | 1685 starToken = token; |
1711 token = token.next; | 1686 token = token.next; |
1712 } | 1687 } |
1713 token = parseExpression(token); | 1688 token = parseExpression(token); |
1714 listener.endYieldStatement(begin, starToken, token); | 1689 listener.endYieldStatement(begin, starToken, token); |
1715 return expectSemicolon(token); | 1690 return expectSemicolon(token); |
1716 } | 1691 } |
1717 | 1692 |
1718 | |
1719 Token parseReturnStatement(Token token) { | 1693 Token parseReturnStatement(Token token) { |
1720 Token begin = token; | 1694 Token begin = token; |
1721 listener.beginReturnStatement(begin); | 1695 listener.beginReturnStatement(begin); |
1722 assert(identical('return', token.stringValue)); | 1696 assert(identical('return', token.stringValue)); |
1723 token = token.next; | 1697 token = token.next; |
1724 if (optional(';', token)) { | 1698 if (optional(';', token)) { |
1725 listener.endReturnStatement(false, begin, token); | 1699 listener.endReturnStatement(false, begin, token); |
1726 } else { | 1700 } else { |
1727 token = parseExpression(token); | 1701 token = parseExpression(token); |
1728 listener.endReturnStatement(true, begin, token); | 1702 listener.endReturnStatement(true, begin, token); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1863 assert(optional('?', token)); | 1837 assert(optional('?', token)); |
1864 Token question = token; | 1838 Token question = token; |
1865 token = parseExpressionWithoutCascade(token.next); | 1839 token = parseExpressionWithoutCascade(token.next); |
1866 Token colon = token; | 1840 Token colon = token; |
1867 token = expect(':', token); | 1841 token = expect(':', token); |
1868 token = parseExpressionWithoutCascade(token); | 1842 token = parseExpressionWithoutCascade(token); |
1869 listener.handleConditionalExpression(question, colon); | 1843 listener.handleConditionalExpression(question, colon); |
1870 return token; | 1844 return token; |
1871 } | 1845 } |
1872 | 1846 |
1873 Token parsePrecedenceExpression(Token token, int precedence, | 1847 Token parsePrecedenceExpression( |
1874 bool allowCascades) { | 1848 Token token, int precedence, bool allowCascades) { |
1875 assert(precedence >= 1); | 1849 assert(precedence >= 1); |
1876 assert(precedence <= POSTFIX_PRECEDENCE); | 1850 assert(precedence <= POSTFIX_PRECEDENCE); |
1877 token = parseUnaryExpression(token, allowCascades); | 1851 token = parseUnaryExpression(token, allowCascades); |
1878 PrecedenceInfo info = token.info; | 1852 PrecedenceInfo info = token.info; |
1879 int tokenLevel = info.precedence; | 1853 int tokenLevel = info.precedence; |
1880 for (int level = tokenLevel; level >= precedence; --level) { | 1854 for (int level = tokenLevel; level >= precedence; --level) { |
1881 while (identical(tokenLevel, level)) { | 1855 while (identical(tokenLevel, level)) { |
1882 Token operator = token; | 1856 Token operator = token; |
1883 if (identical(tokenLevel, CASCADE_PRECEDENCE)) { | 1857 if (identical(tokenLevel, CASCADE_PRECEDENCE)) { |
1884 if (!allowCascades) { | 1858 if (!allowCascades) { |
1885 return token; | 1859 return token; |
1886 } | 1860 } |
1887 token = parseCascadeExpression(token); | 1861 token = parseCascadeExpression(token); |
1888 } else if (identical(tokenLevel, ASSIGNMENT_PRECEDENCE)) { | 1862 } else if (identical(tokenLevel, ASSIGNMENT_PRECEDENCE)) { |
1889 // Right associative, so we recurse at the same precedence | 1863 // Right associative, so we recurse at the same precedence |
1890 // level. | 1864 // level. |
1891 token = parsePrecedenceExpression(token.next, level, allowCascades); | 1865 token = parsePrecedenceExpression(token.next, level, allowCascades); |
1892 listener.handleAssignmentExpression(operator); | 1866 listener.handleAssignmentExpression(operator); |
1893 } else if (identical(tokenLevel, POSTFIX_PRECEDENCE)) { | 1867 } else if (identical(tokenLevel, POSTFIX_PRECEDENCE)) { |
1894 if (identical(info, PERIOD_INFO) || | 1868 if (identical(info, PERIOD_INFO) || |
1895 identical(info, QUESTION_PERIOD_INFO)) { | 1869 identical(info, QUESTION_PERIOD_INFO)) { |
1896 // Left associative, so we recurse at the next higher | 1870 // Left associative, so we recurse at the next higher |
1897 // precedence level. However, POSTFIX_PRECEDENCE is the | 1871 // precedence level. However, POSTFIX_PRECEDENCE is the |
1898 // highest level, so we just call parseUnaryExpression | 1872 // highest level, so we just call parseUnaryExpression |
1899 // directly. | 1873 // directly. |
1900 token = parseUnaryExpression(token.next, allowCascades); | 1874 token = parseUnaryExpression(token.next, allowCascades); |
1901 listener.handleBinaryExpression(operator); | 1875 listener.handleBinaryExpression(operator); |
1902 } else if ((identical(info, OPEN_PAREN_INFO)) || | 1876 } else if ((identical(info, OPEN_PAREN_INFO)) || |
1903 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { | 1877 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { |
1904 token = parseArgumentOrIndexStar(token); | 1878 token = parseArgumentOrIndexStar(token); |
1905 } else if ((identical(info, PLUS_PLUS_INFO)) || | 1879 } else if ((identical(info, PLUS_PLUS_INFO)) || |
1906 (identical(info, MINUS_MINUS_INFO))) { | 1880 (identical(info, MINUS_MINUS_INFO))) { |
1907 listener.handleUnaryPostfixAssignmentExpression(token); | 1881 listener.handleUnaryPostfixAssignmentExpression(token); |
1908 token = token.next; | 1882 token = token.next; |
1909 } else { | 1883 } else { |
1910 token = listener.unexpected(token); | 1884 token = listener.unexpected(token); |
1911 } | 1885 } |
1912 } else if (identical(info, IS_INFO)) { | 1886 } else if (identical(info, IS_INFO)) { |
1913 token = parseIsOperatorRest(token); | 1887 token = parseIsOperatorRest(token); |
1914 } else if (identical(info, AS_INFO)) { | 1888 } else if (identical(info, AS_INFO)) { |
1915 token = parseAsOperatorRest(token); | 1889 token = parseAsOperatorRest(token); |
1916 } else if (identical(info, QUESTION_INFO)) { | 1890 } else if (identical(info, QUESTION_INFO)) { |
1917 token = parseConditionalExpressionRest(token); | 1891 token = parseConditionalExpressionRest(token); |
1918 } else { | 1892 } else { |
1919 // Left associative, so we recurse at the next higher | 1893 // Left associative, so we recurse at the next higher |
1920 // precedence level. | 1894 // precedence level. |
1921 token = parsePrecedenceExpression(token.next, level + 1, | 1895 token = |
1922 allowCascades); | 1896 parsePrecedenceExpression(token.next, level + 1, allowCascades); |
1923 listener.handleBinaryExpression(operator); | 1897 listener.handleBinaryExpression(operator); |
1924 } | 1898 } |
1925 info = token.info; | 1899 info = token.info; |
1926 tokenLevel = info.precedence; | 1900 tokenLevel = info.precedence; |
1927 if (level == EQUALITY_PRECEDENCE || level == RELATIONAL_PRECEDENCE) { | 1901 if (level == EQUALITY_PRECEDENCE || level == RELATIONAL_PRECEDENCE) { |
1928 // We don't allow (a == b == c) or (a < b < c). | 1902 // We don't allow (a == b == c) or (a < b < c). |
1929 // Continue the outer loop if we have matched one equality or | 1903 // Continue the outer loop if we have matched one equality or |
1930 // relational operator. | 1904 // relational operator. |
1931 break; | 1905 break; |
1932 } | 1906 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1971 Token parseUnaryExpression(Token token, bool allowCascades) { | 1945 Token parseUnaryExpression(Token token, bool allowCascades) { |
1972 String value = token.stringValue; | 1946 String value = token.stringValue; |
1973 // Prefix: | 1947 // Prefix: |
1974 if (asyncAwaitKeywordsEnabled && optional('await', token)) { | 1948 if (asyncAwaitKeywordsEnabled && optional('await', token)) { |
1975 return parseAwaitExpression(token, allowCascades); | 1949 return parseAwaitExpression(token, allowCascades); |
1976 } else if (identical(value, '+')) { | 1950 } else if (identical(value, '+')) { |
1977 // Dart no longer allows prefix-plus. | 1951 // Dart no longer allows prefix-plus. |
1978 listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS); | 1952 listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS); |
1979 return parseUnaryExpression(token.next, allowCascades); | 1953 return parseUnaryExpression(token.next, allowCascades); |
1980 } else if ((identical(value, '!')) || | 1954 } else if ((identical(value, '!')) || |
1981 (identical(value, '-')) || | 1955 (identical(value, '-')) || |
1982 (identical(value, '~'))) { | 1956 (identical(value, '~'))) { |
1983 Token operator = token; | 1957 Token operator = token; |
1984 // Right associative, so we recurse at the same precedence | 1958 // Right associative, so we recurse at the same precedence |
1985 // level. | 1959 // level. |
1986 token = parsePrecedenceExpression(token.next, POSTFIX_PRECEDENCE, | 1960 token = parsePrecedenceExpression( |
1987 allowCascades); | 1961 token.next, POSTFIX_PRECEDENCE, allowCascades); |
1988 listener.handleUnaryPrefixExpression(operator); | 1962 listener.handleUnaryPrefixExpression(operator); |
1989 } else if ((identical(value, '++')) || identical(value, '--')) { | 1963 } else if ((identical(value, '++')) || identical(value, '--')) { |
1990 // TODO(ahe): Validate this is used correctly. | 1964 // TODO(ahe): Validate this is used correctly. |
1991 Token operator = token; | 1965 Token operator = token; |
1992 // Right associative, so we recurse at the same precedence | 1966 // Right associative, so we recurse at the same precedence |
1993 // level. | 1967 // level. |
1994 token = parsePrecedenceExpression(token.next, POSTFIX_PRECEDENCE, | 1968 token = parsePrecedenceExpression( |
1995 allowCascades); | 1969 token.next, POSTFIX_PRECEDENCE, allowCascades); |
1996 listener.handleUnaryPrefixAssignmentExpression(operator); | 1970 listener.handleUnaryPrefixAssignmentExpression(operator); |
1997 } else { | 1971 } else { |
1998 token = parsePrimary(token); | 1972 token = parsePrimary(token); |
1999 } | 1973 } |
2000 return token; | 1974 return token; |
2001 } | 1975 } |
2002 | 1976 |
2003 Token parseArgumentOrIndexStar(Token token) { | 1977 Token parseArgumentOrIndexStar(Token token) { |
2004 while (true) { | 1978 while (true) { |
2005 if (optional('[', token)) { | 1979 if (optional('[', token)) { |
(...skipping 11 matching lines...) Expand all Loading... |
2017 break; | 1991 break; |
2018 } | 1992 } |
2019 } | 1993 } |
2020 return token; | 1994 return token; |
2021 } | 1995 } |
2022 | 1996 |
2023 Token parsePrimary(Token token) { | 1997 Token parsePrimary(Token token) { |
2024 final kind = token.kind; | 1998 final kind = token.kind; |
2025 if (kind == IDENTIFIER_TOKEN) { | 1999 if (kind == IDENTIFIER_TOKEN) { |
2026 return parseSendOrFunctionLiteral(token); | 2000 return parseSendOrFunctionLiteral(token); |
2027 } else if (kind == INT_TOKEN | 2001 } else if (kind == INT_TOKEN || kind == HEXADECIMAL_TOKEN) { |
2028 || kind == HEXADECIMAL_TOKEN) { | |
2029 return parseLiteralInt(token); | 2002 return parseLiteralInt(token); |
2030 } else if (kind == DOUBLE_TOKEN) { | 2003 } else if (kind == DOUBLE_TOKEN) { |
2031 return parseLiteralDouble(token); | 2004 return parseLiteralDouble(token); |
2032 } else if (kind == STRING_TOKEN) { | 2005 } else if (kind == STRING_TOKEN) { |
2033 return parseLiteralString(token); | 2006 return parseLiteralString(token); |
2034 } else if (kind == HASH_TOKEN) { | 2007 } else if (kind == HASH_TOKEN) { |
2035 return parseLiteralSymbol(token); | 2008 return parseLiteralSymbol(token); |
2036 } else if (kind == KEYWORD_TOKEN) { | 2009 } else if (kind == KEYWORD_TOKEN) { |
2037 final value = token.stringValue; | 2010 final value = token.stringValue; |
2038 if (value == 'true' || value == 'false') { | 2011 if (value == 'true' || value == 'false') { |
2039 return parseLiteralBool(token); | 2012 return parseLiteralBool(token); |
2040 } else if (value == 'null') { | 2013 } else if (value == 'null') { |
2041 return parseLiteralNull(token); | 2014 return parseLiteralNull(token); |
2042 } else if (value == 'this') { | 2015 } else if (value == 'this') { |
2043 return parseThisExpression(token); | 2016 return parseThisExpression(token); |
2044 } else if (value == 'super') { | 2017 } else if (value == 'super') { |
2045 return parseSuperExpression(token); | 2018 return parseSuperExpression(token); |
2046 } else if (value == 'new') { | 2019 } else if (value == 'new') { |
2047 return parseNewExpression(token); | 2020 return parseNewExpression(token); |
2048 } else if (value == 'const') { | 2021 } else if (value == 'const') { |
2049 return parseConstExpression(token); | 2022 return parseConstExpression(token); |
2050 } else if (value == 'void') { | 2023 } else if (value == 'void') { |
2051 return parseFunctionExpression(token); | 2024 return parseFunctionExpression(token); |
2052 } else if (asyncAwaitKeywordsEnabled && | 2025 } else if (asyncAwaitKeywordsEnabled && |
2053 (value == 'yield' || value == 'async')) { | 2026 (value == 'yield' || value == 'async')) { |
2054 return listener.expectedExpression(token); | 2027 return listener.expectedExpression(token); |
2055 } else if (token.isIdentifier()) { | 2028 } else if (token.isIdentifier()) { |
2056 return parseSendOrFunctionLiteral(token); | 2029 return parseSendOrFunctionLiteral(token); |
2057 } else { | 2030 } else { |
2058 return listener.expectedExpression(token); | 2031 return listener.expectedExpression(token); |
2059 } | 2032 } |
2060 } else if (kind == OPEN_PAREN_TOKEN) { | 2033 } else if (kind == OPEN_PAREN_TOKEN) { |
2061 return parseParenthesizedExpressionOrFunctionLiteral(token); | 2034 return parseParenthesizedExpressionOrFunctionLiteral(token); |
2062 } else if ((kind == LT_TOKEN) || | 2035 } else if ((kind == LT_TOKEN) || |
2063 (kind == OPEN_SQUARE_BRACKET_TOKEN) || | 2036 (kind == OPEN_SQUARE_BRACKET_TOKEN) || |
2064 (kind == OPEN_CURLY_BRACKET_TOKEN) || | 2037 (kind == OPEN_CURLY_BRACKET_TOKEN) || |
2065 token.stringValue == '[]') { | 2038 token.stringValue == '[]') { |
2066 return parseLiteralListOrMap(token); | 2039 return parseLiteralListOrMap(token); |
2067 } else { | 2040 } else { |
2068 return listener.expectedExpression(token); | 2041 return listener.expectedExpression(token); |
2069 } | 2042 } |
2070 } | 2043 } |
2071 | 2044 |
2072 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 2045 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
2073 BeginGroupToken beginGroup = token; | 2046 BeginGroupToken beginGroup = token; |
2074 Token nextToken = beginGroup.endGroup.next; | 2047 Token nextToken = beginGroup.endGroup.next; |
2075 int kind = nextToken.kind; | 2048 int kind = nextToken.kind; |
2076 if (mayParseFunctionExpressions && | 2049 if (mayParseFunctionExpressions && |
2077 (identical(kind, FUNCTION_TOKEN) || | 2050 (identical(kind, FUNCTION_TOKEN) || |
2078 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || | 2051 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || |
2079 (identical(kind, KEYWORD_TOKEN) && | 2052 (identical(kind, KEYWORD_TOKEN) && |
2080 (nextToken.value == 'async' || nextToken.value == 'sync')))) { | 2053 (nextToken.value == 'async' || nextToken.value == 'sync')))) { |
2081 return parseUnnamedFunction(token); | 2054 return parseUnnamedFunction(token); |
2082 } else { | 2055 } else { |
2083 bool old = mayParseFunctionExpressions; | 2056 bool old = mayParseFunctionExpressions; |
2084 mayParseFunctionExpressions = true; | 2057 mayParseFunctionExpressions = true; |
2085 token = parseParenthesizedExpression(token); | 2058 token = parseParenthesizedExpression(token); |
2086 mayParseFunctionExpressions = old; | 2059 mayParseFunctionExpressions = old; |
2087 return token; | 2060 return token; |
2088 } | 2061 } |
2089 } | 2062 } |
2090 | 2063 |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 | 2382 |
2410 Token parseVariablesDeclaration(Token token) { | 2383 Token parseVariablesDeclaration(Token token) { |
2411 return parseVariablesDeclarationMaybeSemicolon(token, true); | 2384 return parseVariablesDeclarationMaybeSemicolon(token, true); |
2412 } | 2385 } |
2413 | 2386 |
2414 Token parseVariablesDeclarationNoSemicolon(Token token) { | 2387 Token parseVariablesDeclarationNoSemicolon(Token token) { |
2415 // Only called when parsing a for loop, so this is for parsing locals. | 2388 // Only called when parsing a for loop, so this is for parsing locals. |
2416 return parseVariablesDeclarationMaybeSemicolon(token, false); | 2389 return parseVariablesDeclarationMaybeSemicolon(token, false); |
2417 } | 2390 } |
2418 | 2391 |
2419 Token parseVariablesDeclarationMaybeSemicolon(Token token, | 2392 Token parseVariablesDeclarationMaybeSemicolon( |
2420 bool endWithSemicolon) { | 2393 Token token, bool endWithSemicolon) { |
2421 int count = 1; | 2394 int count = 1; |
2422 listener.beginVariablesDeclaration(token); | 2395 listener.beginVariablesDeclaration(token); |
2423 token = parseModifiers(token); | 2396 token = parseModifiers(token); |
2424 token = parseTypeOpt(token); | 2397 token = parseTypeOpt(token); |
2425 token = parseOptionallyInitializedIdentifier(token); | 2398 token = parseOptionallyInitializedIdentifier(token); |
2426 while (optional(',', token)) { | 2399 while (optional(',', token)) { |
2427 token = parseOptionallyInitializedIdentifier(token.next); | 2400 token = parseOptionallyInitializedIdentifier(token.next); |
2428 ++count; | 2401 ++count; |
2429 } | 2402 } |
2430 if (endWithSemicolon) { | 2403 if (endWithSemicolon) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2561 ++statementCount; | 2534 ++statementCount; |
2562 } | 2535 } |
2563 listener.endBlock(statementCount, begin, token); | 2536 listener.endBlock(statementCount, begin, token); |
2564 return expect('}', token); | 2537 return expect('}', token); |
2565 } | 2538 } |
2566 | 2539 |
2567 Token parseAwaitExpression(Token token, bool allowCascades) { | 2540 Token parseAwaitExpression(Token token, bool allowCascades) { |
2568 Token awaitToken = token; | 2541 Token awaitToken = token; |
2569 listener.beginAwaitExpression(awaitToken); | 2542 listener.beginAwaitExpression(awaitToken); |
2570 token = expect('await', token); | 2543 token = expect('await', token); |
2571 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, | 2544 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades); |
2572 allowCascades); | |
2573 listener.endAwaitExpression(awaitToken, token); | 2545 listener.endAwaitExpression(awaitToken, token); |
2574 return token; | 2546 return token; |
2575 } | 2547 } |
2576 | 2548 |
2577 Token parseThrowExpression(Token token, bool allowCascades) { | 2549 Token parseThrowExpression(Token token, bool allowCascades) { |
2578 Token throwToken = token; | 2550 Token throwToken = token; |
2579 listener.beginThrowExpression(throwToken); | 2551 listener.beginThrowExpression(throwToken); |
2580 token = expect('throw', token); | 2552 token = expect('throw', token); |
2581 token = allowCascades | 2553 token = allowCascades |
2582 ? parseExpression(token) | 2554 ? parseExpression(token) |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2725 ((identical(value, '}')) && (identical(token, peek)))) { | 2697 ((identical(value, '}')) && (identical(token, peek)))) { |
2726 // A label just before "}" will be handled as a statement error. | 2698 // A label just before "}" will be handled as a statement error. |
2727 break; | 2699 break; |
2728 } else { | 2700 } else { |
2729 token = parseStatement(token); | 2701 token = parseStatement(token); |
2730 } | 2702 } |
2731 statementCount++; | 2703 statementCount++; |
2732 peek = peekPastLabels(token); | 2704 peek = peekPastLabels(token); |
2733 } | 2705 } |
2734 listener.handleSwitchCase(labelCount, expressionCount, defaultKeyword, | 2706 listener.handleSwitchCase(labelCount, expressionCount, defaultKeyword, |
2735 statementCount, begin, token); | 2707 statementCount, begin, token); |
2736 return token; | 2708 return token; |
2737 } | 2709 } |
2738 | 2710 |
2739 Token parseBreakStatement(Token token) { | 2711 Token parseBreakStatement(Token token) { |
2740 assert(optional('break', token)); | 2712 assert(optional('break', token)); |
2741 Token breakKeyword = token; | 2713 Token breakKeyword = token; |
2742 token = token.next; | 2714 token = token.next; |
2743 bool hasTarget = false; | 2715 bool hasTarget = false; |
2744 if (token.isIdentifier()) { | 2716 if (token.isIdentifier()) { |
2745 token = parseIdentifier(token); | 2717 token = parseIdentifier(token); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2779 } | 2751 } |
2780 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2752 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
2781 return expectSemicolon(token); | 2753 return expectSemicolon(token); |
2782 } | 2754 } |
2783 | 2755 |
2784 Token parseEmptyStatement(Token token) { | 2756 Token parseEmptyStatement(Token token) { |
2785 listener.handleEmptyStatement(token); | 2757 listener.handleEmptyStatement(token); |
2786 return expectSemicolon(token); | 2758 return expectSemicolon(token); |
2787 } | 2759 } |
2788 } | 2760 } |
OLD | NEW |