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

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

Issue 2876813002: Implement generalized function types. (Closed)
Patch Set: Fixes for analyzer and dart2js. 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; 57 import '../scanner.dart' show ErrorToken;
58 58
59 import '../scanner/recover.dart' show closeBraceFor, skipToEof; 59 import '../scanner/recover.dart' show closeBraceFor, skipToEof;
60 60
61 import '../../scanner/token.dart' 61 import '../../scanner/token.dart'
62 show 62 show
63 ASSIGNMENT_PRECEDENCE, 63 ASSIGNMENT_PRECEDENCE,
64 CASCADE_PRECEDENCE, 64 CASCADE_PRECEDENCE,
65 EQUALITY_PRECEDENCE, 65 EQUALITY_PRECEDENCE,
66 Keyword,
67 POSTFIX_PRECEDENCE, 66 POSTFIX_PRECEDENCE,
68 RELATIONAL_PRECEDENCE, 67 RELATIONAL_PRECEDENCE,
69 TokenType; 68 TokenType;
70 69
71 import '../scanner/token.dart' 70 import '../scanner/token.dart'
72 show 71 show BeginGroupToken, SymbolToken, Token, isUserDefinableOperator;
73 BeginGroupToken,
74 KeywordToken,
75 SymbolToken,
76 Token,
77 isUserDefinableOperator;
78 72
79 import '../scanner/token_constants.dart' 73 import '../scanner/token_constants.dart'
80 show 74 show
81 COMMA_TOKEN, 75 COMMA_TOKEN,
82 DOUBLE_TOKEN, 76 DOUBLE_TOKEN,
83 EOF_TOKEN, 77 EOF_TOKEN,
84 EQ_TOKEN, 78 EQ_TOKEN,
85 FUNCTION_TOKEN, 79 FUNCTION_TOKEN,
86 GT_TOKEN, 80 GT_TOKEN,
87 GT_GT_TOKEN, 81 GT_GT_TOKEN,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 final String type; 113 final String type;
120 const FormalParameterType(this.type); 114 const FormalParameterType(this.type);
121 bool get isRequired => this == REQUIRED; 115 bool get isRequired => this == REQUIRED;
122 bool get isPositional => this == POSITIONAL; 116 bool get isPositional => this == POSITIONAL;
123 bool get isNamed => this == NAMED; 117 bool get isNamed => this == NAMED;
124 static final REQUIRED = const FormalParameterType('required'); 118 static final REQUIRED = const FormalParameterType('required');
125 static final POSITIONAL = const FormalParameterType('positional'); 119 static final POSITIONAL = const FormalParameterType('positional');
126 static final NAMED = const FormalParameterType('named'); 120 static final NAMED = const FormalParameterType('named');
127 } 121 }
128 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
129 /// 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
130 /// in a linked list (aka a token stream). 162 /// in a linked list (aka a token stream).
131 /// 163 ///
132 /// 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
133 /// [scanner.dart](../scanner.dart). 165 /// [scanner.dart](../scanner.dart).
134 /// 166 ///
135 /// Subclasses of the class [Listener] are used to listen to events. 167 /// Subclasses of the class [Listener] are used to listen to events.
136 /// 168 ///
137 /// 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
138 /// 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
296 if (identical(token.type, TokenType.SCRIPT_TAG)) { 328 if (identical(token.type, TokenType.SCRIPT_TAG)) {
297 return parseScript(token); 329 return parseScript(token);
298 } 330 }
299 token = parseMetadataStar(token); 331 token = parseMetadataStar(token);
300 final String value = token.stringValue; 332 final String value = token.stringValue;
301 if ((identical(value, 'abstract') && optional('class', token.next)) || 333 if ((identical(value, 'abstract') && optional('class', token.next)) ||
302 identical(value, 'class')) { 334 identical(value, 'class')) {
303 return parseClassOrNamedMixinApplication(token); 335 return parseClassOrNamedMixinApplication(token);
304 } else if (identical(value, 'enum')) { 336 } else if (identical(value, 'enum')) {
305 return parseEnum(token); 337 return parseEnum(token);
306 } else if (identical(value, 'typedef')) { 338 } else if (identical(value, 'typedef') &&
339 (token.next.isIdentifier || optional("void", token.next))) {
307 return parseTypedef(token); 340 return parseTypedef(token);
308 } else if (identical(value, 'library')) { 341 } else if (identical(value, 'library')) {
309 return parseLibraryName(token); 342 return parseLibraryName(token);
310 } else if (identical(value, 'import')) { 343 } else if (identical(value, 'import')) {
311 return parseImport(token); 344 return parseImport(token);
312 } else if (identical(value, 'export')) { 345 } else if (identical(value, 'export')) {
313 return parseExport(token); 346 return parseExport(token);
314 } else if (identical(value, 'part')) { 347 } else if (identical(value, 'part')) {
315 return parsePartOrPartOf(token); 348 return parsePartOrPartOf(token);
316 } else { 349 } else {
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 if (optional('=', peekAfterNominalType(token.next))) { 593 if (optional('=', peekAfterNominalType(token.next))) {
561 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration); 594 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration);
562 token = parseTypeVariablesOpt(token); 595 token = parseTypeVariablesOpt(token);
563 equals = token; 596 equals = token;
564 token = expect('=', token); 597 token = expect('=', token);
565 token = parseType(token); 598 token = parseType(token);
566 } else { 599 } else {
567 token = parseReturnTypeOpt(token.next); 600 token = parseReturnTypeOpt(token.next);
568 token = parseIdentifier(token, IdentifierContext.typedefDeclaration); 601 token = parseIdentifier(token, IdentifierContext.typedefDeclaration);
569 token = parseTypeVariablesOpt(token); 602 token = parseTypeVariablesOpt(token);
570 token = parseFormalParameters(token); 603 token = parseFormalParameters(token, MemberKind.FunctionTypeAlias);
571 } 604 }
572 listener.endFunctionTypeAlias(typedefKeyword, equals, token); 605 listener.endFunctionTypeAlias(typedefKeyword, equals, token);
573 return expect(';', token); 606 return expect(';', token);
574 } 607 }
575 608
576 Token parseMixinApplication(Token token) { 609 Token parseMixinApplication(Token token) {
577 listener.beginMixinApplication(token); 610 listener.beginMixinApplication(token);
578 token = parseType(token); 611 token = parseType(token);
579 Token withKeyword = token; 612 Token withKeyword = token;
580 token = expect('with', token); 613 token = expect('with', token);
581 token = parseTypeList(token); 614 token = parseTypeList(token);
582 listener.endMixinApplication(withKeyword); 615 listener.endMixinApplication(withKeyword);
583 return token; 616 return token;
584 } 617 }
585 618
586 Token parseReturnTypeOpt(Token token) { 619 Token parseReturnTypeOpt(Token token) {
587 if (identical(token.stringValue, 'void')) { 620 if (identical(token.stringValue, 'void')) {
588 if (isGeneralizedFunctionType(token.next)) { 621 if (isGeneralizedFunctionType(token.next)) {
589 return parseType(token); 622 return parseType(token);
590 } else { 623 } else {
591 listener.handleVoidKeyword(token); 624 listener.handleVoidKeyword(token);
592 return token.next; 625 return token.next;
593 } 626 }
594 } else { 627 } else {
595 return parseTypeOpt(token); 628 return parseTypeOpt(token);
596 } 629 }
597 } 630 }
598 631
599 Token parseFormalParametersOpt(Token token) { 632 Token parseFormalParametersOpt(Token token, MemberKind kind) {
600 if (optional('(', token)) { 633 if (optional('(', token)) {
601 return parseFormalParameters(token); 634 return parseFormalParameters(token, kind);
602 } else { 635 } else {
603 listener.handleNoFormalParameters(token); 636 listener.handleNoFormalParameters(token, kind);
604 return token; 637 return token;
605 } 638 }
606 } 639 }
607 640
608 Token skipFormalParameters(Token token) { 641 Token skipFormalParameters(Token token, MemberKind kind) {
609 // TODO(ahe): Shouldn't this be `beginFormalParameters`? 642 // TODO(ahe): Shouldn't this be `beginFormalParameters`?
610 listener.beginOptionalFormalParameters(token); 643 listener.beginOptionalFormalParameters(token);
611 if (!optional('(', token)) { 644 if (!optional('(', token)) {
612 if (optional(';', token)) { 645 if (optional(';', token)) {
613 reportRecoverableErrorCode(token, codeExpectedOpenParens); 646 reportRecoverableErrorCode(token, codeExpectedOpenParens);
614 return token; 647 return token;
615 } 648 }
616 return reportUnrecoverableErrorCodeWithString( 649 return reportUnrecoverableErrorCodeWithString(
617 token, codeExpectedButGot, "(") 650 token, codeExpectedButGot, "(")
618 .next; 651 .next;
619 } 652 }
620 BeginGroupToken beginGroupToken = token; 653 BeginGroupToken beginGroupToken = token;
621 Token endToken = beginGroupToken.endGroup; 654 Token endToken = beginGroupToken.endGroup;
622 listener.endFormalParameters(0, token, endToken); 655 listener.endFormalParameters(0, token, endToken, kind);
623 return endToken.next; 656 return endToken.next;
624 } 657 }
625 658
626 /// Parses the formal parameter list of a function. 659 /// Parses the formal parameter list of a function.
627 /// 660 ///
628 /// If [inFunctionType] is true, then the names may be omitted (except for 661 /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be
629 /// named arguments). If it is false, then the types may be omitted. 662 /// omitted (except for named arguments). Otherwise, types may be omitted.
630 Token parseFormalParameters(Token token, {bool inFunctionType: false}) { 663 Token parseFormalParameters(Token token, MemberKind kind) {
631 Token begin = token; 664 Token begin = token;
632 listener.beginFormalParameters(begin); 665 listener.beginFormalParameters(begin, kind);
633 expect('(', token); 666 expect('(', token);
634 int parameterCount = 0; 667 int parameterCount = 0;
635 do { 668 do {
636 token = token.next; 669 token = token.next;
637 if (optional(')', token)) { 670 if (optional(')', token)) {
638 break; 671 break;
639 } 672 }
640 ++parameterCount; 673 ++parameterCount;
641 String value = token.stringValue; 674 String value = token.stringValue;
642 if (identical(value, '[')) { 675 if (identical(value, '[')) {
643 token = parseOptionalFormalParameters(token, false, 676 token = parseOptionalFormalParameters(token, false, kind);
644 inFunctionType: inFunctionType);
645 break; 677 break;
646 } else if (identical(value, '{')) { 678 } else if (identical(value, '{')) {
647 token = parseOptionalFormalParameters(token, true, 679 token = parseOptionalFormalParameters(token, true, kind);
648 inFunctionType: inFunctionType);
649 break; 680 break;
650 } else if (identical(value, '[]')) { 681 } else if (identical(value, '[]')) {
651 --parameterCount; 682 --parameterCount;
652 reportRecoverableErrorCode(token, codeEmptyOptionalParameterList); 683 reportRecoverableErrorCode(token, codeEmptyOptionalParameterList);
653 token = token.next; 684 token = token.next;
654 break; 685 break;
655 } 686 }
656 token = parseFormalParameter(token, FormalParameterType.REQUIRED, 687 token = parseFormalParameter(token, FormalParameterType.REQUIRED, kind);
657 inFunctionType: inFunctionType);
658 } while (optional(',', token)); 688 } while (optional(',', token));
659 listener.endFormalParameters(parameterCount, begin, token); 689 listener.endFormalParameters(parameterCount, begin, token, kind);
660 return expect(')', token); 690 return expect(')', token);
661 } 691 }
662 692
663 Token parseFormalParameter(Token token, FormalParameterType kind, 693 Token parseFormalParameter(
664 {bool inFunctionType: false}) { 694 Token token, FormalParameterType kind, MemberKind memberKind) {
Johnni Winther 2017/05/19 08:23:39 Rename [kind] to [parameterKind]
ahe 2017/05/19 09:02:47 Done.
665 token = parseMetadataStar(token, forParameter: true); 695 token = parseMetadataStar(token, forParameter: true);
666 listener.beginFormalParameter(token); 696 listener.beginFormalParameter(token, memberKind);
667 697
668 // Skip over `covariant` token, if the next token is an identifier or 698 bool inFunctionType = memberKind == MemberKind.GeneralizedFunctionType;
669 // modifier. 699 token = parseModifiers(token, memberKind, parameterKind: kind);
670 // This enables the case where `covariant` is the name of the parameter:
671 // void foo(covariant);
672 Token covariantKeyword;
673 if (identical(token.stringValue, 'covariant') &&
674 (token.next.isIdentifier || isModifier(token.next))) {
675 covariantKeyword = token;
676 token = token.next;
677 }
678 token = parseModifiers(token);
679 bool isNamedParameter = kind == FormalParameterType.NAMED; 700 bool isNamedParameter = kind == FormalParameterType.NAMED;
680 701
681 Token thisKeyword = null; 702 Token thisKeyword = null;
682 Token nameToken; 703 Token nameToken;
683 if (inFunctionType && isNamedParameter) { 704 if (inFunctionType) {
684 token = parseType(token); 705 if (isNamedParameter || token.isIdentifier) {
685 token =
686 parseIdentifier(token, IdentifierContext.formalParameterDeclaration);
687 } else if (inFunctionType) {
688 token = parseType(token);
689 if (token.isIdentifier) {
690 token = parseIdentifier( 706 token = parseIdentifier(
691 token, IdentifierContext.formalParameterDeclaration); 707 token, IdentifierContext.formalParameterDeclaration);
692 } else { 708 } else {
693 listener.handleNoName(token); 709 listener.handleNoName(token);
694 } 710 }
695 } else { 711 } else {
696 token = parseReturnTypeOpt(token);
697 if (optional('this', token)) { 712 if (optional('this', token)) {
698 thisKeyword = token; 713 thisKeyword = token;
699 token = expect('.', token.next); 714 token = expect('.', token.next);
700 nameToken = token; 715 nameToken = token;
701 token = parseIdentifier(token, IdentifierContext.fieldInitializer); 716 token = parseIdentifier(token, IdentifierContext.fieldInitializer);
702 } else { 717 } else {
703 nameToken = token; 718 nameToken = token;
704 token = parseIdentifier( 719 token = parseIdentifier(
705 token, IdentifierContext.formalParameterDeclaration); 720 token, IdentifierContext.formalParameterDeclaration);
706 } 721 }
707 } 722 }
708 723
709 token = listener.injectGenericCommentTypeList(token); 724 token = listener.injectGenericCommentTypeList(token);
710 if (optional('(', token)) { 725 if (optional('(', token)) {
711 Token inlineFunctionTypeStart = token; 726 Token inlineFunctionTypeStart = token;
712 listener.beginFunctionTypedFormalParameter(token); 727 listener.beginFunctionTypedFormalParameter(token);
713 listener.handleNoTypeVariables(token); 728 listener.handleNoTypeVariables(token);
714 token = parseFormalParameters(token); 729 token = parseFormalParameters(token, MemberKind.FunctionTypedParameter);
715 listener.endFunctionTypedFormalParameter( 730 listener.endFunctionTypedFormalParameter(thisKeyword, kind);
716 covariantKeyword, thisKeyword, kind);
717 // Generalized function types don't allow inline function types. 731 // Generalized function types don't allow inline function types.
718 // The following isn't allowed: 732 // The following isn't allowed:
719 // int Function(int bar(String x)). 733 // int Function(int bar(String x)).
720 if (inFunctionType) { 734 if (memberKind == MemberKind.GeneralizedFunctionType) {
721 reportRecoverableErrorCode( 735 reportRecoverableErrorCode(
722 inlineFunctionTypeStart, codeInvalidInlineFunctionType); 736 inlineFunctionTypeStart, codeInvalidInlineFunctionType);
723 } 737 }
724 } else if (optional('<', token)) { 738 } else if (optional('<', token)) {
725 Token inlineFunctionTypeStart = token; 739 Token inlineFunctionTypeStart = token;
726 listener.beginFunctionTypedFormalParameter(token); 740 listener.beginFunctionTypedFormalParameter(token);
727 token = parseTypeVariablesOpt(token); 741 token = parseTypeVariablesOpt(token);
728 token = parseFormalParameters(token); 742 token = parseFormalParameters(token, MemberKind.FunctionTypedParameter);
729 listener.endFunctionTypedFormalParameter( 743 listener.endFunctionTypedFormalParameter(thisKeyword, kind);
730 covariantKeyword, thisKeyword, kind);
731 // Generalized function types don't allow inline function types. 744 // Generalized function types don't allow inline function types.
732 // The following isn't allowed: 745 // The following isn't allowed:
733 // int Function(int bar(String x)). 746 // int Function(int bar(String x)).
734 if (inFunctionType) { 747 if (memberKind == MemberKind.GeneralizedFunctionType) {
735 reportRecoverableErrorCode( 748 reportRecoverableErrorCode(
736 inlineFunctionTypeStart, codeInvalidInlineFunctionType); 749 inlineFunctionTypeStart, codeInvalidInlineFunctionType);
737 } 750 }
738 } 751 }
739 String value = token.stringValue; 752 String value = token.stringValue;
740 if ((identical('=', value)) || (identical(':', value))) { 753 if ((identical('=', value)) || (identical(':', value))) {
741 // TODO(ahe): Validate that these are only used for optional parameters. 754 // TODO(ahe): Validate that these are only used for optional parameters.
742 Token equal = token; 755 Token equal = token;
743 token = parseExpression(token.next); 756 token = parseExpression(token.next);
744 listener.handleValuedFormalParameter(equal, token); 757 listener.handleValuedFormalParameter(equal, token);
745 if (kind.isRequired) { 758 if (kind.isRequired) {
746 reportRecoverableErrorCode(equal, codeRequiredParameterWithDefault); 759 reportRecoverableErrorCode(equal, codeRequiredParameterWithDefault);
747 } else if (kind.isPositional && identical(':', value)) { 760 } else if (kind.isPositional && identical(':', value)) {
748 reportRecoverableErrorCode(equal, codePositionalParameterWithEquals); 761 reportRecoverableErrorCode(equal, codePositionalParameterWithEquals);
749 } 762 }
750 } else { 763 } else {
751 listener.handleFormalParameterWithoutValue(token); 764 listener.handleFormalParameterWithoutValue(token);
752 } 765 }
753 listener.endFormalParameter(covariantKeyword, thisKeyword, nameToken, kind); 766 listener.endFormalParameter(thisKeyword, nameToken, kind, memberKind);
754 return token; 767 return token;
755 } 768 }
756 769
757 Token parseOptionalFormalParameters(Token token, bool isNamed, 770 Token parseOptionalFormalParameters(
758 {bool inFunctionType: false}) { 771 Token token, bool isNamed, MemberKind kind) {
759 Token begin = token; 772 Token begin = token;
760 listener.beginOptionalFormalParameters(begin); 773 listener.beginOptionalFormalParameters(begin);
761 assert((isNamed && optional('{', token)) || optional('[', token)); 774 assert((isNamed && optional('{', token)) || optional('[', token));
762 int parameterCount = 0; 775 int parameterCount = 0;
763 do { 776 do {
764 token = token.next; 777 token = token.next;
765 if (isNamed && optional('}', token)) { 778 if (isNamed && optional('}', token)) {
766 break; 779 break;
767 } else if (!isNamed && optional(']', token)) { 780 } else if (!isNamed && optional(']', token)) {
768 break; 781 break;
769 } 782 }
770 var type = 783 var type =
771 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 784 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
772 token = parseFormalParameter(token, type, inFunctionType: inFunctionType); 785 token = parseFormalParameter(token, type, kind);
773 ++parameterCount; 786 ++parameterCount;
774 } while (optional(',', token)); 787 } while (optional(',', token));
775 if (parameterCount == 0) { 788 if (parameterCount == 0) {
776 reportRecoverableErrorCode( 789 reportRecoverableErrorCode(
777 token, 790 token,
778 isNamed 791 isNamed
779 ? codeEmptyNamedParameterList 792 ? codeEmptyNamedParameterList
780 : codeEmptyOptionalParameterList); 793 : codeEmptyOptionalParameterList);
781 } 794 }
782 listener.endOptionalFormalParameters(parameterCount, begin, token); 795 listener.endOptionalFormalParameters(parameterCount, begin, token);
(...skipping 12 matching lines...) Expand all
795 token = listener.injectGenericCommentTypeAssign(token); 808 token = listener.injectGenericCommentTypeAssign(token);
796 Token peek = peekAfterIfType(token); 809 Token peek = peekAfterIfType(token);
797 if (peek != null && (peek.isIdentifier || optional('this', peek))) { 810 if (peek != null && (peek.isIdentifier || optional('this', peek))) {
798 return parseType(token); 811 return parseType(token);
799 } 812 }
800 listener.handleNoType(token); 813 listener.handleNoType(token);
801 return token; 814 return token;
802 } 815 }
803 816
804 bool isValidTypeReference(Token token) { 817 bool isValidTypeReference(Token token) {
805 final kind = token.kind; 818 int kind = token.kind;
806 if (identical(kind, IDENTIFIER_TOKEN)) return true; 819 if (IDENTIFIER_TOKEN == kind) return true;
807 if (identical(kind, KEYWORD_TOKEN)) { 820 if (KEYWORD_TOKEN == kind) {
808 Keyword keyword = (token as KeywordToken).keyword; 821 String value = token.lexeme;
809 String value = keyword.lexeme; 822 return token.type.isPseudo ||
810 return keyword.isPseudo ||
811 (identical(value, 'dynamic')) || 823 (identical(value, 'dynamic')) ||
812 (identical(value, 'void')); 824 (identical(value, 'void'));
813 } 825 }
814 return false; 826 return false;
815 } 827 }
816 828
817 /// Returns true if [token] matches '<' type (',' type)* '>' '(', and 829 /// Returns true if [token] matches '<' type (',' type)* '>' '(', and
818 /// otherwise returns false. The final '(' is not part of the grammar 830 /// otherwise returns false. The final '(' is not part of the grammar
819 /// construct `typeArguments`, but it is required here such that type 831 /// construct `typeArguments`, but it is required here such that type
820 /// arguments in generic method invocations can be recognized, and as few as 832 /// arguments in generic method invocations can be recognized, and as few as
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 if (token.kind != STRING_TOKEN) { 1045 if (token.kind != STRING_TOKEN) {
1034 token = 1046 token =
1035 reportUnrecoverableErrorCodeWithToken(token, codeExpectedString).next; 1047 reportUnrecoverableErrorCodeWithToken(token, codeExpectedString).next;
1036 } 1048 }
1037 listener.handleStringPart(token); 1049 listener.handleStringPart(token);
1038 return token.next; 1050 return token.next;
1039 } 1051 }
1040 1052
1041 Token parseIdentifier(Token token, IdentifierContext context) { 1053 Token parseIdentifier(Token token, IdentifierContext context) {
1042 if (!token.isIdentifier) { 1054 if (!token.isIdentifier) {
1043 token = 1055 if (optional("void", token)) {
1044 reportUnrecoverableErrorCodeWithToken(token, codeExpectedIdentifier) 1056 reportRecoverableErrorCode(token, codeInvalidVoid);
1045 .next; 1057 } else {
1058 token =
1059 reportUnrecoverableErrorCodeWithToken(token, codeExpectedIdentifier)
1060 .next;
1061 }
1046 } else if (token.isBuiltInIdentifier && 1062 } else if (token.isBuiltInIdentifier &&
1047 !context.isBuiltInIdentifierAllowed) { 1063 !context.isBuiltInIdentifierAllowed) {
1048 if (context.inDeclaration) { 1064 if (context.inDeclaration) {
1049 reportRecoverableErrorCodeWithToken( 1065 reportRecoverableErrorCodeWithToken(
1050 token, codeBuiltInIdentifierInDeclaration); 1066 token, codeBuiltInIdentifierInDeclaration);
1051 } else if (!optional("dynamic", token)) { 1067 } else if (!optional("dynamic", token)) {
1052 reportRecoverableErrorCodeWithToken(token, codeBuiltInIdentifierAsType); 1068 reportRecoverableErrorCodeWithToken(token, codeBuiltInIdentifierAsType);
1053 } 1069 }
1054 } else if (!inPlainSync && token.type.isPseudo) { 1070 } else if (!inPlainSync && token.type.isPseudo) {
1055 if (optional('await', token)) { 1071 if (optional('await', token)) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1118 (optional('<', token.next) || optional('(', token.next)); 1134 (optional('<', token.next) || optional('(', token.next));
1119 } 1135 }
1120 1136
1121 Token parseType(Token token) { 1137 Token parseType(Token token) {
1122 Token begin = token; 1138 Token begin = token;
1123 if (isGeneralizedFunctionType(token)) { 1139 if (isGeneralizedFunctionType(token)) {
1124 // A function type without return type. 1140 // A function type without return type.
1125 // Push the non-existing return type first. The loop below will 1141 // Push the non-existing return type first. The loop below will
1126 // generate the full type. 1142 // generate the full type.
1127 listener.handleNoType(token); 1143 listener.handleNoType(token);
1128 } else if (identical(token.stringValue, 'void') && 1144 } else if (optional("void", token) &&
1129 isGeneralizedFunctionType(token.next)) { 1145 isGeneralizedFunctionType(token.next)) {
1130 listener.handleVoidKeyword(token); 1146 listener.handleVoidKeyword(token);
1131 token = token.next; 1147 token = token.next;
1132 } else { 1148 } else {
1133 if (isValidTypeReference(token)) { 1149 IdentifierContext context = IdentifierContext.typeReference;
1134 token = parseIdentifier(token, IdentifierContext.typeReference); 1150 if (token.isIdentifier && optional(".", token.next)) {
1135 token = parseQualifiedRestOpt( 1151 context = IdentifierContext.prefixedTypeReference;
1136 token, IdentifierContext.typeReferenceContinuation);
1137 } else {
1138 token =
1139 reportUnrecoverableErrorCodeWithToken(token, codeExpectedType).next;
1140 listener.handleInvalidTypeReference(token);
1141 } 1152 }
1153 token = parseIdentifier(token, context);
1154 token = parseQualifiedRestOpt(
1155 token, IdentifierContext.typeReferenceContinuation);
1142 token = parseTypeArgumentsOpt(token); 1156 token = parseTypeArgumentsOpt(token);
1143 listener.handleType(begin, token); 1157 listener.handleType(begin, token);
1144 } 1158 }
1145 1159
1146 { 1160 {
1147 Token newBegin = 1161 Token newBegin =
1148 listener.replaceTokenWithGenericCommentTypeAssign(begin, token); 1162 listener.replaceTokenWithGenericCommentTypeAssign(begin, token);
1149 if (!identical(newBegin, begin)) { 1163 if (!identical(newBegin, begin)) {
1150 listener.discardTypeReplacedWithCommentTypeAssign(); 1164 listener.discardTypeReplacedWithCommentTypeAssign();
1151 return parseType(newBegin); 1165 return parseType(newBegin);
1152 } 1166 }
1153 } 1167 }
1154 1168
1155 // 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.
1156 // For example: `int Function() Function(int) Function(String x)`. 1170 // For example: `int Function() Function(int) Function(String x)`.
1157 while (isGeneralizedFunctionType(token)) { 1171 while (isGeneralizedFunctionType(token)) {
1158 token = parseFunctionType(token); 1172 token = parseFunctionType(token);
1159 } 1173 }
1160 return token; 1174 return token;
1161 } 1175 }
1162 1176
1163 /// Parses a generalized function type. 1177 /// Parses a generalized function type.
1164 /// 1178 ///
1165 /// The return type must already be pushed. 1179 /// The return type must already be pushed.
1166 Token parseFunctionType(Token token) { 1180 Token parseFunctionType(Token token) {
1167 assert(optional('Function', token)); 1181 assert(optional('Function', token));
1168 Token functionToken = token; 1182 Token functionToken = token;
1169 token = token.next; 1183 token = token.next;
1170 token = parseTypeVariablesOpt(token); 1184 token = parseTypeVariablesOpt(token);
1171 token = parseFormalParameters(token, inFunctionType: true); 1185 token = parseFormalParameters(token, MemberKind.GeneralizedFunctionType);
1172 listener.handleFunctionType(functionToken, token); 1186 listener.handleFunctionType(functionToken, token);
1173 return token; 1187 return token;
1174 } 1188 }
1175 1189
1176 Token parseTypeArgumentsOpt(Token token) { 1190 Token parseTypeArgumentsOpt(Token token) {
1177 return parseStuff( 1191 return parseStuff(
1178 token, 1192 token,
1179 (t) => listener.beginTypeArguments(t), 1193 (t) => listener.beginTypeArguments(t),
1180 (t) => parseType(t), 1194 (t) => parseType(t),
1181 (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
1280 token = reportUnexpectedToken(token).next; 1294 token = reportUnexpectedToken(token).next;
1281 if (identical(token.kind, EOF_TOKEN)) return token; 1295 if (identical(token.kind, EOF_TOKEN)) return token;
1282 } 1296 }
1283 } 1297 }
1284 var modifiers = identifiers.reverse(); 1298 var modifiers = identifiers.reverse();
1285 return isField 1299 return isField
1286 ? parseFields(start, modifiers, type, getOrSet, name, true) 1300 ? parseFields(start, modifiers, type, getOrSet, name, true)
1287 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); 1301 : parseTopLevelMethod(start, modifiers, type, getOrSet, name);
1288 } 1302 }
1289 1303
1290 bool isVarFinalOrConst(Token token) {
1291 String value = token.stringValue;
1292 return identical('var', value) ||
1293 identical('final', value) ||
1294 identical('const', value);
1295 }
1296
1297 Token expectVarFinalOrConst(
1298 Link<Token> modifiers, bool hasType, bool allowStatic) {
1299 int modifierCount = 0;
1300 Token staticModifier;
1301 if (allowStatic &&
1302 !modifiers.isEmpty &&
1303 optional('static', modifiers.head)) {
1304 staticModifier = modifiers.head;
1305 modifierCount++;
1306 parseModifier(staticModifier);
1307 modifiers = modifiers.tail;
1308 }
1309 if (modifiers.isEmpty) {
1310 listener.handleModifiers(modifierCount);
1311 return null;
1312 }
1313 if (modifiers.tail.isEmpty) {
1314 Token modifier = modifiers.head;
1315 if (isVarFinalOrConst(modifier)) {
1316 modifierCount++;
1317 parseModifier(modifier);
1318 listener.handleModifiers(modifierCount);
1319 // TODO(ahe): The caller checks for "var Type name", perhaps we should
1320 // check here instead.
1321 return modifier;
1322 }
1323 }
1324
1325 // Slow case to report errors.
1326 List<Token> modifierList = modifiers.toList();
1327 Token varFinalOrConst =
1328 modifierList.firstWhere(isVarFinalOrConst, orElse: () => null);
1329 if (allowStatic && staticModifier == null) {
1330 staticModifier = modifierList.firstWhere(
1331 (modifier) => optional('static', modifier),
1332 orElse: () => null);
1333 if (staticModifier != null) {
1334 modifierCount++;
1335 parseModifier(staticModifier);
1336 modifierList.remove(staticModifier);
1337 }
1338 }
1339 bool hasTypeOrModifier = hasType;
1340 if (varFinalOrConst != null) {
1341 parseModifier(varFinalOrConst);
1342 modifierCount++;
1343 hasTypeOrModifier = true;
1344 modifierList.remove(varFinalOrConst);
1345 }
1346 listener.handleModifiers(modifierCount);
1347 for (Token modifier in modifierList) {
1348 reportRecoverableErrorCodeWithToken(
1349 modifier,
1350 hasTypeOrModifier
1351 ? codeExtraneousModifier
1352 : codeExtraneousModifierReplace);
1353 }
1354 return null;
1355 }
1356
1357 /// Removes the optional `covariant` token from the modifiers, if there
1358 /// is no `static` in the list, and `covariant` is the first modifier.
1359 Link<Token> removeOptCovariantTokenIfNotStatic(Link<Token> modifiers) {
1360 if (modifiers.isEmpty ||
1361 !identical(modifiers.first.stringValue, 'covariant')) {
1362 return modifiers;
1363 }
1364 for (Token modifier in modifiers.tail) {
1365 if (identical(modifier.stringValue, 'static')) {
1366 return modifiers;
1367 }
1368 }
1369 return modifiers.tail;
1370 }
1371
1372 Token parseFields(Token start, Link<Token> modifiers, Token type, 1304 Token parseFields(Token start, Link<Token> modifiers, Token type,
1373 Token getOrSet, Token name, bool isTopLevel) { 1305 Token getOrSet, Token name, bool isTopLevel) {
1374 bool hasType = type != null; 1306 Token token = parseModifiers(start,
1307 isTopLevel ? MemberKind.TopLevelField : MemberKind.NonStaticField,
1308 isVariable: true);
1375 1309
1376 Token covariantKeyword; 1310 if (token != name) {
1377 if (getOrSet == null && !isTopLevel) { 1311 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
1378 // TODO(ahe): replace the method removeOptCovariantTokenIfNotStatic with 1312 token = name;
1379 // a better mechanism.
1380 Link<Token> newModifiers = removeOptCovariantTokenIfNotStatic(modifiers);
1381 if (!identical(newModifiers, modifiers)) {
1382 covariantKeyword = modifiers.first;
1383 modifiers = newModifiers;
1384 }
1385 }
1386
1387 Token varFinalOrConst =
1388 expectVarFinalOrConst(modifiers, hasType, !isTopLevel);
1389 bool isVar = false;
1390 bool hasModifier = false;
1391 if (varFinalOrConst != null) {
1392 hasModifier = true;
1393 isVar = optional('var', varFinalOrConst);
1394 }
1395
1396 if (getOrSet != null) {
1397 reportRecoverableErrorCodeWithToken(
1398 getOrSet,
1399 hasModifier || hasType
1400 ? codeExtraneousModifier
1401 : codeExtraneousModifierReplace);
1402 }
1403
1404 if (!hasType) {
1405 listener.handleNoType(name);
1406 } else if (optional('void', type) &&
1407 !isGeneralizedFunctionType(type.next)) {
1408 listener.handleNoType(name);
1409 // TODO(ahe): This error is reported twice, second time is from
1410 // [parseVariablesDeclarationMaybeSemicolon] via
1411 // [PartialFieldListElement.parseNode].
1412 reportRecoverableErrorCode(type, codeInvalidVoid);
1413 } else {
1414 parseType(type);
1415 if (isVar) {
1416 reportRecoverableErrorCodeWithToken(
1417 modifiers.head, codeExtraneousModifier);
1418 }
1419 } 1313 }
1420 1314
1421 IdentifierContext context = isTopLevel 1315 IdentifierContext context = isTopLevel
1422 ? IdentifierContext.topLevelVariableDeclaration 1316 ? IdentifierContext.topLevelVariableDeclaration
1423 : IdentifierContext.fieldDeclaration; 1317 : IdentifierContext.fieldDeclaration;
1424 Token token = parseIdentifier(name, context); 1318 token = parseIdentifier(token, context);
1425 1319
1426 int fieldCount = 1; 1320 int fieldCount = 1;
1427 token = parseFieldInitializerOpt(token); 1321 token = parseFieldInitializerOpt(token);
1428 while (optional(',', token)) { 1322 while (optional(',', token)) {
1429 token = parseIdentifier(token.next, context); 1323 token = parseIdentifier(token.next, context);
1430 token = parseFieldInitializerOpt(token); 1324 token = parseFieldInitializerOpt(token);
1431 ++fieldCount; 1325 ++fieldCount;
1432 } 1326 }
1433 Token semicolon = token; 1327 Token semicolon = token;
1434 token = expectSemicolon(token); 1328 token = expectSemicolon(token);
1435 if (isTopLevel) { 1329 if (isTopLevel) {
1436 listener.endTopLevelFields(fieldCount, start, semicolon); 1330 listener.endTopLevelFields(fieldCount, start, semicolon);
1437 } else { 1331 } else {
1438 listener.endFields(fieldCount, covariantKeyword, start, semicolon); 1332 listener.endFields(fieldCount, start, semicolon);
1439 } 1333 }
1440 return token; 1334 return token;
1441 } 1335 }
1442 1336
1443 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, 1337 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type,
1444 Token getOrSet, Token name) { 1338 Token getOrSet, Token name) {
1445 listener.beginTopLevelMethod(start, name); 1339 listener.beginTopLevelMethod(start, name);
1446 Token externalModifier; 1340 Token externalModifier;
1447 // TODO(johnniwinther): Move error reporting to resolution to give more 1341 // TODO(johnniwinther): Move error reporting to resolution to give more
1448 // specific error messages. 1342 // specific error messages.
(...skipping 17 matching lines...) Expand all
1466 parseReturnTypeOpt(type); 1360 parseReturnTypeOpt(type);
1467 } 1361 }
1468 Token token = 1362 Token token =
1469 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration); 1363 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration);
1470 1364
1471 if (getOrSet == null) { 1365 if (getOrSet == null) {
1472 token = parseTypeVariablesOpt(token); 1366 token = parseTypeVariablesOpt(token);
1473 } else { 1367 } else {
1474 listener.handleNoTypeVariables(token); 1368 listener.handleNoTypeVariables(token);
1475 } 1369 }
1476 token = parseFormalParametersOpt(token); 1370 token = parseFormalParametersOpt(token, MemberKind.TopLevelMethod);
1477 AsyncModifier savedAsyncModifier = asyncState; 1371 AsyncModifier savedAsyncModifier = asyncState;
1478 Token asyncToken = token; 1372 Token asyncToken = token;
1479 token = parseAsyncModifier(token); 1373 token = parseAsyncModifier(token);
1480 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { 1374 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
1481 reportRecoverableErrorCode(asyncToken, codeSetterNotSync); 1375 reportRecoverableErrorCode(asyncToken, codeSetterNotSync);
1482 } 1376 }
1483 token = parseFunctionBody(token, false, externalModifier != null); 1377 token = parseFunctionBody(token, false, externalModifier != null);
1484 asyncState = savedAsyncModifier; 1378 asyncState = savedAsyncModifier;
1485 Token endToken = token; 1379 Token endToken = token;
1486 token = token.next; 1380 token = token.next;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1684 } else { 1578 } else {
1685 reportRecoverableErrorCodeWithToken(token, codeExpectedString); 1579 reportRecoverableErrorCodeWithToken(token, codeExpectedString);
1686 return parseRecoverExpression(token); 1580 return parseRecoverExpression(token);
1687 } 1581 }
1688 } 1582 }
1689 1583
1690 Token expectSemicolon(Token token) { 1584 Token expectSemicolon(Token token) {
1691 return expect(';', token); 1585 return expect(';', token);
1692 } 1586 }
1693 1587
1694 bool isModifier(Token token) { 1588 bool isModifier(Token token) => modifierOrder(token) < 127;
1589
1590 int modifierOrder(Token token) {
Johnni Winther 2017/05/19 08:23:39 Add doc about the semantics of the order.
ahe 2017/05/19 09:02:47 Done.
1695 final String value = token.stringValue; 1591 final String value = token.stringValue;
1696 return (identical('final', value)) || 1592 if (identical('external', value)) return 0;
1697 (identical('var', value)) || 1593 if (identical('static', value) || identical('covariant', value)) {
1698 (identical('const', value)) || 1594 return 1;
1699 (identical('abstract', value)) || 1595 }
1700 (identical('static', value)) || 1596 if (identical('final', value) ||
1701 (identical('external', value)); 1597 identical('var', value) ||
1598 identical('const', value)) {
1599 return 2;
1600 }
1601 if (identical('abstract', value)) return 3;
1602 return 127;
1702 } 1603 }
1703 1604
1704 Token parseModifier(Token token) { 1605 Token parseModifier(Token token) {
1705 assert(isModifier(token)); 1606 assert(isModifier(token));
1706 listener.handleModifier(token); 1607 listener.handleModifier(token);
1707 return token.next; 1608 return token.next;
1708 } 1609 }
1709 1610
1710 void parseModifierList(Link<Token> tokens) { 1611 Token parseModifiers(Token token, MemberKind kind,
Johnni Winther 2017/05/19 08:23:38 Add doc on when this is used (and not used)
Johnni Winther 2017/05/19 08:23:39 Rename [kind] to [memberKind].
ahe 2017/05/19 09:02:47 Done.
ahe 2017/05/19 09:02:47 Done.
1612 {FormalParameterType parameterKind, bool isVariable: false}) {
1613 bool returnTypeAllowed =
1614 !isVariable && kind != MemberKind.GeneralizedFunctionType;
1615 bool typeRequired =
1616 isVariable || kind == MemberKind.GeneralizedFunctionType;
1711 int count = 0; 1617 int count = 0;
1712 for (; !tokens.isEmpty; tokens = tokens.tail) { 1618
1713 Token token = tokens.head; 1619 int currentOrder = -1;
1714 if (isModifier(token)) { 1620 bool hasVar = false;
1715 parseModifier(token); 1621 while (token.kind == KEYWORD_TOKEN) {
1716 } else { 1622 if (token.type.isPseudo) {
1717 reportUnexpectedToken(token); 1623 // A pseudo keyword is never a modifier.
1718 // Skip the remaining modifiers.
1719 break; 1624 break;
1720 } 1625 }
1721 count++; 1626 if (token.isBuiltInIdentifier) {
1627 // A built-in identifier can only be a modifier as long as it is
1628 // followed by another modifier or an identifier. Otherwise, it is the
1629 // identifier.
1630 if (token.next.kind != KEYWORD_TOKEN && !token.next.isIdentifier) {
1631 break;
1632 }
1633 }
1634 int order = modifierOrder(token);
1635 if (order < 3) {
1636 // `abstract` isn't parsed with this method.
1637 if (order > currentOrder) {
1638 currentOrder = order;
1639 if (optional("var", token)) {
1640 if (!isVariable && parameterKind == null) {
1641 reportRecoverableErrorCodeWithToken(
1642 token, codeExtraneousModifier);
1643 }
1644 hasVar = true;
1645 typeRequired = false;
1646 } else if (optional("final", token)) {
1647 if (!isVariable && parameterKind == null) {
1648 reportRecoverableErrorCodeWithToken(
1649 token, codeExtraneousModifier);
1650 }
1651 typeRequired = false;
1652 } else if (optional("const", token)) {
1653 if (!isVariable) {
1654 reportRecoverableErrorCodeWithToken(
1655 token, codeExtraneousModifier);
1656 }
1657 typeRequired = false;
1658 } else if (optional("static", token)) {
1659 if (kind == MemberKind.NonStaticMethod) {
1660 kind = MemberKind.StaticMethod;
1661 } else if (kind == MemberKind.NonStaticField) {
1662 kind = MemberKind.StaticField;
1663 } else {
1664 reportRecoverableErrorCodeWithToken(
1665 token, codeExtraneousModifier);
1666 token = token.next;
1667 continue;
1668 }
1669 } else if (optional("covariant", token)) {
1670 switch (kind) {
1671 case MemberKind.StaticField:
1672 case MemberKind.StaticMethod:
1673 case MemberKind.TopLevelField:
1674 case MemberKind.TopLevelMethod:
1675 reportRecoverableErrorCodeWithToken(
1676 token, codeExtraneousModifier);
1677 token = token.next;
1678 continue;
1679
1680 default:
1681 break;
1682 }
1683 } else if (optional("external", token)) {
1684 switch (kind) {
1685 case MemberKind.Factory:
1686 case MemberKind.NonStaticMethod:
1687 case MemberKind.StaticMethod:
1688 case MemberKind.TopLevelMethod:
1689 break;
1690
1691 default:
1692 reportRecoverableErrorCodeWithToken(
1693 token, codeExtraneousModifier);
1694 token = token.next;
1695 continue;
1696 }
1697 }
1698 token = parseModifier(token);
1699 count++;
1700 } else {
1701 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
1702 token = token.next;
1703 }
1704 } else {
1705 break;
1706 }
1722 } 1707 }
1723 listener.handleModifiers(count); 1708 listener.handleModifiers(count);
1724 }
1725 1709
1726 Token parseModifiers(Token token) { 1710 Token beforeType = token;
1727 // TODO(ahe): The calling convention of this method probably needs to 1711 if (returnTypeAllowed) {
1728 // change. For example, this is parsed as a local variable declaration: 1712 token = parseReturnTypeOpt(token);
1729 // `abstract foo;`. Ideally, this example should be handled as a local 1713 } else {
1730 // variable having the type `abstract` (which should be reported as 1714 token = typeRequired ? parseType(token) : parseTypeOpt(token);
1731 // `codeBuiltInIdentifierAsType` by [parseIdentifier]).
1732 int count = 0;
1733 while (identical(token.kind, KEYWORD_TOKEN)) {
1734 if (!isModifier(token)) break;
1735 token = parseModifier(token);
1736 count++;
1737 } 1715 }
1738 listener.handleModifiers(count); 1716 if (typeRequired && beforeType == token) {
1717 reportRecoverableErrorCode(token, codeTypeRequired);
1718 }
1719 if (hasVar && beforeType != token) {
1720 reportRecoverableErrorCode(beforeType, codeTypeAfterVar);
1721 }
1739 return token; 1722 return token;
1740 } 1723 }
1741 1724
1742 /// Returns the first token after the type starting at [token]. 1725 /// Returns the first token after the type starting at [token].
1743 /// 1726 ///
1744 /// This method assumes that [token] is an identifier (or void). Use 1727 /// This method assumes that [token] is an identifier (or void). Use
1745 /// [peekAfterIfType] if [token] isn't known to be an identifier. 1728 /// [peekAfterIfType] if [token] isn't known to be an identifier.
1746 Token peekAfterType(Token token) { 1729 Token peekAfterType(Token token) {
1747 // We are looking at "identifier ...". 1730 // We are looking at "identifier ...".
1748 Token peek = token; 1731 Token peek = token;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1951 isField = true; 1934 isField = true;
1952 } 1935 }
1953 break; 1936 break;
1954 } else if ((identical(value, '=')) || (identical(value, ','))) { 1937 } else if ((identical(value, '=')) || (identical(value, ','))) {
1955 isField = true; 1938 isField = true;
1956 break; 1939 break;
1957 } else { 1940 } else {
1958 token = reportUnexpectedToken(token).next; 1941 token = reportUnexpectedToken(token).next;
1959 if (identical(token.kind, EOF_TOKEN)) { 1942 if (identical(token.kind, EOF_TOKEN)) {
1960 // TODO(ahe): This is a hack, see parseTopLevelMember. 1943 // TODO(ahe): This is a hack, see parseTopLevelMember.
1961 listener.endFields(1, null, start, token); 1944 listener.endFields(1, start, token);
1962 listener.endMember(); 1945 listener.endMember();
1963 return token; 1946 return token;
1964 } 1947 }
1965 } 1948 }
1966 } 1949 }
1967 1950
1968 var modifiers = identifiers.reverse(); 1951 var modifiers = identifiers.reverse();
1969 token = isField 1952 token = isField
1970 ? parseFields(start, modifiers, type, getOrSet, name, false) 1953 ? parseFields(start, modifiers, type, getOrSet, name, false)
1971 : parseMethod(start, modifiers, type, getOrSet, name); 1954 : parseMethod(start, modifiers, type, getOrSet, name);
1972 listener.endMember(); 1955 listener.endMember();
1973 return token; 1956 return token;
1974 } 1957 }
1975 1958
1976 Token parseMethod(Token start, Link<Token> modifiers, Token type, 1959 Token parseMethod(Token start, Link<Token> modifiers, Token type,
1977 Token getOrSet, Token name) { 1960 Token getOrSet, Token name) {
1978 listener.beginMethod(start, name); 1961 listener.beginMethod(start, name);
1962
1979 Token externalModifier; 1963 Token externalModifier;
1980 Token staticModifier; 1964 Token staticModifier;
1981 Token constModifier; 1965 void parseModifierList(Link<Token> tokens) {
1982 int modifierCount = 0; 1966 int count = 0;
1983 int allowedModifierCount = 1; 1967 int currentOrder = -1;
1984 // TODO(johnniwinther): Move error reporting to resolution to give more 1968 for (; !tokens.isEmpty; tokens = tokens.tail) {
1985 // specific error messages. 1969 Token token = tokens.head;
1986 for (Token modifier in modifiers) { 1970 if (optional("abstract", token)) {
1987 if (externalModifier == null && optional('external', modifier)) { 1971 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
1988 modifierCount++; 1972 continue;
1989 externalModifier = modifier;
1990 if (modifierCount != allowedModifierCount) {
1991 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
1992 } 1973 }
1993 allowedModifierCount++; 1974 int order = modifierOrder(token);
1994 } else if (staticModifier == null && optional('static', modifier)) { 1975 if (order < 127) {
1995 modifierCount++; 1976 if (order > currentOrder) {
1996 staticModifier = modifier; 1977 currentOrder = order;
1997 if (modifierCount != allowedModifierCount) { 1978 if (optional("var", token)) {
1998 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier); 1979 reportRecoverableErrorCodeWithToken(
1980 token, codeExtraneousModifier);
1981 } else if (optional("const", token)) {
1982 if (getOrSet != null) {
1983 reportRecoverableErrorCodeWithToken(
1984 token, codeExtraneousModifier);
1985 continue;
1986 }
1987 } else if (optional("external", token)) {
1988 externalModifier = token;
1989 } else if (optional("static", token)) {
1990 staticModifier = token;
1991 } else if (optional("covariant", token)) {
1992 if (staticModifier != null ||
1993 getOrSet == null ||
1994 optional("get", getOrSet)) {
1995 reportRecoverableErrorCodeWithToken(
1996 token, codeExtraneousModifier);
1997 continue;
1998 }
1999 }
2000 } else {
2001 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
2002 continue;
2003 }
2004 } else {
2005 reportUnexpectedToken(token);
2006 break; // Skip the remaining modifiers.
1999 } 2007 }
2000 } else if (constModifier == null && optional('const', modifier)) { 2008 parseModifier(token);
2001 modifierCount++; 2009 count++;
2002 constModifier = modifier;
2003 if (modifierCount != allowedModifierCount) {
2004 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
2005 }
2006 } else {
2007 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
2008 } 2010 }
2011 listener.handleModifiers(count);
2009 } 2012 }
2010 if (getOrSet != null && constModifier != null) { 2013
2011 reportRecoverableErrorCodeWithToken(
2012 constModifier, codeExtraneousModifier);
2013 }
2014 parseModifierList(modifiers); 2014 parseModifierList(modifiers);
2015 2015
2016 if (type == null) { 2016 if (type == null) {
2017 listener.handleNoType(name); 2017 listener.handleNoType(name);
2018 } else { 2018 } else {
2019 parseReturnTypeOpt(type); 2019 parseReturnTypeOpt(type);
2020 } 2020 }
2021 Token token; 2021 Token token;
2022 if (optional('operator', name)) { 2022 if (optional('operator', name)) {
2023 token = parseOperatorName(name); 2023 token = parseOperatorName(name);
2024 if (staticModifier != null) { 2024 if (staticModifier != null) {
2025 reportRecoverableErrorCodeWithToken( 2025 reportRecoverableErrorCodeWithToken(
2026 staticModifier, codeExtraneousModifier); 2026 staticModifier, codeExtraneousModifier);
2027 } 2027 }
2028 } else { 2028 } else {
2029 token = parseIdentifier(name, IdentifierContext.methodDeclaration); 2029 token = parseIdentifier(name, IdentifierContext.methodDeclaration);
2030 } 2030 }
2031 2031
2032 token = parseQualifiedRestOpt( 2032 token = parseQualifiedRestOpt(
2033 token, IdentifierContext.methodDeclarationContinuation); 2033 token, IdentifierContext.methodDeclarationContinuation);
2034 if (getOrSet == null) { 2034 if (getOrSet == null) {
2035 token = parseTypeVariablesOpt(token); 2035 token = parseTypeVariablesOpt(token);
2036 } else { 2036 } else {
2037 listener.handleNoTypeVariables(token); 2037 listener.handleNoTypeVariables(token);
2038 } 2038 }
2039 token = parseFormalParametersOpt(token); 2039 token = parseFormalParametersOpt(
2040 token,
2041 staticModifier != null
2042 ? MemberKind.StaticMethod
2043 : MemberKind.NonStaticMethod);
2040 token = parseInitializersOpt(token); 2044 token = parseInitializersOpt(token);
2041 AsyncModifier savedAsyncModifier = asyncState; 2045 AsyncModifier savedAsyncModifier = asyncState;
2042 Token asyncToken = token; 2046 Token asyncToken = token;
2043 token = parseAsyncModifier(token); 2047 token = parseAsyncModifier(token);
2044 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { 2048 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
2045 reportRecoverableErrorCode(asyncToken, codeSetterNotSync); 2049 reportRecoverableErrorCode(asyncToken, codeSetterNotSync);
2046 } 2050 }
2047 if (optional('=', token)) { 2051 if (optional('=', token)) {
2048 token = parseRedirectingFactoryBody(token); 2052 token = parseRedirectingFactoryBody(token);
2049 } else { 2053 } else {
(...skipping 15 matching lines...) Expand all
2065 isExternal = true; 2069 isExternal = true;
2066 } 2070 }
2067 token = parseModifier(token); 2071 token = parseModifier(token);
2068 modifierCount++; 2072 modifierCount++;
2069 } 2073 }
2070 listener.handleModifiers(modifierCount); 2074 listener.handleModifiers(modifierCount);
2071 Token factoryKeyword = token; 2075 Token factoryKeyword = token;
2072 listener.beginFactoryMethod(factoryKeyword); 2076 listener.beginFactoryMethod(factoryKeyword);
2073 token = expect('factory', token); 2077 token = expect('factory', token);
2074 token = parseConstructorReference(token); 2078 token = parseConstructorReference(token);
2075 token = parseFormalParameters(token); 2079 token = parseFormalParameters(token, MemberKind.Factory);
2076 Token asyncToken = token; 2080 Token asyncToken = token;
2077 token = parseAsyncModifier(token); 2081 token = parseAsyncModifier(token);
2078 if (!inPlainSync) { 2082 if (!inPlainSync) {
2079 reportRecoverableErrorCode(asyncToken, codeFactoryNotSync); 2083 reportRecoverableErrorCode(asyncToken, codeFactoryNotSync);
2080 } 2084 }
2081 if (optional('=', token)) { 2085 if (optional('=', token)) {
2082 token = parseRedirectingFactoryBody(token); 2086 token = parseRedirectingFactoryBody(token);
2083 } else { 2087 } else {
2084 token = parseFunctionBody(token, false, isExternal); 2088 token = parseFunctionBody(token, false, isExternal);
2085 } 2089 }
2086 listener.endFactoryMethod(start, factoryKeyword, token); 2090 listener.endFactoryMethod(start, factoryKeyword, token);
2087 return token.next; 2091 return token.next;
2088 } 2092 }
2089 2093
2090 Token parseOperatorName(Token token) { 2094 Token parseOperatorName(Token token) {
2091 assert(optional('operator', token)); 2095 assert(optional('operator', token));
2092 if (isUserDefinableOperator(token.next.stringValue)) { 2096 if (isUserDefinableOperator(token.next.stringValue)) {
2093 Token operator = token; 2097 Token operator = token;
2094 token = token.next; 2098 token = token.next;
2095 listener.handleOperatorName(operator, token); 2099 listener.handleOperatorName(operator, token);
2096 return token.next; 2100 return token.next;
2097 } else { 2101 } else {
2098 return parseIdentifier(token, IdentifierContext.operatorName); 2102 return parseIdentifier(token, IdentifierContext.operatorName);
2099 } 2103 }
2100 } 2104 }
2101 2105
2102 Token parseFunction(Token token, Token getOrSet) { 2106 Token parseFunction(Token token) {
2103 Token beginToken = token; 2107 Token beginToken = token;
2104 listener.beginFunction(token); 2108 listener.beginFunction(token);
2105 token = parseModifiers(token); 2109 token = parseModifiers(token, MemberKind.Local);
2106 if (identical(getOrSet, token)) { 2110 listener.beginFunctionName(token);
2107 // get <name> => ... 2111 token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
2108 token = token.next;
2109 listener.handleNoType(token);
2110 listener.beginFunctionName(token);
2111 if (optional('operator', token)) {
2112 token = parseOperatorName(token);
2113 } else {
2114 token =
2115 parseIdentifier(token, IdentifierContext.localAccessorDeclaration);
2116 }
2117 } else if (optional('operator', token)) {
2118 // operator <op> (...
2119 listener.handleNoType(token);
2120 listener.beginFunctionName(token);
2121 token = parseOperatorName(token);
2122 } else {
2123 // <type>? <get>? <name>
2124 token = parseReturnTypeOpt(token);
2125 if (identical(getOrSet, token)) {
2126 token = token.next;
2127 }
2128 listener.beginFunctionName(token);
2129 if (optional('operator', token)) {
2130 token = parseOperatorName(token);
2131 } else {
2132 token =
2133 parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
2134 }
2135 }
2136 token = parseQualifiedRestOpt( 2112 token = parseQualifiedRestOpt(
2137 token, IdentifierContext.localFunctionDeclarationContinuation); 2113 token, IdentifierContext.localFunctionDeclarationContinuation);
2138 listener.endFunctionName(beginToken, token); 2114 listener.endFunctionName(beginToken, token);
2139 if (getOrSet == null) { 2115 token = parseTypeVariablesOpt(token);
2140 token = parseTypeVariablesOpt(token); 2116 token = parseFormalParametersOpt(token, MemberKind.Local);
2141 } else {
2142 listener.handleNoTypeVariables(token);
2143 }
2144 token = parseFormalParametersOpt(token);
2145 token = parseInitializersOpt(token); 2117 token = parseInitializersOpt(token);
2146 AsyncModifier savedAsyncModifier = asyncState; 2118 AsyncModifier savedAsyncModifier = asyncState;
2147 token = parseAsyncModifier(token); 2119 token = parseAsyncModifier(token);
2148 token = parseFunctionBody(token, false, true); 2120 token = parseFunctionBody(token, false, true);
2149 asyncState = savedAsyncModifier; 2121 asyncState = savedAsyncModifier;
2150 listener.endFunction(getOrSet, token); 2122 listener.endFunction(null, token);
2151 return token.next; 2123 return token.next;
2152 } 2124 }
2153 2125
2154 Token parseUnnamedFunction(Token token) { 2126 Token parseUnnamedFunction(Token token) {
2155 Token beginToken = token; 2127 Token beginToken = token;
2156 listener.beginUnnamedFunction(token); 2128 listener.beginUnnamedFunction(token);
2157 token = parseFormalParameters(token); 2129 token = parseFormalParameters(token, MemberKind.Local);
2158 AsyncModifier savedAsyncModifier = asyncState; 2130 AsyncModifier savedAsyncModifier = asyncState;
2159 token = parseAsyncModifier(token); 2131 token = parseAsyncModifier(token);
2160 bool isBlock = optional('{', token); 2132 bool isBlock = optional('{', token);
2161 token = parseFunctionBody(token, true, false); 2133 token = parseFunctionBody(token, true, false);
2162 asyncState = savedAsyncModifier; 2134 asyncState = savedAsyncModifier;
2163 listener.endUnnamedFunction(beginToken, token); 2135 listener.endUnnamedFunction(beginToken, token);
2164 return isBlock ? token.next : token; 2136 return isBlock ? token.next : token;
2165 } 2137 }
2166 2138
2167 Token parseFunctionDeclaration(Token token) { 2139 Token parseFunctionDeclaration(Token token) {
2168 listener.beginFunctionDeclaration(token); 2140 listener.beginFunctionDeclaration(token);
2169 token = parseFunction(token, null); 2141 token = parseFunction(token);
2170 listener.endFunctionDeclaration(token); 2142 listener.endFunctionDeclaration(token);
2171 return token; 2143 return token;
2172 } 2144 }
2173 2145
2174 Token parseFunctionExpression(Token token) { 2146 Token parseFunctionExpression(Token token) {
2175 Token beginToken = token; 2147 Token beginToken = token;
2176 listener.beginFunction(token); 2148 listener.beginFunction(token);
2177 listener.handleModifiers(0); 2149 listener.handleModifiers(0);
2178 token = parseReturnTypeOpt(token); 2150 token = parseReturnTypeOpt(token);
2179 listener.beginFunctionName(token); 2151 listener.beginFunctionName(token);
2180 token = parseIdentifier(token, IdentifierContext.functionExpressionName); 2152 token = parseIdentifier(token, IdentifierContext.functionExpressionName);
2181 listener.endFunctionName(beginToken, token); 2153 listener.endFunctionName(beginToken, token);
2182 token = parseTypeVariablesOpt(token); 2154 token = parseTypeVariablesOpt(token);
2183 token = parseFormalParameters(token); 2155 token = parseFormalParameters(token, MemberKind.Local);
2184 listener.handleNoInitializers(); 2156 listener.handleNoInitializers();
2185 AsyncModifier savedAsyncModifier = asyncState; 2157 AsyncModifier savedAsyncModifier = asyncState;
2186 token = parseAsyncModifier(token); 2158 token = parseAsyncModifier(token);
2187 bool isBlock = optional('{', token); 2159 bool isBlock = optional('{', token);
2188 token = parseFunctionBody(token, true, false); 2160 token = parseFunctionBody(token, true, false);
2189 asyncState = savedAsyncModifier; 2161 asyncState = savedAsyncModifier;
2190 listener.endFunction(null, token); 2162 listener.endFunction(null, token);
2191 return isBlock ? token.next : token; 2163 return isBlock ? token.next : token;
2192 } 2164 }
2193 2165
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after
3413 return parseVariablesDeclarationMaybeSemicolon(token, false); 3385 return parseVariablesDeclarationMaybeSemicolon(token, false);
3414 } 3386 }
3415 3387
3416 Token parseVariablesDeclarationMaybeSemicolon( 3388 Token parseVariablesDeclarationMaybeSemicolon(
3417 Token token, bool endWithSemicolon) { 3389 Token token, bool endWithSemicolon) {
3418 int count = 1; 3390 int count = 1;
3419 token = parseMetadataStar(token); 3391 token = parseMetadataStar(token);
3420 3392
3421 // If the next token has a type substitution comment /*=T*/, then 3393 // If the next token has a type substitution comment /*=T*/, then
3422 // the current 'var' token should be repealed and replaced. 3394 // the current 'var' token should be repealed and replaced.
3423 if (identical('var', token.stringValue)) { 3395 if (optional('var', token)) {
3424 token = 3396 token =
3425 listener.replaceTokenWithGenericCommentTypeAssign(token, token.next); 3397 listener.replaceTokenWithGenericCommentTypeAssign(token, token.next);
3426 } 3398 }
3427 3399
3428 token = parseModifiers(token); 3400 token = parseModifiers(token, MemberKind.Local, isVariable: true);
3429 token = parseTypeOpt(token);
3430 listener.beginVariablesDeclaration(token); 3401 listener.beginVariablesDeclaration(token);
3431 token = parseOptionallyInitializedIdentifier(token); 3402 token = parseOptionallyInitializedIdentifier(token);
3432 while (optional(',', token)) { 3403 while (optional(',', token)) {
3433 token = parseOptionallyInitializedIdentifier(token.next); 3404 token = parseOptionallyInitializedIdentifier(token.next);
3434 ++count; 3405 ++count;
3435 } 3406 }
3436 if (endWithSemicolon) { 3407 if (endWithSemicolon) {
3437 Token semicolon = token; 3408 Token semicolon = token;
3438 token = expectSemicolon(semicolon); 3409 token = expectSemicolon(semicolon);
3439 listener.endVariablesDeclaration(count, semicolon); 3410 listener.endVariablesDeclaration(count, semicolon);
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
3641 if (identical(value, 'on')) { 3612 if (identical(value, 'on')) {
3642 // on qualified catchPart? 3613 // on qualified catchPart?
3643 onKeyword = token; 3614 onKeyword = token;
3644 token = parseType(token.next); 3615 token = parseType(token.next);
3645 value = token.stringValue; 3616 value = token.stringValue;
3646 } 3617 }
3647 Token catchKeyword = null; 3618 Token catchKeyword = null;
3648 if (identical(value, 'catch')) { 3619 if (identical(value, 'catch')) {
3649 catchKeyword = token; 3620 catchKeyword = token;
3650 // TODO(ahe): Validate the "parameters". 3621 // TODO(ahe): Validate the "parameters".
3651 token = parseFormalParameters(token.next); 3622 token = parseFormalParameters(token.next, MemberKind.Catch);
3652 } 3623 }
3653 listener.endCatchClause(token); 3624 listener.endCatchClause(token);
3654 token = parseBlock(token); 3625 token = parseBlock(token);
3655 ++catchCount; 3626 ++catchCount;
3656 listener.handleCatchBlock(onKeyword, catchKeyword); 3627 listener.handleCatchBlock(onKeyword, catchKeyword);
3657 value = token.stringValue; // while condition 3628 value = token.stringValue; // while condition
3658 } 3629 }
3659 3630
3660 Token finallyKeyword = null; 3631 Token finallyKeyword = null;
3661 if (optional('finally', token)) { 3632 if (optional('finally', token)) {
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
3917 return reportUnrecoverableError( 3888 return reportUnrecoverableError(
3918 token, () => code.format(uri, token.charOffset, string)); 3889 token, () => code.format(uri, token.charOffset, string));
3919 } 3890 }
3920 } 3891 }
3921 3892
3922 typedef FastaMessage NoArgument(Uri uri, int charOffset); 3893 typedef FastaMessage NoArgument(Uri uri, int charOffset);
3923 3894
3924 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); 3895 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token);
3925 3896
3926 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); 3897 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