Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2876813002: Implement generalized function types. (Closed)
Patch Set: Address comments. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 fasta.parser.parser; 5 library fasta.parser.parser;
6 6
7 import '../fasta_codes.dart' 7 import '../fasta_codes.dart'
8 show 8 show
9 FastaCode, 9 FastaCode,
10 FastaMessage, 10 FastaMessage,
(...skipping 12 matching lines...) Expand all
23 codeExpectedBody, 23 codeExpectedBody,
24 codeExpectedButGot, 24 codeExpectedButGot,
25 codeExpectedClassBody, 25 codeExpectedClassBody,
26 codeExpectedClassBodyToSkip, 26 codeExpectedClassBodyToSkip,
27 codeExpectedDeclaration, 27 codeExpectedDeclaration,
28 codeExpectedExpression, 28 codeExpectedExpression,
29 codeExpectedFunctionBody, 29 codeExpectedFunctionBody,
30 codeExpectedIdentifier, 30 codeExpectedIdentifier,
31 codeExpectedOpenParens, 31 codeExpectedOpenParens,
32 codeExpectedString, 32 codeExpectedString,
33 codeExpectedType,
34 codeExtraneousModifier, 33 codeExtraneousModifier,
35 codeExtraneousModifierReplace,
36 codeFactoryNotSync, 34 codeFactoryNotSync,
37 codeGeneratorReturnsValue, 35 codeGeneratorReturnsValue,
38 codeInvalidAwaitFor, 36 codeInvalidAwaitFor,
39 codeInvalidInlineFunctionType, 37 codeInvalidInlineFunctionType,
40 codeInvalidSyncModifier, 38 codeInvalidSyncModifier,
41 codeInvalidVoid, 39 codeInvalidVoid,
42 codeNonAsciiIdentifier, 40 codeNonAsciiIdentifier,
43 codeNonAsciiWhitespace, 41 codeNonAsciiWhitespace,
44 codeOnlyTry, 42 codeOnlyTry,
45 codePositionalParameterWithEquals, 43 codePositionalParameterWithEquals,
46 codeRequiredParameterWithDefault, 44 codeRequiredParameterWithDefault,
47 codeSetterNotSync, 45 codeSetterNotSync,
48 codeStackOverflow, 46 codeStackOverflow,
47 codeTypeAfterVar,
48 codeTypeRequired,
49 codeUnexpectedToken, 49 codeUnexpectedToken,
50 codeUnmatchedToken, 50 codeUnmatchedToken,
51 codeUnspecified, 51 codeUnspecified,
52 codeUnsupportedPrefixPlus, 52 codeUnsupportedPrefixPlus,
53 codeUnterminatedString, 53 codeUnterminatedString,
54 codeYieldAsIdentifier, 54 codeYieldAsIdentifier,
55 codeYieldNotGenerator; 55 codeYieldNotGenerator;
56 56
57 import '../scanner.dart' show ErrorToken, Token; 57 import '../scanner.dart' show ErrorToken, Token;
58 58
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 final String type; 113 final String type;
114 const FormalParameterType(this.type); 114 const FormalParameterType(this.type);
115 bool get isRequired => this == REQUIRED; 115 bool get isRequired => this == REQUIRED;
116 bool get isPositional => this == POSITIONAL; 116 bool get isPositional => this == POSITIONAL;
117 bool get isNamed => this == NAMED; 117 bool get isNamed => this == NAMED;
118 static final REQUIRED = const FormalParameterType('required'); 118 static final REQUIRED = const FormalParameterType('required');
119 static final POSITIONAL = const FormalParameterType('positional'); 119 static final POSITIONAL = const FormalParameterType('positional');
120 static final NAMED = const FormalParameterType('named'); 120 static final NAMED = const FormalParameterType('named');
121 } 121 }
122 122
123 enum MemberKind {
124 /// A catch block, not a real member.
125 Catch,
126
127 /// A factory
128 Factory,
129
130 /// Old-style typedef.
131 FunctionTypeAlias,
132
133 /// Old-style function-typed parameter, not a real member.
134 FunctionTypedParameter,
135
136 /// A generalized function type, not a real member.
137 GeneralizedFunctionType,
138
139 /// A local function.
140 Local,
141
142 /// A non-static method in a class (including constructors).
143 NonStaticMethod,
144
145 /// A static method in a class.
146 StaticMethod,
147
148 /// A top-level method.
149 TopLevelMethod,
150
151 /// An instance field in a class.
152 NonStaticField,
153
154 /// A static field in a class.
155 StaticField,
156
157 /// A top-level field.
158 TopLevelField,
159 }
160
123 /// An event generating parser of Dart programs. This parser expects all tokens 161 /// An event generating parser of Dart programs. This parser expects all tokens
124 /// in a linked list (aka a token stream). 162 /// in a linked list (aka a token stream).
125 /// 163 ///
126 /// The class [Scanner] is used to generate a token stream. See the file 164 /// The class [Scanner] is used to generate a token stream. See the file
127 /// [scanner.dart](../scanner.dart). 165 /// [scanner.dart](../scanner.dart).
128 /// 166 ///
129 /// Subclasses of the class [Listener] are used to listen to events. 167 /// Subclasses of the class [Listener] are used to listen to events.
130 /// 168 ///
131 /// Most methods of this class belong in one of three major categories: parse 169 /// Most methods of this class belong in one of three major categories: parse
132 /// methods, peek methods, and skip methods. Parse methods all have the prefix 170 /// methods, peek methods, and skip methods. Parse methods all have the prefix
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 if (identical(token.type, TokenType.SCRIPT_TAG)) { 328 if (identical(token.type, TokenType.SCRIPT_TAG)) {
291 return parseScript(token); 329 return parseScript(token);
292 } 330 }
293 token = parseMetadataStar(token); 331 token = parseMetadataStar(token);
294 final String value = token.stringValue; 332 final String value = token.stringValue;
295 if ((identical(value, 'abstract') && optional('class', token.next)) || 333 if ((identical(value, 'abstract') && optional('class', token.next)) ||
296 identical(value, 'class')) { 334 identical(value, 'class')) {
297 return parseClassOrNamedMixinApplication(token); 335 return parseClassOrNamedMixinApplication(token);
298 } else if (identical(value, 'enum')) { 336 } else if (identical(value, 'enum')) {
299 return parseEnum(token); 337 return parseEnum(token);
300 } else if (identical(value, 'typedef')) { 338 } else if (identical(value, 'typedef') &&
339 (token.next.isIdentifier || optional("void", token.next))) {
301 return parseTypedef(token); 340 return parseTypedef(token);
302 } else if (identical(value, 'library')) { 341 } else if (identical(value, 'library')) {
303 return parseLibraryName(token); 342 return parseLibraryName(token);
304 } else if (identical(value, 'import')) { 343 } else if (identical(value, 'import')) {
305 return parseImport(token); 344 return parseImport(token);
306 } else if (identical(value, 'export')) { 345 } else if (identical(value, 'export')) {
307 return parseExport(token); 346 return parseExport(token);
308 } else if (identical(value, 'part')) { 347 } else if (identical(value, 'part')) {
309 return parsePartOrPartOf(token); 348 return parsePartOrPartOf(token);
310 } else { 349 } else {
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 if (optional('=', peekAfterNominalType(token.next))) { 593 if (optional('=', peekAfterNominalType(token.next))) {
555 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration); 594 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration);
556 token = parseTypeVariablesOpt(token); 595 token = parseTypeVariablesOpt(token);
557 equals = token; 596 equals = token;
558 token = expect('=', token); 597 token = expect('=', token);
559 token = parseType(token); 598 token = parseType(token);
560 } else { 599 } else {
561 token = parseReturnTypeOpt(token.next); 600 token = parseReturnTypeOpt(token.next);
562 token = parseIdentifier(token, IdentifierContext.typedefDeclaration); 601 token = parseIdentifier(token, IdentifierContext.typedefDeclaration);
563 token = parseTypeVariablesOpt(token); 602 token = parseTypeVariablesOpt(token);
564 token = parseFormalParameters(token); 603 token = parseFormalParameters(token, MemberKind.FunctionTypeAlias);
565 } 604 }
566 listener.endFunctionTypeAlias(typedefKeyword, equals, token); 605 listener.endFunctionTypeAlias(typedefKeyword, equals, token);
567 return expect(';', token); 606 return expect(';', token);
568 } 607 }
569 608
570 Token parseMixinApplication(Token token) { 609 Token parseMixinApplication(Token token) {
571 listener.beginMixinApplication(token); 610 listener.beginMixinApplication(token);
572 token = parseType(token); 611 token = parseType(token);
573 Token withKeyword = token; 612 Token withKeyword = token;
574 token = expect('with', token); 613 token = expect('with', token);
575 token = parseTypeList(token); 614 token = parseTypeList(token);
576 listener.endMixinApplication(withKeyword); 615 listener.endMixinApplication(withKeyword);
577 return token; 616 return token;
578 } 617 }
579 618
580 Token parseReturnTypeOpt(Token token) { 619 Token parseReturnTypeOpt(Token token) {
581 if (identical(token.stringValue, 'void')) { 620 if (identical(token.stringValue, 'void')) {
582 if (isGeneralizedFunctionType(token.next)) { 621 if (isGeneralizedFunctionType(token.next)) {
583 return parseType(token); 622 return parseType(token);
584 } else { 623 } else {
585 listener.handleVoidKeyword(token); 624 listener.handleVoidKeyword(token);
586 return token.next; 625 return token.next;
587 } 626 }
588 } else { 627 } else {
589 return parseTypeOpt(token); 628 return parseTypeOpt(token);
590 } 629 }
591 } 630 }
592 631
593 Token parseFormalParametersOpt(Token token) { 632 Token parseFormalParametersOpt(Token token, MemberKind kind) {
594 if (optional('(', token)) { 633 if (optional('(', token)) {
595 return parseFormalParameters(token); 634 return parseFormalParameters(token, kind);
596 } else { 635 } else {
597 listener.handleNoFormalParameters(token); 636 listener.handleNoFormalParameters(token, kind);
598 return token; 637 return token;
599 } 638 }
600 } 639 }
601 640
602 Token skipFormalParameters(Token token) { 641 Token skipFormalParameters(Token token, MemberKind kind) {
603 // TODO(ahe): Shouldn't this be `beginFormalParameters`? 642 // TODO(ahe): Shouldn't this be `beginFormalParameters`?
604 listener.beginOptionalFormalParameters(token); 643 listener.beginOptionalFormalParameters(token);
605 if (!optional('(', token)) { 644 if (!optional('(', token)) {
606 if (optional(';', token)) { 645 if (optional(';', token)) {
607 reportRecoverableErrorCode(token, codeExpectedOpenParens); 646 reportRecoverableErrorCode(token, codeExpectedOpenParens);
608 return token; 647 return token;
609 } 648 }
610 return reportUnrecoverableErrorCodeWithString( 649 return reportUnrecoverableErrorCodeWithString(
611 token, codeExpectedButGot, "(") 650 token, codeExpectedButGot, "(")
612 .next; 651 .next;
613 } 652 }
614 BeginGroupToken beginGroupToken = token; 653 BeginGroupToken beginGroupToken = token;
615 Token endToken = beginGroupToken.endGroup; 654 Token endToken = beginGroupToken.endGroup;
616 listener.endFormalParameters(0, token, endToken); 655 listener.endFormalParameters(0, token, endToken, kind);
617 return endToken.next; 656 return endToken.next;
618 } 657 }
619 658
620 /// Parses the formal parameter list of a function. 659 /// Parses the formal parameter list of a function.
621 /// 660 ///
622 /// If [inFunctionType] is true, then the names may be omitted (except for 661 /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be
623 /// named arguments). If it is false, then the types may be omitted. 662 /// omitted (except for named arguments). Otherwise, types may be omitted.
624 Token parseFormalParameters(Token token, {bool inFunctionType: false}) { 663 Token parseFormalParameters(Token token, MemberKind kind) {
625 Token begin = token; 664 Token begin = token;
626 listener.beginFormalParameters(begin); 665 listener.beginFormalParameters(begin, kind);
627 expect('(', token); 666 expect('(', token);
628 int parameterCount = 0; 667 int parameterCount = 0;
629 do { 668 do {
630 token = token.next; 669 token = token.next;
631 if (optional(')', token)) { 670 if (optional(')', token)) {
632 break; 671 break;
633 } 672 }
634 ++parameterCount; 673 ++parameterCount;
635 String value = token.stringValue; 674 String value = token.stringValue;
636 if (identical(value, '[')) { 675 if (identical(value, '[')) {
637 token = parseOptionalFormalParameters(token, false, 676 token = parseOptionalFormalParameters(token, false, kind);
638 inFunctionType: inFunctionType);
639 break; 677 break;
640 } else if (identical(value, '{')) { 678 } else if (identical(value, '{')) {
641 token = parseOptionalFormalParameters(token, true, 679 token = parseOptionalFormalParameters(token, true, kind);
642 inFunctionType: inFunctionType);
643 break; 680 break;
644 } else if (identical(value, '[]')) { 681 } else if (identical(value, '[]')) {
645 --parameterCount; 682 --parameterCount;
646 reportRecoverableErrorCode(token, codeEmptyOptionalParameterList); 683 reportRecoverableErrorCode(token, codeEmptyOptionalParameterList);
647 token = token.next; 684 token = token.next;
648 break; 685 break;
649 } 686 }
650 token = parseFormalParameter(token, FormalParameterType.REQUIRED, 687 token = parseFormalParameter(token, FormalParameterType.REQUIRED, kind);
651 inFunctionType: inFunctionType);
652 } while (optional(',', token)); 688 } while (optional(',', token));
653 listener.endFormalParameters(parameterCount, begin, token); 689 listener.endFormalParameters(parameterCount, begin, token, kind);
654 return expect(')', token); 690 return expect(')', token);
655 } 691 }
656 692
657 Token parseFormalParameter(Token token, FormalParameterType kind, 693 Token parseFormalParameter(
658 {bool inFunctionType: false}) { 694 Token token, FormalParameterType parameterKind, MemberKind memberKind) {
659 token = parseMetadataStar(token, forParameter: true); 695 token = parseMetadataStar(token, forParameter: true);
660 listener.beginFormalParameter(token); 696 listener.beginFormalParameter(token, memberKind);
661 697
662 // Skip over `covariant` token, if the next token is an identifier or 698 bool inFunctionType = memberKind == MemberKind.GeneralizedFunctionType;
663 // modifier. 699 token = parseModifiers(token, memberKind, parameterKind: parameterKind);
664 // This enables the case where `covariant` is the name of the parameter: 700 bool isNamedParameter = parameterKind == FormalParameterType.NAMED;
665 // void foo(covariant);
666 Token covariantKeyword;
667 if (identical(token.stringValue, 'covariant') &&
668 (token.next.isIdentifier || isModifier(token.next))) {
669 covariantKeyword = token;
670 token = token.next;
671 }
672 token = parseModifiers(token);
673 bool isNamedParameter = kind == FormalParameterType.NAMED;
674 701
675 Token thisKeyword = null; 702 Token thisKeyword = null;
676 Token nameToken; 703 Token nameToken;
677 if (inFunctionType && isNamedParameter) { 704 if (inFunctionType) {
678 token = parseType(token); 705 if (isNamedParameter || token.isIdentifier) {
679 token =
680 parseIdentifier(token, IdentifierContext.formalParameterDeclaration);
681 } else if (inFunctionType) {
682 token = parseType(token);
683 if (token.isIdentifier) {
684 token = parseIdentifier( 706 token = parseIdentifier(
685 token, IdentifierContext.formalParameterDeclaration); 707 token, IdentifierContext.formalParameterDeclaration);
686 } else { 708 } else {
687 listener.handleNoName(token); 709 listener.handleNoName(token);
688 } 710 }
689 } else { 711 } else {
690 token = parseReturnTypeOpt(token);
691 if (optional('this', token)) { 712 if (optional('this', token)) {
692 thisKeyword = token; 713 thisKeyword = token;
693 token = expect('.', token.next); 714 token = expect('.', token.next);
694 nameToken = token; 715 nameToken = token;
695 token = parseIdentifier(token, IdentifierContext.fieldInitializer); 716 token = parseIdentifier(token, IdentifierContext.fieldInitializer);
696 } else { 717 } else {
697 nameToken = token; 718 nameToken = token;
698 token = parseIdentifier( 719 token = parseIdentifier(
699 token, IdentifierContext.formalParameterDeclaration); 720 token, IdentifierContext.formalParameterDeclaration);
700 } 721 }
701 } 722 }
702 723
703 token = listener.injectGenericCommentTypeList(token); 724 token = listener.injectGenericCommentTypeList(token);
704 if (optional('(', token)) { 725 if (optional('(', token)) {
705 Token inlineFunctionTypeStart = token; 726 Token inlineFunctionTypeStart = token;
706 listener.beginFunctionTypedFormalParameter(token); 727 listener.beginFunctionTypedFormalParameter(token);
707 listener.handleNoTypeVariables(token); 728 listener.handleNoTypeVariables(token);
708 token = parseFormalParameters(token); 729 token = parseFormalParameters(token, MemberKind.FunctionTypedParameter);
709 listener.endFunctionTypedFormalParameter( 730 listener.endFunctionTypedFormalParameter(thisKeyword, parameterKind);
710 covariantKeyword, thisKeyword, kind);
711 // Generalized function types don't allow inline function types. 731 // Generalized function types don't allow inline function types.
712 // The following isn't allowed: 732 // The following isn't allowed:
713 // int Function(int bar(String x)). 733 // int Function(int bar(String x)).
714 if (inFunctionType) { 734 if (memberKind == MemberKind.GeneralizedFunctionType) {
715 reportRecoverableErrorCode( 735 reportRecoverableErrorCode(
716 inlineFunctionTypeStart, codeInvalidInlineFunctionType); 736 inlineFunctionTypeStart, codeInvalidInlineFunctionType);
717 } 737 }
718 } else if (optional('<', token)) { 738 } else if (optional('<', token)) {
719 Token inlineFunctionTypeStart = token; 739 Token inlineFunctionTypeStart = token;
720 listener.beginFunctionTypedFormalParameter(token); 740 listener.beginFunctionTypedFormalParameter(token);
721 token = parseTypeVariablesOpt(token); 741 token = parseTypeVariablesOpt(token);
722 token = parseFormalParameters(token); 742 token = parseFormalParameters(token, MemberKind.FunctionTypedParameter);
723 listener.endFunctionTypedFormalParameter( 743 listener.endFunctionTypedFormalParameter(thisKeyword, parameterKind);
724 covariantKeyword, thisKeyword, kind);
725 // Generalized function types don't allow inline function types. 744 // Generalized function types don't allow inline function types.
726 // The following isn't allowed: 745 // The following isn't allowed:
727 // int Function(int bar(String x)). 746 // int Function(int bar(String x)).
728 if (inFunctionType) { 747 if (memberKind == MemberKind.GeneralizedFunctionType) {
729 reportRecoverableErrorCode( 748 reportRecoverableErrorCode(
730 inlineFunctionTypeStart, codeInvalidInlineFunctionType); 749 inlineFunctionTypeStart, codeInvalidInlineFunctionType);
731 } 750 }
732 } 751 }
733 String value = token.stringValue; 752 String value = token.stringValue;
734 if ((identical('=', value)) || (identical(':', value))) { 753 if ((identical('=', value)) || (identical(':', value))) {
735 // TODO(ahe): Validate that these are only used for optional parameters. 754 // TODO(ahe): Validate that these are only used for optional parameters.
736 Token equal = token; 755 Token equal = token;
737 token = parseExpression(token.next); 756 token = parseExpression(token.next);
738 listener.handleValuedFormalParameter(equal, token); 757 listener.handleValuedFormalParameter(equal, token);
739 if (kind.isRequired) { 758 if (parameterKind.isRequired) {
740 reportRecoverableErrorCode(equal, codeRequiredParameterWithDefault); 759 reportRecoverableErrorCode(equal, codeRequiredParameterWithDefault);
741 } else if (kind.isPositional && identical(':', value)) { 760 } else if (parameterKind.isPositional && identical(':', value)) {
742 reportRecoverableErrorCode(equal, codePositionalParameterWithEquals); 761 reportRecoverableErrorCode(equal, codePositionalParameterWithEquals);
743 } 762 }
744 } else { 763 } else {
745 listener.handleFormalParameterWithoutValue(token); 764 listener.handleFormalParameterWithoutValue(token);
746 } 765 }
747 listener.endFormalParameter(covariantKeyword, thisKeyword, nameToken, kind); 766 listener.endFormalParameter(
767 thisKeyword, nameToken, parameterKind, memberKind);
748 return token; 768 return token;
749 } 769 }
750 770
751 Token parseOptionalFormalParameters(Token token, bool isNamed, 771 Token parseOptionalFormalParameters(
752 {bool inFunctionType: false}) { 772 Token token, bool isNamed, MemberKind kind) {
753 Token begin = token; 773 Token begin = token;
754 listener.beginOptionalFormalParameters(begin); 774 listener.beginOptionalFormalParameters(begin);
755 assert((isNamed && optional('{', token)) || optional('[', token)); 775 assert((isNamed && optional('{', token)) || optional('[', token));
756 int parameterCount = 0; 776 int parameterCount = 0;
757 do { 777 do {
758 token = token.next; 778 token = token.next;
759 if (isNamed && optional('}', token)) { 779 if (isNamed && optional('}', token)) {
760 break; 780 break;
761 } else if (!isNamed && optional(']', token)) { 781 } else if (!isNamed && optional(']', token)) {
762 break; 782 break;
763 } 783 }
764 var type = 784 var type =
765 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 785 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
766 token = parseFormalParameter(token, type, inFunctionType: inFunctionType); 786 token = parseFormalParameter(token, type, kind);
767 ++parameterCount; 787 ++parameterCount;
768 } while (optional(',', token)); 788 } while (optional(',', token));
769 if (parameterCount == 0) { 789 if (parameterCount == 0) {
770 reportRecoverableErrorCode( 790 reportRecoverableErrorCode(
771 token, 791 token,
772 isNamed 792 isNamed
773 ? codeEmptyNamedParameterList 793 ? codeEmptyNamedParameterList
774 : codeEmptyOptionalParameterList); 794 : codeEmptyOptionalParameterList);
775 } 795 }
776 listener.endOptionalFormalParameters(parameterCount, begin, token); 796 listener.endOptionalFormalParameters(parameterCount, begin, token);
(...skipping 12 matching lines...) Expand all
789 token = listener.injectGenericCommentTypeAssign(token); 809 token = listener.injectGenericCommentTypeAssign(token);
790 Token peek = peekAfterIfType(token); 810 Token peek = peekAfterIfType(token);
791 if (peek != null && (peek.isIdentifier || optional('this', peek))) { 811 if (peek != null && (peek.isIdentifier || optional('this', peek))) {
792 return parseType(token); 812 return parseType(token);
793 } 813 }
794 listener.handleNoType(token); 814 listener.handleNoType(token);
795 return token; 815 return token;
796 } 816 }
797 817
798 bool isValidTypeReference(Token token) { 818 bool isValidTypeReference(Token token) {
799 final kind = token.kind; 819 int kind = token.kind;
800 if (identical(kind, IDENTIFIER_TOKEN)) return true; 820 if (IDENTIFIER_TOKEN == kind) return true;
801 if (identical(kind, KEYWORD_TOKEN)) { 821 if (KEYWORD_TOKEN == kind) {
802 String value = token.type.lexeme; 822 String value = token.type.lexeme;
803 return token.type.isPseudo || 823 return token.type.isPseudo ||
804 (identical(value, 'dynamic')) || 824 (identical(value, 'dynamic')) ||
805 (identical(value, 'void')); 825 (identical(value, 'void'));
806 } 826 }
807 return false; 827 return false;
808 } 828 }
809 829
810 /// Returns true if [token] matches '<' type (',' type)* '>' '(', and 830 /// Returns true if [token] matches '<' type (',' type)* '>' '(', and
811 /// otherwise returns false. The final '(' is not part of the grammar 831 /// otherwise returns false. The final '(' is not part of the grammar
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 if (token.kind != STRING_TOKEN) { 1046 if (token.kind != STRING_TOKEN) {
1027 token = 1047 token =
1028 reportUnrecoverableErrorCodeWithToken(token, codeExpectedString).next; 1048 reportUnrecoverableErrorCodeWithToken(token, codeExpectedString).next;
1029 } 1049 }
1030 listener.handleStringPart(token); 1050 listener.handleStringPart(token);
1031 return token.next; 1051 return token.next;
1032 } 1052 }
1033 1053
1034 Token parseIdentifier(Token token, IdentifierContext context) { 1054 Token parseIdentifier(Token token, IdentifierContext context) {
1035 if (!token.isIdentifier) { 1055 if (!token.isIdentifier) {
1036 token = 1056 if (optional("void", token)) {
1037 reportUnrecoverableErrorCodeWithToken(token, codeExpectedIdentifier) 1057 reportRecoverableErrorCode(token, codeInvalidVoid);
1038 .next; 1058 } else {
1059 token =
1060 reportUnrecoverableErrorCodeWithToken(token, codeExpectedIdentifier)
1061 .next;
1062 }
1039 } else if (token.type.isBuiltIn && !context.isBuiltInIdentifierAllowed) { 1063 } else if (token.type.isBuiltIn && !context.isBuiltInIdentifierAllowed) {
1040 if (context.inDeclaration) { 1064 if (context.inDeclaration) {
1041 reportRecoverableErrorCodeWithToken( 1065 reportRecoverableErrorCodeWithToken(
1042 token, codeBuiltInIdentifierInDeclaration); 1066 token, codeBuiltInIdentifierInDeclaration);
1043 } else if (!optional("dynamic", token)) { 1067 } else if (!optional("dynamic", token)) {
1044 reportRecoverableErrorCodeWithToken(token, codeBuiltInIdentifierAsType); 1068 reportRecoverableErrorCodeWithToken(token, codeBuiltInIdentifierAsType);
1045 } 1069 }
1046 } else if (!inPlainSync && token.type.isPseudo) { 1070 } else if (!inPlainSync && token.type.isPseudo) {
1047 if (optional('await', token)) { 1071 if (optional('await', token)) {
1048 reportRecoverableErrorCode(token, codeAwaitAsIdentifier); 1072 reportRecoverableErrorCode(token, codeAwaitAsIdentifier);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 (optional('<', token.next) || optional('(', token.next)); 1134 (optional('<', token.next) || optional('(', token.next));
1111 } 1135 }
1112 1136
1113 Token parseType(Token token) { 1137 Token parseType(Token token) {
1114 Token begin = token; 1138 Token begin = token;
1115 if (isGeneralizedFunctionType(token)) { 1139 if (isGeneralizedFunctionType(token)) {
1116 // A function type without return type. 1140 // A function type without return type.
1117 // Push the non-existing return type first. The loop below will 1141 // Push the non-existing return type first. The loop below will
1118 // generate the full type. 1142 // generate the full type.
1119 listener.handleNoType(token); 1143 listener.handleNoType(token);
1120 } else if (identical(token.stringValue, 'void') && 1144 } else if (optional("void", token) &&
1121 isGeneralizedFunctionType(token.next)) { 1145 isGeneralizedFunctionType(token.next)) {
1122 listener.handleVoidKeyword(token); 1146 listener.handleVoidKeyword(token);
1123 token = token.next; 1147 token = token.next;
1124 } else { 1148 } else {
1125 if (isValidTypeReference(token)) { 1149 IdentifierContext context = IdentifierContext.typeReference;
1126 token = parseIdentifier(token, IdentifierContext.typeReference); 1150 if (token.isIdentifier && optional(".", token.next)) {
1127 token = parseQualifiedRestOpt( 1151 context = IdentifierContext.prefixedTypeReference;
1128 token, IdentifierContext.typeReferenceContinuation);
1129 } else {
1130 token =
1131 reportUnrecoverableErrorCodeWithToken(token, codeExpectedType).next;
1132 listener.handleInvalidTypeReference(token);
1133 } 1152 }
1153 token = parseIdentifier(token, context);
1154 token = parseQualifiedRestOpt(
1155 token, IdentifierContext.typeReferenceContinuation);
1134 token = parseTypeArgumentsOpt(token); 1156 token = parseTypeArgumentsOpt(token);
1135 listener.handleType(begin, token); 1157 listener.handleType(begin, token);
1136 } 1158 }
1137 1159
1138 { 1160 {
1139 Token newBegin = 1161 Token newBegin =
1140 listener.replaceTokenWithGenericCommentTypeAssign(begin, token); 1162 listener.replaceTokenWithGenericCommentTypeAssign(begin, token);
1141 if (!identical(newBegin, begin)) { 1163 if (!identical(newBegin, begin)) {
1142 listener.discardTypeReplacedWithCommentTypeAssign(); 1164 listener.discardTypeReplacedWithCommentTypeAssign();
1143 return parseType(newBegin); 1165 return parseType(newBegin);
1144 } 1166 }
1145 } 1167 }
1146 1168
1147 // While we see a `Function(` treat the pushed type as return type. 1169 // While we see a `Function(` treat the pushed type as return type.
1148 // For example: `int Function() Function(int) Function(String x)`. 1170 // For example: `int Function() Function(int) Function(String x)`.
1149 while (isGeneralizedFunctionType(token)) { 1171 while (isGeneralizedFunctionType(token)) {
1150 token = parseFunctionType(token); 1172 token = parseFunctionType(token);
1151 } 1173 }
1152 return token; 1174 return token;
1153 } 1175 }
1154 1176
1155 /// Parses a generalized function type. 1177 /// Parses a generalized function type.
1156 /// 1178 ///
1157 /// The return type must already be pushed. 1179 /// The return type must already be pushed.
1158 Token parseFunctionType(Token token) { 1180 Token parseFunctionType(Token token) {
1159 assert(optional('Function', token)); 1181 assert(optional('Function', token));
1160 Token functionToken = token; 1182 Token functionToken = token;
1161 token = token.next; 1183 token = token.next;
1162 token = parseTypeVariablesOpt(token); 1184 token = parseTypeVariablesOpt(token);
1163 token = parseFormalParameters(token, inFunctionType: true); 1185 token = parseFormalParameters(token, MemberKind.GeneralizedFunctionType);
1164 listener.handleFunctionType(functionToken, token); 1186 listener.handleFunctionType(functionToken, token);
1165 return token; 1187 return token;
1166 } 1188 }
1167 1189
1168 Token parseTypeArgumentsOpt(Token token) { 1190 Token parseTypeArgumentsOpt(Token token) {
1169 return parseStuff( 1191 return parseStuff(
1170 token, 1192 token,
1171 (t) => listener.beginTypeArguments(t), 1193 (t) => listener.beginTypeArguments(t),
1172 (t) => parseType(t), 1194 (t) => parseType(t),
1173 (c, bt, et) => listener.endTypeArguments(c, bt, et), 1195 (c, bt, et) => listener.endTypeArguments(c, bt, et),
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 token = reportUnexpectedToken(token).next; 1294 token = reportUnexpectedToken(token).next;
1273 if (identical(token.kind, EOF_TOKEN)) return token; 1295 if (identical(token.kind, EOF_TOKEN)) return token;
1274 } 1296 }
1275 } 1297 }
1276 var modifiers = identifiers.reverse(); 1298 var modifiers = identifiers.reverse();
1277 return isField 1299 return isField
1278 ? parseFields(start, modifiers, type, getOrSet, name, true) 1300 ? parseFields(start, modifiers, type, getOrSet, name, true)
1279 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); 1301 : parseTopLevelMethod(start, modifiers, type, getOrSet, name);
1280 } 1302 }
1281 1303
1282 bool isVarFinalOrConst(Token token) {
1283 String value = token.stringValue;
1284 return identical('var', value) ||
1285 identical('final', value) ||
1286 identical('const', value);
1287 }
1288
1289 Token expectVarFinalOrConst(
1290 Link<Token> modifiers, bool hasType, bool allowStatic) {
1291 int modifierCount = 0;
1292 Token staticModifier;
1293 if (allowStatic &&
1294 !modifiers.isEmpty &&
1295 optional('static', modifiers.head)) {
1296 staticModifier = modifiers.head;
1297 modifierCount++;
1298 parseModifier(staticModifier);
1299 modifiers = modifiers.tail;
1300 }
1301 if (modifiers.isEmpty) {
1302 listener.handleModifiers(modifierCount);
1303 return null;
1304 }
1305 if (modifiers.tail.isEmpty) {
1306 Token modifier = modifiers.head;
1307 if (isVarFinalOrConst(modifier)) {
1308 modifierCount++;
1309 parseModifier(modifier);
1310 listener.handleModifiers(modifierCount);
1311 // TODO(ahe): The caller checks for "var Type name", perhaps we should
1312 // check here instead.
1313 return modifier;
1314 }
1315 }
1316
1317 // Slow case to report errors.
1318 List<Token> modifierList = modifiers.toList();
1319 Token varFinalOrConst =
1320 modifierList.firstWhere(isVarFinalOrConst, orElse: () => null);
1321 if (allowStatic && staticModifier == null) {
1322 staticModifier = modifierList.firstWhere(
1323 (modifier) => optional('static', modifier),
1324 orElse: () => null);
1325 if (staticModifier != null) {
1326 modifierCount++;
1327 parseModifier(staticModifier);
1328 modifierList.remove(staticModifier);
1329 }
1330 }
1331 bool hasTypeOrModifier = hasType;
1332 if (varFinalOrConst != null) {
1333 parseModifier(varFinalOrConst);
1334 modifierCount++;
1335 hasTypeOrModifier = true;
1336 modifierList.remove(varFinalOrConst);
1337 }
1338 listener.handleModifiers(modifierCount);
1339 for (Token modifier in modifierList) {
1340 reportRecoverableErrorCodeWithToken(
1341 modifier,
1342 hasTypeOrModifier
1343 ? codeExtraneousModifier
1344 : codeExtraneousModifierReplace);
1345 }
1346 return null;
1347 }
1348
1349 /// Removes the optional `covariant` token from the modifiers, if there
1350 /// is no `static` in the list, and `covariant` is the first modifier.
1351 Link<Token> removeOptCovariantTokenIfNotStatic(Link<Token> modifiers) {
1352 if (modifiers.isEmpty ||
1353 !identical(modifiers.first.stringValue, 'covariant')) {
1354 return modifiers;
1355 }
1356 for (Token modifier in modifiers.tail) {
1357 if (identical(modifier.stringValue, 'static')) {
1358 return modifiers;
1359 }
1360 }
1361 return modifiers.tail;
1362 }
1363
1364 Token parseFields(Token start, Link<Token> modifiers, Token type, 1304 Token parseFields(Token start, Link<Token> modifiers, Token type,
1365 Token getOrSet, Token name, bool isTopLevel) { 1305 Token getOrSet, Token name, bool isTopLevel) {
1366 bool hasType = type != null; 1306 Token token = parseModifiers(start,
1307 isTopLevel ? MemberKind.TopLevelField : MemberKind.NonStaticField,
1308 isVariable: true);
1367 1309
1368 Token covariantKeyword; 1310 if (token != name) {
1369 if (getOrSet == null && !isTopLevel) { 1311 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
1370 // TODO(ahe): replace the method removeOptCovariantTokenIfNotStatic with 1312 token = name;
1371 // a better mechanism.
1372 Link<Token> newModifiers = removeOptCovariantTokenIfNotStatic(modifiers);
1373 if (!identical(newModifiers, modifiers)) {
1374 covariantKeyword = modifiers.first;
1375 modifiers = newModifiers;
1376 }
1377 }
1378
1379 Token varFinalOrConst =
1380 expectVarFinalOrConst(modifiers, hasType, !isTopLevel);
1381 bool isVar = false;
1382 bool hasModifier = false;
1383 if (varFinalOrConst != null) {
1384 hasModifier = true;
1385 isVar = optional('var', varFinalOrConst);
1386 }
1387
1388 if (getOrSet != null) {
1389 reportRecoverableErrorCodeWithToken(
1390 getOrSet,
1391 hasModifier || hasType
1392 ? codeExtraneousModifier
1393 : codeExtraneousModifierReplace);
1394 }
1395
1396 if (!hasType) {
1397 listener.handleNoType(name);
1398 } else if (optional('void', type) &&
1399 !isGeneralizedFunctionType(type.next)) {
1400 listener.handleNoType(name);
1401 // TODO(ahe): This error is reported twice, second time is from
1402 // [parseVariablesDeclarationMaybeSemicolon] via
1403 // [PartialFieldListElement.parseNode].
1404 reportRecoverableErrorCode(type, codeInvalidVoid);
1405 } else {
1406 parseType(type);
1407 if (isVar) {
1408 reportRecoverableErrorCodeWithToken(
1409 modifiers.head, codeExtraneousModifier);
1410 }
1411 } 1313 }
1412 1314
1413 IdentifierContext context = isTopLevel 1315 IdentifierContext context = isTopLevel
1414 ? IdentifierContext.topLevelVariableDeclaration 1316 ? IdentifierContext.topLevelVariableDeclaration
1415 : IdentifierContext.fieldDeclaration; 1317 : IdentifierContext.fieldDeclaration;
1416 Token token = parseIdentifier(name, context); 1318 token = parseIdentifier(token, context);
1417 1319
1418 int fieldCount = 1; 1320 int fieldCount = 1;
1419 token = parseFieldInitializerOpt(token); 1321 token = parseFieldInitializerOpt(token);
1420 while (optional(',', token)) { 1322 while (optional(',', token)) {
1421 token = parseIdentifier(token.next, context); 1323 token = parseIdentifier(token.next, context);
1422 token = parseFieldInitializerOpt(token); 1324 token = parseFieldInitializerOpt(token);
1423 ++fieldCount; 1325 ++fieldCount;
1424 } 1326 }
1425 Token semicolon = token; 1327 Token semicolon = token;
1426 token = expectSemicolon(token); 1328 token = expectSemicolon(token);
1427 if (isTopLevel) { 1329 if (isTopLevel) {
1428 listener.endTopLevelFields(fieldCount, start, semicolon); 1330 listener.endTopLevelFields(fieldCount, start, semicolon);
1429 } else { 1331 } else {
1430 listener.endFields(fieldCount, covariantKeyword, start, semicolon); 1332 listener.endFields(fieldCount, start, semicolon);
1431 } 1333 }
1432 return token; 1334 return token;
1433 } 1335 }
1434 1336
1435 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, 1337 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type,
1436 Token getOrSet, Token name) { 1338 Token getOrSet, Token name) {
1437 listener.beginTopLevelMethod(start, name); 1339 listener.beginTopLevelMethod(start, name);
1438 Token externalModifier; 1340 Token externalModifier;
1439 // TODO(johnniwinther): Move error reporting to resolution to give more 1341 // TODO(johnniwinther): Move error reporting to resolution to give more
1440 // specific error messages. 1342 // specific error messages.
(...skipping 17 matching lines...) Expand all
1458 parseReturnTypeOpt(type); 1360 parseReturnTypeOpt(type);
1459 } 1361 }
1460 Token token = 1362 Token token =
1461 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration); 1363 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration);
1462 1364
1463 if (getOrSet == null) { 1365 if (getOrSet == null) {
1464 token = parseTypeVariablesOpt(token); 1366 token = parseTypeVariablesOpt(token);
1465 } else { 1367 } else {
1466 listener.handleNoTypeVariables(token); 1368 listener.handleNoTypeVariables(token);
1467 } 1369 }
1468 token = parseFormalParametersOpt(token); 1370 token = parseFormalParametersOpt(token, MemberKind.TopLevelMethod);
1469 AsyncModifier savedAsyncModifier = asyncState; 1371 AsyncModifier savedAsyncModifier = asyncState;
1470 Token asyncToken = token; 1372 Token asyncToken = token;
1471 token = parseAsyncModifier(token); 1373 token = parseAsyncModifier(token);
1472 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { 1374 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
1473 reportRecoverableErrorCode(asyncToken, codeSetterNotSync); 1375 reportRecoverableErrorCode(asyncToken, codeSetterNotSync);
1474 } 1376 }
1475 token = parseFunctionBody(token, false, externalModifier != null); 1377 token = parseFunctionBody(token, false, externalModifier != null);
1476 asyncState = savedAsyncModifier; 1378 asyncState = savedAsyncModifier;
1477 Token endToken = token; 1379 Token endToken = token;
1478 token = token.next; 1380 token = token.next;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1676 } else { 1578 } else {
1677 reportRecoverableErrorCodeWithToken(token, codeExpectedString); 1579 reportRecoverableErrorCodeWithToken(token, codeExpectedString);
1678 return parseRecoverExpression(token); 1580 return parseRecoverExpression(token);
1679 } 1581 }
1680 } 1582 }
1681 1583
1682 Token expectSemicolon(Token token) { 1584 Token expectSemicolon(Token token) {
1683 return expect(';', token); 1585 return expect(';', token);
1684 } 1586 }
1685 1587
1686 bool isModifier(Token token) { 1588 bool isModifier(Token token) => modifierOrder(token) < 127;
1589
1590 /// Provides a partial order on modifiers.
1591 ///
1592 /// The order is based on the order modifiers must appear in according to the
1593 /// grammar. For example, `external` must come before `static`.
1594 ///
1595 /// In addition, if two modifiers have the same order, they can't both be
1596 /// used together, for example, `final` and `var` can't be used together.
1597 ///
1598 /// If [token] isn't a modifier, 127 is returned.
1599 int modifierOrder(Token token) {
1687 final String value = token.stringValue; 1600 final String value = token.stringValue;
1688 return (identical('final', value)) || 1601 if (identical('external', value)) return 0;
1689 (identical('var', value)) || 1602 if (identical('static', value) || identical('covariant', value)) {
1690 (identical('const', value)) || 1603 return 1;
1691 (identical('abstract', value)) || 1604 }
1692 (identical('static', value)) || 1605 if (identical('final', value) ||
1693 (identical('external', value)); 1606 identical('var', value) ||
1607 identical('const', value)) {
1608 return 2;
1609 }
1610 if (identical('abstract', value)) return 3;
1611 return 127;
1694 } 1612 }
1695 1613
1696 Token parseModifier(Token token) { 1614 Token parseModifier(Token token) {
1697 assert(isModifier(token)); 1615 assert(isModifier(token));
1698 listener.handleModifier(token); 1616 listener.handleModifier(token);
1699 return token.next; 1617 return token.next;
1700 } 1618 }
1701 1619
1702 void parseModifierList(Link<Token> tokens) { 1620 /// This method is used in most locations where modifiers can occur. However,
1621 /// it isn't used when parsing a class or when parsing the modifiers of a
1622 /// member function (non-local), but is used when parsing their formal
1623 /// parameters.
1624 ///
1625 /// When parsing the formal parameters of any function, [parameterKind] is
1626 /// non-null.
1627 Token parseModifiers(Token token, MemberKind memberKind,
1628 {FormalParameterType parameterKind, bool isVariable: false}) {
1629 bool returnTypeAllowed =
1630 !isVariable && memberKind != MemberKind.GeneralizedFunctionType;
1631 bool typeRequired =
1632 isVariable || memberKind == MemberKind.GeneralizedFunctionType;
1703 int count = 0; 1633 int count = 0;
1704 for (; !tokens.isEmpty; tokens = tokens.tail) { 1634
1705 Token token = tokens.head; 1635 int currentOrder = -1;
1706 if (isModifier(token)) { 1636 bool hasVar = false;
1707 parseModifier(token); 1637 while (token.kind == KEYWORD_TOKEN) {
1708 } else { 1638 if (token.type.isPseudo) {
1709 reportUnexpectedToken(token); 1639 // A pseudo keyword is never a modifier.
1710 // Skip the remaining modifiers.
1711 break; 1640 break;
1712 } 1641 }
1713 count++; 1642 if (token.type.isBuiltIn) {
1643 // A built-in identifier can only be a modifier as long as it is
1644 // followed by another modifier or an identifier. Otherwise, it is the
1645 // identifier.
1646 if (token.next.kind != KEYWORD_TOKEN && !token.next.isIdentifier) {
1647 break;
1648 }
1649 }
1650 int order = modifierOrder(token);
1651 if (order < 3) {
1652 // `abstract` isn't parsed with this method.
1653 if (order > currentOrder) {
1654 currentOrder = order;
1655 if (optional("var", token)) {
1656 if (!isVariable && parameterKind == null) {
1657 reportRecoverableErrorCodeWithToken(
1658 token, codeExtraneousModifier);
1659 }
1660 hasVar = true;
1661 typeRequired = false;
1662 } else if (optional("final", token)) {
1663 if (!isVariable && parameterKind == null) {
1664 reportRecoverableErrorCodeWithToken(
1665 token, codeExtraneousModifier);
1666 }
1667 typeRequired = false;
1668 } else if (optional("const", token)) {
1669 if (!isVariable) {
1670 reportRecoverableErrorCodeWithToken(
1671 token, codeExtraneousModifier);
1672 }
1673 typeRequired = false;
1674 } else if (optional("static", token)) {
1675 if (memberKind == MemberKind.NonStaticMethod) {
1676 memberKind = MemberKind.StaticMethod;
1677 } else if (memberKind == MemberKind.NonStaticField) {
1678 memberKind = MemberKind.StaticField;
1679 } else {
1680 reportRecoverableErrorCodeWithToken(
1681 token, codeExtraneousModifier);
1682 token = token.next;
1683 continue;
1684 }
1685 } else if (optional("covariant", token)) {
1686 switch (memberKind) {
1687 case MemberKind.StaticField:
1688 case MemberKind.StaticMethod:
1689 case MemberKind.TopLevelField:
1690 case MemberKind.TopLevelMethod:
1691 reportRecoverableErrorCodeWithToken(
1692 token, codeExtraneousModifier);
1693 token = token.next;
1694 continue;
1695
1696 default:
1697 break;
1698 }
1699 } else if (optional("external", token)) {
1700 switch (memberKind) {
1701 case MemberKind.Factory:
1702 case MemberKind.NonStaticMethod:
1703 case MemberKind.StaticMethod:
1704 case MemberKind.TopLevelMethod:
1705 break;
1706
1707 default:
1708 reportRecoverableErrorCodeWithToken(
1709 token, codeExtraneousModifier);
1710 token = token.next;
1711 continue;
1712 }
1713 }
1714 token = parseModifier(token);
1715 count++;
1716 } else {
1717 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
1718 token = token.next;
1719 }
1720 } else {
1721 break;
1722 }
1714 } 1723 }
1715 listener.handleModifiers(count); 1724 listener.handleModifiers(count);
1716 }
1717 1725
1718 Token parseModifiers(Token token) { 1726 Token beforeType = token;
1719 // TODO(ahe): The calling convention of this method probably needs to 1727 if (returnTypeAllowed) {
1720 // change. For example, this is parsed as a local variable declaration: 1728 token = parseReturnTypeOpt(token);
1721 // `abstract foo;`. Ideally, this example should be handled as a local 1729 } else {
1722 // variable having the type `abstract` (which should be reported as 1730 token = typeRequired ? parseType(token) : parseTypeOpt(token);
1723 // `codeBuiltInIdentifierAsType` by [parseIdentifier]).
1724 int count = 0;
1725 while (identical(token.kind, KEYWORD_TOKEN)) {
1726 if (!isModifier(token)) break;
1727 token = parseModifier(token);
1728 count++;
1729 } 1731 }
1730 listener.handleModifiers(count); 1732 if (typeRequired && beforeType == token) {
1733 reportRecoverableErrorCode(token, codeTypeRequired);
1734 }
1735 if (hasVar && beforeType != token) {
1736 reportRecoverableErrorCode(beforeType, codeTypeAfterVar);
1737 }
1731 return token; 1738 return token;
1732 } 1739 }
1733 1740
1734 /// Returns the first token after the type starting at [token]. 1741 /// Returns the first token after the type starting at [token].
1735 /// 1742 ///
1736 /// This method assumes that [token] is an identifier (or void). Use 1743 /// This method assumes that [token] is an identifier (or void). Use
1737 /// [peekAfterIfType] if [token] isn't known to be an identifier. 1744 /// [peekAfterIfType] if [token] isn't known to be an identifier.
1738 Token peekAfterType(Token token) { 1745 Token peekAfterType(Token token) {
1739 // We are looking at "identifier ...". 1746 // We are looking at "identifier ...".
1740 Token peek = token; 1747 Token peek = token;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1943 isField = true; 1950 isField = true;
1944 } 1951 }
1945 break; 1952 break;
1946 } else if ((identical(value, '=')) || (identical(value, ','))) { 1953 } else if ((identical(value, '=')) || (identical(value, ','))) {
1947 isField = true; 1954 isField = true;
1948 break; 1955 break;
1949 } else { 1956 } else {
1950 token = reportUnexpectedToken(token).next; 1957 token = reportUnexpectedToken(token).next;
1951 if (identical(token.kind, EOF_TOKEN)) { 1958 if (identical(token.kind, EOF_TOKEN)) {
1952 // TODO(ahe): This is a hack, see parseTopLevelMember. 1959 // TODO(ahe): This is a hack, see parseTopLevelMember.
1953 listener.endFields(1, null, start, token); 1960 listener.endFields(1, start, token);
1954 listener.endMember(); 1961 listener.endMember();
1955 return token; 1962 return token;
1956 } 1963 }
1957 } 1964 }
1958 } 1965 }
1959 1966
1960 var modifiers = identifiers.reverse(); 1967 var modifiers = identifiers.reverse();
1961 token = isField 1968 token = isField
1962 ? parseFields(start, modifiers, type, getOrSet, name, false) 1969 ? parseFields(start, modifiers, type, getOrSet, name, false)
1963 : parseMethod(start, modifiers, type, getOrSet, name); 1970 : parseMethod(start, modifiers, type, getOrSet, name);
1964 listener.endMember(); 1971 listener.endMember();
1965 return token; 1972 return token;
1966 } 1973 }
1967 1974
1968 Token parseMethod(Token start, Link<Token> modifiers, Token type, 1975 Token parseMethod(Token start, Link<Token> modifiers, Token type,
1969 Token getOrSet, Token name) { 1976 Token getOrSet, Token name) {
1970 listener.beginMethod(start, name); 1977 listener.beginMethod(start, name);
1978
1971 Token externalModifier; 1979 Token externalModifier;
1972 Token staticModifier; 1980 Token staticModifier;
1973 Token constModifier; 1981 // TODO(ahe): Consider using [parseModifiers] instead.
1974 int modifierCount = 0; 1982 void parseModifierList(Link<Token> tokens) {
1975 int allowedModifierCount = 1; 1983 int count = 0;
1976 // TODO(johnniwinther): Move error reporting to resolution to give more 1984 int currentOrder = -1;
1977 // specific error messages. 1985 for (; !tokens.isEmpty; tokens = tokens.tail) {
1978 for (Token modifier in modifiers) { 1986 Token token = tokens.head;
1979 if (externalModifier == null && optional('external', modifier)) { 1987 if (optional("abstract", token)) {
1980 modifierCount++; 1988 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
1981 externalModifier = modifier; 1989 continue;
1982 if (modifierCount != allowedModifierCount) {
1983 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
1984 } 1990 }
1985 allowedModifierCount++; 1991 int order = modifierOrder(token);
1986 } else if (staticModifier == null && optional('static', modifier)) { 1992 if (order < 127) {
1987 modifierCount++; 1993 if (order > currentOrder) {
1988 staticModifier = modifier; 1994 currentOrder = order;
1989 if (modifierCount != allowedModifierCount) { 1995 if (optional("var", token)) {
1990 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier); 1996 reportRecoverableErrorCodeWithToken(
1997 token, codeExtraneousModifier);
1998 } else if (optional("const", token)) {
1999 if (getOrSet != null) {
2000 reportRecoverableErrorCodeWithToken(
2001 token, codeExtraneousModifier);
2002 continue;
2003 }
2004 } else if (optional("external", token)) {
2005 externalModifier = token;
2006 } else if (optional("static", token)) {
2007 staticModifier = token;
2008 } else if (optional("covariant", token)) {
2009 if (staticModifier != null ||
2010 getOrSet == null ||
2011 optional("get", getOrSet)) {
2012 reportRecoverableErrorCodeWithToken(
2013 token, codeExtraneousModifier);
2014 continue;
2015 }
2016 }
2017 } else {
2018 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
2019 continue;
2020 }
2021 } else {
2022 reportUnexpectedToken(token);
2023 break; // Skip the remaining modifiers.
1991 } 2024 }
1992 } else if (constModifier == null && optional('const', modifier)) { 2025 parseModifier(token);
1993 modifierCount++; 2026 count++;
1994 constModifier = modifier;
1995 if (modifierCount != allowedModifierCount) {
1996 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
1997 }
1998 } else {
1999 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
2000 } 2027 }
2028 listener.handleModifiers(count);
2001 } 2029 }
2002 if (getOrSet != null && constModifier != null) { 2030
2003 reportRecoverableErrorCodeWithToken(
2004 constModifier, codeExtraneousModifier);
2005 }
2006 parseModifierList(modifiers); 2031 parseModifierList(modifiers);
2007 2032
2008 if (type == null) { 2033 if (type == null) {
2009 listener.handleNoType(name); 2034 listener.handleNoType(name);
2010 } else { 2035 } else {
2011 parseReturnTypeOpt(type); 2036 parseReturnTypeOpt(type);
2012 } 2037 }
2013 Token token; 2038 Token token;
2014 if (optional('operator', name)) { 2039 if (optional('operator', name)) {
2015 token = parseOperatorName(name); 2040 token = parseOperatorName(name);
2016 if (staticModifier != null) { 2041 if (staticModifier != null) {
2017 reportRecoverableErrorCodeWithToken( 2042 reportRecoverableErrorCodeWithToken(
2018 staticModifier, codeExtraneousModifier); 2043 staticModifier, codeExtraneousModifier);
2019 } 2044 }
2020 } else { 2045 } else {
2021 token = parseIdentifier(name, IdentifierContext.methodDeclaration); 2046 token = parseIdentifier(name, IdentifierContext.methodDeclaration);
2022 } 2047 }
2023 2048
2024 token = parseQualifiedRestOpt( 2049 token = parseQualifiedRestOpt(
2025 token, IdentifierContext.methodDeclarationContinuation); 2050 token, IdentifierContext.methodDeclarationContinuation);
2026 if (getOrSet == null) { 2051 if (getOrSet == null) {
2027 token = parseTypeVariablesOpt(token); 2052 token = parseTypeVariablesOpt(token);
2028 } else { 2053 } else {
2029 listener.handleNoTypeVariables(token); 2054 listener.handleNoTypeVariables(token);
2030 } 2055 }
2031 token = parseFormalParametersOpt(token); 2056 token = parseFormalParametersOpt(
2057 token,
2058 staticModifier != null
2059 ? MemberKind.StaticMethod
2060 : MemberKind.NonStaticMethod);
2032 token = parseInitializersOpt(token); 2061 token = parseInitializersOpt(token);
2033 AsyncModifier savedAsyncModifier = asyncState; 2062 AsyncModifier savedAsyncModifier = asyncState;
2034 Token asyncToken = token; 2063 Token asyncToken = token;
2035 token = parseAsyncModifier(token); 2064 token = parseAsyncModifier(token);
2036 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { 2065 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
2037 reportRecoverableErrorCode(asyncToken, codeSetterNotSync); 2066 reportRecoverableErrorCode(asyncToken, codeSetterNotSync);
2038 } 2067 }
2039 if (optional('=', token)) { 2068 if (optional('=', token)) {
2040 token = parseRedirectingFactoryBody(token); 2069 token = parseRedirectingFactoryBody(token);
2041 } else { 2070 } else {
(...skipping 15 matching lines...) Expand all
2057 isExternal = true; 2086 isExternal = true;
2058 } 2087 }
2059 token = parseModifier(token); 2088 token = parseModifier(token);
2060 modifierCount++; 2089 modifierCount++;
2061 } 2090 }
2062 listener.handleModifiers(modifierCount); 2091 listener.handleModifiers(modifierCount);
2063 Token factoryKeyword = token; 2092 Token factoryKeyword = token;
2064 listener.beginFactoryMethod(factoryKeyword); 2093 listener.beginFactoryMethod(factoryKeyword);
2065 token = expect('factory', token); 2094 token = expect('factory', token);
2066 token = parseConstructorReference(token); 2095 token = parseConstructorReference(token);
2067 token = parseFormalParameters(token); 2096 token = parseFormalParameters(token, MemberKind.Factory);
2068 Token asyncToken = token; 2097 Token asyncToken = token;
2069 token = parseAsyncModifier(token); 2098 token = parseAsyncModifier(token);
2070 if (!inPlainSync) { 2099 if (!inPlainSync) {
2071 reportRecoverableErrorCode(asyncToken, codeFactoryNotSync); 2100 reportRecoverableErrorCode(asyncToken, codeFactoryNotSync);
2072 } 2101 }
2073 if (optional('=', token)) { 2102 if (optional('=', token)) {
2074 token = parseRedirectingFactoryBody(token); 2103 token = parseRedirectingFactoryBody(token);
2075 } else { 2104 } else {
2076 token = parseFunctionBody(token, false, isExternal); 2105 token = parseFunctionBody(token, false, isExternal);
2077 } 2106 }
2078 listener.endFactoryMethod(start, factoryKeyword, token); 2107 listener.endFactoryMethod(start, factoryKeyword, token);
2079 return token.next; 2108 return token.next;
2080 } 2109 }
2081 2110
2082 Token parseOperatorName(Token token) { 2111 Token parseOperatorName(Token token) {
2083 assert(optional('operator', token)); 2112 assert(optional('operator', token));
2084 if (isUserDefinableOperator(token.next.stringValue)) { 2113 if (isUserDefinableOperator(token.next.stringValue)) {
2085 Token operator = token; 2114 Token operator = token;
2086 token = token.next; 2115 token = token.next;
2087 listener.handleOperatorName(operator, token); 2116 listener.handleOperatorName(operator, token);
2088 return token.next; 2117 return token.next;
2089 } else { 2118 } else {
2090 return parseIdentifier(token, IdentifierContext.operatorName); 2119 return parseIdentifier(token, IdentifierContext.operatorName);
2091 } 2120 }
2092 } 2121 }
2093 2122
2094 Token parseFunction(Token token, Token getOrSet) { 2123 Token parseFunction(Token token) {
2095 Token beginToken = token; 2124 Token beginToken = token;
2096 listener.beginFunction(token); 2125 listener.beginFunction(token);
2097 token = parseModifiers(token); 2126 token = parseModifiers(token, MemberKind.Local);
2098 if (identical(getOrSet, token)) { 2127 listener.beginFunctionName(token);
2099 // get <name> => ... 2128 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
2100 token = token.next;
2101 listener.handleNoType(token);
2102 listener.beginFunctionName(token);
2103 if (optional('operator', token)) {
2104 token = parseOperatorName(token);
2105 } else {
2106 token =
2107 parseIdentifier(token, IdentifierContext.localAccessorDeclaration);
2108 }
2109 } else if (optional('operator', token)) {
2110 // operator <op> (...
2111 listener.handleNoType(token);
2112 listener.beginFunctionName(token);
2113 token = parseOperatorName(token);
2114 } else {
2115 // <type>? <get>? <name>
2116 token = parseReturnTypeOpt(token);
2117 if (identical(getOrSet, token)) {
2118 token = token.next;
2119 }
2120 listener.beginFunctionName(token);
2121 if (optional('operator', token)) {
2122 token = parseOperatorName(token);
2123 } else {
2124 token =
2125 parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
2126 }
2127 }
2128 token = parseQualifiedRestOpt( 2129 token = parseQualifiedRestOpt(
2129 token, IdentifierContext.localFunctionDeclarationContinuation); 2130 token, IdentifierContext.localFunctionDeclarationContinuation);
2130 listener.endFunctionName(beginToken, token); 2131 listener.endFunctionName(beginToken, token);
2131 if (getOrSet == null) { 2132 token = parseTypeVariablesOpt(token);
2132 token = parseTypeVariablesOpt(token); 2133 token = parseFormalParametersOpt(token, MemberKind.Local);
2133 } else {
2134 listener.handleNoTypeVariables(token);
2135 }
2136 token = parseFormalParametersOpt(token);
2137 token = parseInitializersOpt(token); 2134 token = parseInitializersOpt(token);
2138 AsyncModifier savedAsyncModifier = asyncState; 2135 AsyncModifier savedAsyncModifier = asyncState;
2139 token = parseAsyncModifier(token); 2136 token = parseAsyncModifier(token);
2140 token = parseFunctionBody(token, false, true); 2137 token = parseFunctionBody(token, false, true);
2141 asyncState = savedAsyncModifier; 2138 asyncState = savedAsyncModifier;
2142 listener.endFunction(getOrSet, token); 2139 listener.endFunction(null, token);
2143 return token.next; 2140 return token.next;
2144 } 2141 }
2145 2142
2146 Token parseUnnamedFunction(Token token) { 2143 Token parseUnnamedFunction(Token token) {
2147 Token beginToken = token; 2144 Token beginToken = token;
2148 listener.beginUnnamedFunction(token); 2145 listener.beginUnnamedFunction(token);
2149 token = parseFormalParameters(token); 2146 token = parseFormalParameters(token, MemberKind.Local);
2150 AsyncModifier savedAsyncModifier = asyncState; 2147 AsyncModifier savedAsyncModifier = asyncState;
2151 token = parseAsyncModifier(token); 2148 token = parseAsyncModifier(token);
2152 bool isBlock = optional('{', token); 2149 bool isBlock = optional('{', token);
2153 token = parseFunctionBody(token, true, false); 2150 token = parseFunctionBody(token, true, false);
2154 asyncState = savedAsyncModifier; 2151 asyncState = savedAsyncModifier;
2155 listener.endUnnamedFunction(beginToken, token); 2152 listener.endUnnamedFunction(beginToken, token);
2156 return isBlock ? token.next : token; 2153 return isBlock ? token.next : token;
2157 } 2154 }
2158 2155
2159 Token parseFunctionDeclaration(Token token) { 2156 Token parseFunctionDeclaration(Token token) {
2160 listener.beginFunctionDeclaration(token); 2157 listener.beginFunctionDeclaration(token);
2161 token = parseFunction(token, null); 2158 token = parseFunction(token);
2162 listener.endFunctionDeclaration(token); 2159 listener.endFunctionDeclaration(token);
2163 return token; 2160 return token;
2164 } 2161 }
2165 2162
2166 Token parseFunctionExpression(Token token) { 2163 Token parseFunctionExpression(Token token) {
2167 Token beginToken = token; 2164 Token beginToken = token;
2168 listener.beginFunction(token); 2165 listener.beginFunction(token);
2169 listener.handleModifiers(0); 2166 listener.handleModifiers(0);
2170 token = parseReturnTypeOpt(token); 2167 token = parseReturnTypeOpt(token);
2171 listener.beginFunctionName(token); 2168 listener.beginFunctionName(token);
2172 token = parseIdentifier(token, IdentifierContext.functionExpressionName); 2169 token = parseIdentifier(token, IdentifierContext.functionExpressionName);
2173 listener.endFunctionName(beginToken, token); 2170 listener.endFunctionName(beginToken, token);
2174 token = parseTypeVariablesOpt(token); 2171 token = parseTypeVariablesOpt(token);
2175 token = parseFormalParameters(token); 2172 token = parseFormalParameters(token, MemberKind.Local);
2176 listener.handleNoInitializers(); 2173 listener.handleNoInitializers();
2177 AsyncModifier savedAsyncModifier = asyncState; 2174 AsyncModifier savedAsyncModifier = asyncState;
2178 token = parseAsyncModifier(token); 2175 token = parseAsyncModifier(token);
2179 bool isBlock = optional('{', token); 2176 bool isBlock = optional('{', token);
2180 token = parseFunctionBody(token, true, false); 2177 token = parseFunctionBody(token, true, false);
2181 asyncState = savedAsyncModifier; 2178 asyncState = savedAsyncModifier;
2182 listener.endFunction(null, token); 2179 listener.endFunction(null, token);
2183 return isBlock ? token.next : token; 2180 return isBlock ? token.next : token;
2184 } 2181 }
2185 2182
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after
3405 return parseVariablesDeclarationMaybeSemicolon(token, false); 3402 return parseVariablesDeclarationMaybeSemicolon(token, false);
3406 } 3403 }
3407 3404
3408 Token parseVariablesDeclarationMaybeSemicolon( 3405 Token parseVariablesDeclarationMaybeSemicolon(
3409 Token token, bool endWithSemicolon) { 3406 Token token, bool endWithSemicolon) {
3410 int count = 1; 3407 int count = 1;
3411 token = parseMetadataStar(token); 3408 token = parseMetadataStar(token);
3412 3409
3413 // If the next token has a type substitution comment /*=T*/, then 3410 // If the next token has a type substitution comment /*=T*/, then
3414 // the current 'var' token should be repealed and replaced. 3411 // the current 'var' token should be repealed and replaced.
3415 if (identical('var', token.stringValue)) { 3412 if (optional('var', token)) {
3416 token = 3413 token =
3417 listener.replaceTokenWithGenericCommentTypeAssign(token, token.next); 3414 listener.replaceTokenWithGenericCommentTypeAssign(token, token.next);
3418 } 3415 }
3419 3416
3420 token = parseModifiers(token); 3417 token = parseModifiers(token, MemberKind.Local, isVariable: true);
3421 token = parseTypeOpt(token);
3422 listener.beginVariablesDeclaration(token); 3418 listener.beginVariablesDeclaration(token);
3423 token = parseOptionallyInitializedIdentifier(token); 3419 token = parseOptionallyInitializedIdentifier(token);
3424 while (optional(',', token)) { 3420 while (optional(',', token)) {
3425 token = parseOptionallyInitializedIdentifier(token.next); 3421 token = parseOptionallyInitializedIdentifier(token.next);
3426 ++count; 3422 ++count;
3427 } 3423 }
3428 if (endWithSemicolon) { 3424 if (endWithSemicolon) {
3429 Token semicolon = token; 3425 Token semicolon = token;
3430 token = expectSemicolon(semicolon); 3426 token = expectSemicolon(semicolon);
3431 listener.endVariablesDeclaration(count, semicolon); 3427 listener.endVariablesDeclaration(count, semicolon);
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
3633 if (identical(value, 'on')) { 3629 if (identical(value, 'on')) {
3634 // on qualified catchPart? 3630 // on qualified catchPart?
3635 onKeyword = token; 3631 onKeyword = token;
3636 token = parseType(token.next); 3632 token = parseType(token.next);
3637 value = token.stringValue; 3633 value = token.stringValue;
3638 } 3634 }
3639 Token catchKeyword = null; 3635 Token catchKeyword = null;
3640 if (identical(value, 'catch')) { 3636 if (identical(value, 'catch')) {
3641 catchKeyword = token; 3637 catchKeyword = token;
3642 // TODO(ahe): Validate the "parameters". 3638 // TODO(ahe): Validate the "parameters".
3643 token = parseFormalParameters(token.next); 3639 token = parseFormalParameters(token.next, MemberKind.Catch);
3644 } 3640 }
3645 listener.endCatchClause(token); 3641 listener.endCatchClause(token);
3646 token = parseBlock(token); 3642 token = parseBlock(token);
3647 ++catchCount; 3643 ++catchCount;
3648 listener.handleCatchBlock(onKeyword, catchKeyword); 3644 listener.handleCatchBlock(onKeyword, catchKeyword);
3649 value = token.stringValue; // while condition 3645 value = token.stringValue; // while condition
3650 } 3646 }
3651 3647
3652 Token finallyKeyword = null; 3648 Token finallyKeyword = null;
3653 if (optional('finally', token)) { 3649 if (optional('finally', token)) {
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
3909 return reportUnrecoverableError( 3905 return reportUnrecoverableError(
3910 token, () => code.format(uri, token.charOffset, string)); 3906 token, () => code.format(uri, token.charOffset, string));
3911 } 3907 }
3912 } 3908 }
3913 3909
3914 typedef FastaMessage NoArgument(Uri uri, int charOffset); 3910 typedef FastaMessage NoArgument(Uri uri, int charOffset);
3915 3911
3916 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); 3912 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token);
3917 3913
3918 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); 3914 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string);
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/parser/listener.dart ('k') | pkg/front_end/lib/src/fasta/source/diet_listener.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698