OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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); |
OLD | NEW |