Chromium Code Reviews| 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; | 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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); |
| OLD | NEW |