| 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' |
| 8 show |
| 9 FastaCode, |
| 10 FastaMessage, |
| 11 codeAbstractNotSync, |
| 12 codeAsciiControlCharacter, |
| 13 codeAsyncAsIdentifier, |
| 14 codeAwaitAsIdentifier, |
| 15 codeAwaitForNotAsync, |
| 16 codeAwaitNotAsync, |
| 17 codeBuiltInIdentifierAsType, |
| 18 codeBuiltInIdentifierInDeclaration, |
| 19 codeEmptyNamedParameterList, |
| 20 codeEmptyOptionalParameterList, |
| 21 codeEncoding, |
| 22 codeExpectedBlockToSkip, |
| 23 codeExpectedBody, |
| 24 codeExpectedButGot, |
| 25 codeExpectedClassBody, |
| 26 codeExpectedClassBodyToSkip, |
| 27 codeExpectedDeclaration, |
| 28 codeExpectedExpression, |
| 29 codeExpectedFunctionBody, |
| 30 codeExpectedIdentifier, |
| 31 codeExpectedOpenParens, |
| 32 codeExpectedString, |
| 33 codeExpectedType, |
| 34 codeExtraneousModifier, |
| 35 codeExtraneousModifierReplace, |
| 36 codeFactoryNotSync, |
| 37 codeGeneratorReturnsValue, |
| 38 codeInvalidAwaitFor, |
| 39 codeInvalidInlineFunctionType, |
| 40 codeInvalidSyncModifier, |
| 41 codeInvalidVoid, |
| 42 codeNonAsciiIdentifier, |
| 43 codeNonAsciiWhitespace, |
| 44 codeOnlyTry, |
| 45 codePositionalParameterWithEquals, |
| 46 codeRequiredParameterWithDefault, |
| 47 codeSetterNotSync, |
| 48 codeStackOverflow, |
| 49 codeUnexpectedToken, |
| 50 codeUnmatchedToken, |
| 51 codeUnspecified, |
| 52 codeUnsupportedPrefixPlus, |
| 53 codeUnterminatedString, |
| 54 codeYieldAsIdentifier, |
| 55 codeYieldNotGenerator; |
| 56 |
| 7 import '../scanner.dart' show ErrorToken; | 57 import '../scanner.dart' show ErrorToken; |
| 8 | 58 |
| 9 import '../scanner/recover.dart' show closeBraceFor, skipToEof; | 59 import '../scanner/recover.dart' show closeBraceFor, skipToEof; |
| 10 | 60 |
| 11 import '../scanner/keyword.dart' show Keyword; | 61 import '../scanner/keyword.dart' show Keyword; |
| 12 | 62 |
| 13 import '../scanner/precedence.dart' | 63 import '../scanner/precedence.dart' |
| 14 show | 64 show |
| 15 ASSIGNMENT_PRECEDENCE, | 65 ASSIGNMENT_PRECEDENCE, |
| 16 AS_INFO, | 66 AS_INFO, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 STRING_TOKEN; | 113 STRING_TOKEN; |
| 64 | 114 |
| 65 import '../scanner/characters.dart' show $CLOSE_CURLY_BRACKET; | 115 import '../scanner/characters.dart' show $CLOSE_CURLY_BRACKET; |
| 66 | 116 |
| 67 import '../util/link.dart' show Link; | 117 import '../util/link.dart' show Link; |
| 68 | 118 |
| 69 import 'async_modifier.dart' show AsyncModifier; | 119 import 'async_modifier.dart' show AsyncModifier; |
| 70 | 120 |
| 71 import 'listener.dart' show Listener; | 121 import 'listener.dart' show Listener; |
| 72 | 122 |
| 73 import 'error_kind.dart' show ErrorKind; | |
| 74 | |
| 75 import 'identifier_context.dart' show IdentifierContext; | 123 import 'identifier_context.dart' show IdentifierContext; |
| 76 | 124 |
| 77 /// Returns true if [token] is the symbol or keyword [value]. | 125 /// Returns true if [token] is the symbol or keyword [value]. |
| 78 bool optional(String value, Token token) { | 126 bool optional(String value, Token token) { |
| 79 return identical(value, token.stringValue); | 127 return identical(value, token.stringValue); |
| 80 } | 128 } |
| 81 | 129 |
| 82 class FormalParameterType { | 130 class FormalParameterType { |
| 83 final String type; | 131 final String type; |
| 84 const FormalParameterType(this.type); | 132 const FormalParameterType(this.type); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 /// As a consequence of this, one should not use `==` to compare strings in the | 173 /// As a consequence of this, one should not use `==` to compare strings in the |
| 126 /// parser. One should favor the methods [optional] and [expected] to recognize | 174 /// parser. One should favor the methods [optional] and [expected] to recognize |
| 127 /// keywords or identifiers. In some cases, it's possible to compare a token's | 175 /// keywords or identifiers. In some cases, it's possible to compare a token's |
| 128 /// `stringValue` using [identical], but normally [optional] will suffice. | 176 /// `stringValue` using [identical], but normally [optional] will suffice. |
| 129 /// | 177 /// |
| 130 /// Historically, we over-used identical, and when identical is used on other | 178 /// Historically, we over-used identical, and when identical is used on other |
| 131 /// objects than strings, it can often be replaced by `==`. | 179 /// objects than strings, it can often be replaced by `==`. |
| 132 class Parser { | 180 class Parser { |
| 133 final Listener listener; | 181 final Listener listener; |
| 134 | 182 |
| 183 Uri get uri => listener.uri; |
| 184 |
| 135 bool mayParseFunctionExpressions = true; | 185 bool mayParseFunctionExpressions = true; |
| 136 | 186 |
| 137 /// Represents parser state: what asynchronous syntax is allowed in the | 187 /// Represents parser state: what asynchronous syntax is allowed in the |
| 138 /// function being currently parsed. In rare situations, this can be set by | 188 /// function being currently parsed. In rare situations, this can be set by |
| 139 /// external clients, for example, to parse an expression outside a function. | 189 /// external clients, for example, to parse an expression outside a function. |
| 140 AsyncModifier asyncState = AsyncModifier.Sync; | 190 AsyncModifier asyncState = AsyncModifier.Sync; |
| 141 | 191 |
| 142 Parser(this.listener); | 192 Parser(this.listener); |
| 143 | 193 |
| 144 bool get inGenerator { | 194 bool get inGenerator { |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 listener.handleNoFormalParameters(token); | 530 listener.handleNoFormalParameters(token); |
| 481 return token; | 531 return token; |
| 482 } | 532 } |
| 483 } | 533 } |
| 484 | 534 |
| 485 Token skipFormalParameters(Token token) { | 535 Token skipFormalParameters(Token token) { |
| 486 // TODO(ahe): Shouldn't this be `beginFormalParameters`? | 536 // TODO(ahe): Shouldn't this be `beginFormalParameters`? |
| 487 listener.beginOptionalFormalParameters(token); | 537 listener.beginOptionalFormalParameters(token); |
| 488 if (!optional('(', token)) { | 538 if (!optional('(', token)) { |
| 489 if (optional(';', token)) { | 539 if (optional(';', token)) { |
| 490 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); | 540 reportRecoverableErrorCode(token, codeExpectedOpenParens); |
| 491 return token; | 541 return token; |
| 492 } | 542 } |
| 493 return reportUnrecoverableError( | 543 return reportUnrecoverableErrorCodeWithString( |
| 494 token, ErrorKind.ExpectedButGot, {"expected": "("})?.next; | 544 token, codeExpectedButGot, "(") |
| 545 .next; |
| 495 } | 546 } |
| 496 BeginGroupToken beginGroupToken = token; | 547 BeginGroupToken beginGroupToken = token; |
| 497 Token endToken = beginGroupToken.endGroup; | 548 Token endToken = beginGroupToken.endGroup; |
| 498 listener.endFormalParameters(0, token, endToken); | 549 listener.endFormalParameters(0, token, endToken); |
| 499 return endToken.next; | 550 return endToken.next; |
| 500 } | 551 } |
| 501 | 552 |
| 502 /// Parses the formal parameter list of a function. | 553 /// Parses the formal parameter list of a function. |
| 503 /// | 554 /// |
| 504 /// If [inFunctionType] is true, then the names may be omitted (except for | 555 /// If [inFunctionType] is true, then the names may be omitted (except for |
| (...skipping 13 matching lines...) Expand all Loading... |
| 518 if (identical(value, '[')) { | 569 if (identical(value, '[')) { |
| 519 token = parseOptionalFormalParameters(token, false, | 570 token = parseOptionalFormalParameters(token, false, |
| 520 inFunctionType: inFunctionType); | 571 inFunctionType: inFunctionType); |
| 521 break; | 572 break; |
| 522 } else if (identical(value, '{')) { | 573 } else if (identical(value, '{')) { |
| 523 token = parseOptionalFormalParameters(token, true, | 574 token = parseOptionalFormalParameters(token, true, |
| 524 inFunctionType: inFunctionType); | 575 inFunctionType: inFunctionType); |
| 525 break; | 576 break; |
| 526 } else if (identical(value, '[]')) { | 577 } else if (identical(value, '[]')) { |
| 527 --parameterCount; | 578 --parameterCount; |
| 528 reportRecoverableError(token, ErrorKind.EmptyOptionalParameterList); | 579 reportRecoverableErrorCode(token, codeEmptyOptionalParameterList); |
| 529 token = token.next; | 580 token = token.next; |
| 530 break; | 581 break; |
| 531 } | 582 } |
| 532 token = parseFormalParameter(token, FormalParameterType.REQUIRED, | 583 token = parseFormalParameter(token, FormalParameterType.REQUIRED, |
| 533 inFunctionType: inFunctionType); | 584 inFunctionType: inFunctionType); |
| 534 } while (optional(',', token)); | 585 } while (optional(',', token)); |
| 535 listener.endFormalParameters(parameterCount, begin, token); | 586 listener.endFormalParameters(parameterCount, begin, token); |
| 536 return expect(')', token); | 587 return expect(')', token); |
| 537 } | 588 } |
| 538 | 589 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 Token inlineFunctionTypeStart = token; | 637 Token inlineFunctionTypeStart = token; |
| 587 listener.beginFunctionTypedFormalParameter(token); | 638 listener.beginFunctionTypedFormalParameter(token); |
| 588 listener.handleNoTypeVariables(token); | 639 listener.handleNoTypeVariables(token); |
| 589 token = parseFormalParameters(token); | 640 token = parseFormalParameters(token); |
| 590 listener.endFunctionTypedFormalParameter( | 641 listener.endFunctionTypedFormalParameter( |
| 591 covariantKeyword, thisKeyword, kind); | 642 covariantKeyword, thisKeyword, kind); |
| 592 // Generalized function types don't allow inline function types. | 643 // Generalized function types don't allow inline function types. |
| 593 // The following isn't allowed: | 644 // The following isn't allowed: |
| 594 // int Function(int bar(String x)). | 645 // int Function(int bar(String x)). |
| 595 if (inFunctionType) { | 646 if (inFunctionType) { |
| 596 reportRecoverableError( | 647 reportRecoverableErrorCode( |
| 597 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType); | 648 inlineFunctionTypeStart, codeInvalidInlineFunctionType); |
| 598 } | 649 } |
| 599 } else if (optional('<', token)) { | 650 } else if (optional('<', token)) { |
| 600 Token inlineFunctionTypeStart = token; | 651 Token inlineFunctionTypeStart = token; |
| 601 listener.beginFunctionTypedFormalParameter(token); | 652 listener.beginFunctionTypedFormalParameter(token); |
| 602 token = parseTypeVariablesOpt(token); | 653 token = parseTypeVariablesOpt(token); |
| 603 token = parseFormalParameters(token); | 654 token = parseFormalParameters(token); |
| 604 listener.endFunctionTypedFormalParameter( | 655 listener.endFunctionTypedFormalParameter( |
| 605 covariantKeyword, thisKeyword, kind); | 656 covariantKeyword, thisKeyword, kind); |
| 606 // Generalized function types don't allow inline function types. | 657 // Generalized function types don't allow inline function types. |
| 607 // The following isn't allowed: | 658 // The following isn't allowed: |
| 608 // int Function(int bar(String x)). | 659 // int Function(int bar(String x)). |
| 609 if (inFunctionType) { | 660 if (inFunctionType) { |
| 610 reportRecoverableError( | 661 reportRecoverableErrorCode( |
| 611 inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType); | 662 inlineFunctionTypeStart, codeInvalidInlineFunctionType); |
| 612 } | 663 } |
| 613 } | 664 } |
| 614 String value = token.stringValue; | 665 String value = token.stringValue; |
| 615 if ((identical('=', value)) || (identical(':', value))) { | 666 if ((identical('=', value)) || (identical(':', value))) { |
| 616 // TODO(ahe): Validate that these are only used for optional parameters. | 667 // TODO(ahe): Validate that these are only used for optional parameters. |
| 617 Token equal = token; | 668 Token equal = token; |
| 618 token = parseExpression(token.next); | 669 token = parseExpression(token.next); |
| 619 listener.handleValuedFormalParameter(equal, token); | 670 listener.handleValuedFormalParameter(equal, token); |
| 620 if (kind.isRequired) { | 671 if (kind.isRequired) { |
| 621 reportRecoverableError(equal, ErrorKind.RequiredParameterWithDefault); | 672 reportRecoverableErrorCode(equal, codeRequiredParameterWithDefault); |
| 622 } else if (kind.isPositional && identical(':', value)) { | 673 } else if (kind.isPositional && identical(':', value)) { |
| 623 reportRecoverableError(equal, ErrorKind.PositionalParameterWithEquals); | 674 reportRecoverableErrorCode(equal, codePositionalParameterWithEquals); |
| 624 } | 675 } |
| 625 } else { | 676 } else { |
| 626 listener.handleFormalParameterWithoutValue(token); | 677 listener.handleFormalParameterWithoutValue(token); |
| 627 } | 678 } |
| 628 listener.endFormalParameter(covariantKeyword, thisKeyword, nameToken, kind); | 679 listener.endFormalParameter(covariantKeyword, thisKeyword, nameToken, kind); |
| 629 return token; | 680 return token; |
| 630 } | 681 } |
| 631 | 682 |
| 632 Token parseOptionalFormalParameters(Token token, bool isNamed, | 683 Token parseOptionalFormalParameters(Token token, bool isNamed, |
| 633 {bool inFunctionType: false}) { | 684 {bool inFunctionType: false}) { |
| 634 Token begin = token; | 685 Token begin = token; |
| 635 listener.beginOptionalFormalParameters(begin); | 686 listener.beginOptionalFormalParameters(begin); |
| 636 assert((isNamed && optional('{', token)) || optional('[', token)); | 687 assert((isNamed && optional('{', token)) || optional('[', token)); |
| 637 int parameterCount = 0; | 688 int parameterCount = 0; |
| 638 do { | 689 do { |
| 639 token = token.next; | 690 token = token.next; |
| 640 if (isNamed && optional('}', token)) { | 691 if (isNamed && optional('}', token)) { |
| 641 break; | 692 break; |
| 642 } else if (!isNamed && optional(']', token)) { | 693 } else if (!isNamed && optional(']', token)) { |
| 643 break; | 694 break; |
| 644 } | 695 } |
| 645 var type = | 696 var type = |
| 646 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 697 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
| 647 token = parseFormalParameter(token, type, inFunctionType: inFunctionType); | 698 token = parseFormalParameter(token, type, inFunctionType: inFunctionType); |
| 648 ++parameterCount; | 699 ++parameterCount; |
| 649 } while (optional(',', token)); | 700 } while (optional(',', token)); |
| 650 if (parameterCount == 0) { | 701 if (parameterCount == 0) { |
| 651 reportRecoverableError( | 702 reportRecoverableErrorCode( |
| 652 token, | 703 token, |
| 653 isNamed | 704 isNamed |
| 654 ? ErrorKind.EmptyNamedParameterList | 705 ? codeEmptyNamedParameterList |
| 655 : ErrorKind.EmptyOptionalParameterList); | 706 : codeEmptyOptionalParameterList); |
| 656 } | 707 } |
| 657 listener.endOptionalFormalParameters(parameterCount, begin, token); | 708 listener.endOptionalFormalParameters(parameterCount, begin, token); |
| 658 if (isNamed) { | 709 if (isNamed) { |
| 659 return expect('}', token); | 710 return expect('}', token); |
| 660 } else { | 711 } else { |
| 661 return expect(']', token); | 712 return expect(']', token); |
| 662 } | 713 } |
| 663 } | 714 } |
| 664 | 715 |
| 665 Token parseTypeOpt(Token token) { | 716 Token parseTypeOpt(Token token) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 Token parseQualifiedRest(Token token, IdentifierContext context) { | 835 Token parseQualifiedRest(Token token, IdentifierContext context) { |
| 785 assert(optional('.', token)); | 836 assert(optional('.', token)); |
| 786 Token period = token; | 837 Token period = token; |
| 787 token = parseIdentifier(token.next, context); | 838 token = parseIdentifier(token.next, context); |
| 788 listener.handleQualified(period); | 839 listener.handleQualified(period); |
| 789 return token; | 840 return token; |
| 790 } | 841 } |
| 791 | 842 |
| 792 Token skipBlock(Token token) { | 843 Token skipBlock(Token token) { |
| 793 if (!optional('{', token)) { | 844 if (!optional('{', token)) { |
| 794 return reportUnrecoverableError(token, ErrorKind.ExpectedBlockToSkip) | 845 return reportUnrecoverableErrorCode(token, codeExpectedBlockToSkip).next; |
| 795 ?.next; | |
| 796 } | 846 } |
| 797 BeginGroupToken beginGroupToken = token; | 847 BeginGroupToken beginGroupToken = token; |
| 798 Token endGroup = beginGroupToken.endGroup; | 848 Token endGroup = beginGroupToken.endGroup; |
| 799 if (endGroup == null) { | 849 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
| 800 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) | 850 return reportUnmatchedToken(beginGroupToken).next; |
| 801 ?.next; | |
| 802 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | |
| 803 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) | |
| 804 ?.next; | |
| 805 } | 851 } |
| 806 return beginGroupToken.endGroup; | 852 return beginGroupToken.endGroup; |
| 807 } | 853 } |
| 808 | 854 |
| 809 Token parseEnum(Token token) { | 855 Token parseEnum(Token token) { |
| 810 listener.beginEnum(token); | 856 listener.beginEnum(token); |
| 811 Token enumKeyword = token; | 857 Token enumKeyword = token; |
| 812 token = parseIdentifier(token.next, IdentifierContext.enumDeclaration); | 858 token = parseIdentifier(token.next, IdentifierContext.enumDeclaration); |
| 813 token = expect('{', token); | 859 token = expect('{', token); |
| 814 int count = 0; | 860 int count = 0; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 } while (optional(',', token)); | 949 } while (optional(',', token)); |
| 904 } | 950 } |
| 905 token = parseClassBody(token); | 951 token = parseClassBody(token); |
| 906 listener.endClassDeclaration(interfacesCount, begin, classKeyword, | 952 listener.endClassDeclaration(interfacesCount, begin, classKeyword, |
| 907 extendsKeyword, implementsKeyword, token); | 953 extendsKeyword, implementsKeyword, token); |
| 908 return token.next; | 954 return token.next; |
| 909 } | 955 } |
| 910 | 956 |
| 911 Token parseStringPart(Token token) { | 957 Token parseStringPart(Token token) { |
| 912 if (token.kind != STRING_TOKEN) { | 958 if (token.kind != STRING_TOKEN) { |
| 913 token = reportUnrecoverableError(token, ErrorKind.ExpectedString)?.next; | 959 token = |
| 960 reportUnrecoverableErrorCodeWithToken(token, codeExpectedString).next; |
| 914 } | 961 } |
| 915 listener.handleStringPart(token); | 962 listener.handleStringPart(token); |
| 916 return token.next; | 963 return token.next; |
| 917 } | 964 } |
| 918 | 965 |
| 919 Token parseIdentifier(Token token, IdentifierContext context) { | 966 Token parseIdentifier(Token token, IdentifierContext context) { |
| 920 if (!token.isIdentifier()) { | 967 if (!token.isIdentifier()) { |
| 921 token = | 968 token = |
| 922 reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier)?.next; | 969 reportUnrecoverableErrorCodeWithToken(token, codeExpectedIdentifier) |
| 970 .next; |
| 923 } else if (token.isBuiltInIdentifier && | 971 } else if (token.isBuiltInIdentifier && |
| 924 !context.isBuiltInIdentifierAllowed) { | 972 !context.isBuiltInIdentifierAllowed) { |
| 925 if (context.inDeclaration) { | 973 if (context.inDeclaration) { |
| 926 reportRecoverableError(token, ErrorKind.BuiltInIdentifierInDeclaration); | 974 reportRecoverableErrorCodeWithToken( |
| 975 token, codeBuiltInIdentifierInDeclaration); |
| 927 } else if (!optional("dynamic", token)) { | 976 } else if (!optional("dynamic", token)) { |
| 928 reportRecoverableError(token, ErrorKind.BuiltInIdentifierAsType); | 977 reportRecoverableErrorCodeWithToken(token, codeBuiltInIdentifierAsType); |
| 929 } | 978 } |
| 930 } else if (!inPlainSync && token.isPseudo) { | 979 } else if (!inPlainSync && token.isPseudo) { |
| 931 if (optional('await', token)) { | 980 if (optional('await', token)) { |
| 932 reportRecoverableError(token, ErrorKind.AwaitAsIdentifier); | 981 reportRecoverableErrorCode(token, codeAwaitAsIdentifier); |
| 933 } else if (optional('yield', token)) { | 982 } else if (optional('yield', token)) { |
| 934 reportRecoverableError(token, ErrorKind.YieldAsIdentifier); | 983 reportRecoverableErrorCode(token, codeYieldAsIdentifier); |
| 935 } else if (optional('async', token)) { | 984 } else if (optional('async', token)) { |
| 936 reportRecoverableError(token, ErrorKind.AsyncAsIdentifier); | 985 reportRecoverableErrorCode(token, codeAsyncAsIdentifier); |
| 937 } | 986 } |
| 938 } | 987 } |
| 939 listener.handleIdentifier(token, context); | 988 listener.handleIdentifier(token, context); |
| 940 return token.next; | 989 return token.next; |
| 941 } | 990 } |
| 942 | 991 |
| 943 Token expect(String string, Token token) { | 992 Token expect(String string, Token token) { |
| 944 if (!identical(string, token.stringValue)) { | 993 if (!identical(string, token.stringValue)) { |
| 945 return reportUnrecoverableError( | 994 return reportUnrecoverableErrorCodeWithString( |
| 946 token, ErrorKind.ExpectedButGot, {"expected": string})?.next; | 995 token, codeExpectedButGot, string) |
| 996 .next; |
| 947 } | 997 } |
| 948 return token.next; | 998 return token.next; |
| 949 } | 999 } |
| 950 | 1000 |
| 951 Token parseTypeVariable(Token token) { | 1001 Token parseTypeVariable(Token token) { |
| 952 listener.beginTypeVariable(token); | 1002 listener.beginTypeVariable(token); |
| 953 token = parseMetadataStar(token); | 1003 token = parseMetadataStar(token); |
| 954 token = parseIdentifier(token, IdentifierContext.typeVariableDeclaration); | 1004 token = parseIdentifier(token, IdentifierContext.typeVariableDeclaration); |
| 955 Token extendsOrSuper = null; | 1005 Token extendsOrSuper = null; |
| 956 if (optional('extends', token) || optional('super', token)) { | 1006 if (optional('extends', token) || optional('super', token)) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1003 } else if (identical(token.stringValue, 'void') && | 1053 } else if (identical(token.stringValue, 'void') && |
| 1004 isGeneralizedFunctionType(token.next)) { | 1054 isGeneralizedFunctionType(token.next)) { |
| 1005 listener.handleVoidKeyword(token); | 1055 listener.handleVoidKeyword(token); |
| 1006 token = token.next; | 1056 token = token.next; |
| 1007 } else { | 1057 } else { |
| 1008 if (isValidTypeReference(token)) { | 1058 if (isValidTypeReference(token)) { |
| 1009 token = parseIdentifier(token, IdentifierContext.typeReference); | 1059 token = parseIdentifier(token, IdentifierContext.typeReference); |
| 1010 token = parseQualifiedRestOpt( | 1060 token = parseQualifiedRestOpt( |
| 1011 token, IdentifierContext.typeReferenceContinuation); | 1061 token, IdentifierContext.typeReferenceContinuation); |
| 1012 } else { | 1062 } else { |
| 1013 token = reportUnrecoverableError(token, ErrorKind.ExpectedType)?.next; | 1063 token = |
| 1064 reportUnrecoverableErrorCodeWithToken(token, codeExpectedType).next; |
| 1014 listener.handleInvalidTypeReference(token); | 1065 listener.handleInvalidTypeReference(token); |
| 1015 } | 1066 } |
| 1016 token = parseTypeArgumentsOpt(token); | 1067 token = parseTypeArgumentsOpt(token); |
| 1017 listener.handleType(begin, token); | 1068 listener.handleType(begin, token); |
| 1018 } | 1069 } |
| 1019 | 1070 |
| 1020 // While we see a `Function(` treat the pushed type as return type. | 1071 // While we see a `Function(` treat the pushed type as return type. |
| 1021 // For example: `int Function() Function(int) Function(String x)`. | 1072 // For example: `int Function() Function(int) Function(String x)`. |
| 1022 while (isGeneralizedFunctionType(token)) { | 1073 while (isGeneralizedFunctionType(token)) { |
| 1023 token = parseFunctionType(token); | 1074 token = parseFunctionType(token); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 handleNoStuff(token); | 1130 handleNoStuff(token); |
| 1080 return token; | 1131 return token; |
| 1081 } | 1132 } |
| 1082 | 1133 |
| 1083 Token parseTopLevelMember(Token token) { | 1134 Token parseTopLevelMember(Token token) { |
| 1084 Token start = token; | 1135 Token start = token; |
| 1085 listener.beginTopLevelMember(token); | 1136 listener.beginTopLevelMember(token); |
| 1086 | 1137 |
| 1087 Link<Token> identifiers = findMemberName(token); | 1138 Link<Token> identifiers = findMemberName(token); |
| 1088 if (identifiers.isEmpty) { | 1139 if (identifiers.isEmpty) { |
| 1089 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) | 1140 return reportUnrecoverableErrorCodeWithToken( |
| 1090 ?.next; | 1141 start, codeExpectedDeclaration) |
| 1142 .next; |
| 1091 } | 1143 } |
| 1092 Token afterName = identifiers.head; | 1144 Token afterName = identifiers.head; |
| 1093 identifiers = identifiers.tail; | 1145 identifiers = identifiers.tail; |
| 1094 | 1146 |
| 1095 if (identifiers.isEmpty) { | 1147 if (identifiers.isEmpty) { |
| 1096 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) | 1148 return reportUnrecoverableErrorCodeWithToken( |
| 1097 ?.next; | 1149 start, codeExpectedDeclaration) |
| 1150 .next; |
| 1098 } | 1151 } |
| 1099 Token name = identifiers.head; | 1152 Token name = identifiers.head; |
| 1100 identifiers = identifiers.tail; | 1153 identifiers = identifiers.tail; |
| 1101 Token getOrSet; | 1154 Token getOrSet; |
| 1102 if (!identifiers.isEmpty) { | 1155 if (!identifiers.isEmpty) { |
| 1103 String value = identifiers.head.stringValue; | 1156 String value = identifiers.head.stringValue; |
| 1104 if ((identical(value, 'get')) || (identical(value, 'set'))) { | 1157 if ((identical(value, 'get')) || (identical(value, 'set'))) { |
| 1105 getOrSet = identifiers.head; | 1158 getOrSet = identifiers.head; |
| 1106 identifiers = identifiers.tail; | 1159 identifiers = identifiers.tail; |
| 1107 } | 1160 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1132 if (getOrSet != null) { | 1185 if (getOrSet != null) { |
| 1133 // If we found a "get" keyword, this must be an abstract | 1186 // If we found a "get" keyword, this must be an abstract |
| 1134 // getter. | 1187 // getter. |
| 1135 isField = (!identical(getOrSet.stringValue, 'get')); | 1188 isField = (!identical(getOrSet.stringValue, 'get')); |
| 1136 // TODO(ahe): This feels like a hack. | 1189 // TODO(ahe): This feels like a hack. |
| 1137 } else { | 1190 } else { |
| 1138 isField = true; | 1191 isField = true; |
| 1139 } | 1192 } |
| 1140 break; | 1193 break; |
| 1141 } else { | 1194 } else { |
| 1142 token = | 1195 token = reportUnexpectedToken(token).next; |
| 1143 reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; | |
| 1144 if (identical(token.kind, EOF_TOKEN)) return token; | 1196 if (identical(token.kind, EOF_TOKEN)) return token; |
| 1145 } | 1197 } |
| 1146 } | 1198 } |
| 1147 var modifiers = identifiers.reverse(); | 1199 var modifiers = identifiers.reverse(); |
| 1148 return isField | 1200 return isField |
| 1149 ? parseFields(start, modifiers, type, getOrSet, name, true) | 1201 ? parseFields(start, modifiers, type, getOrSet, name, true) |
| 1150 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); | 1202 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); |
| 1151 } | 1203 } |
| 1152 | 1204 |
| 1153 bool isVarFinalOrConst(Token token) { | 1205 bool isVarFinalOrConst(Token token) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 } | 1252 } |
| 1201 } | 1253 } |
| 1202 bool hasTypeOrModifier = hasType; | 1254 bool hasTypeOrModifier = hasType; |
| 1203 if (varFinalOrConst != null) { | 1255 if (varFinalOrConst != null) { |
| 1204 parseModifier(varFinalOrConst); | 1256 parseModifier(varFinalOrConst); |
| 1205 modifierCount++; | 1257 modifierCount++; |
| 1206 hasTypeOrModifier = true; | 1258 hasTypeOrModifier = true; |
| 1207 modifierList.remove(varFinalOrConst); | 1259 modifierList.remove(varFinalOrConst); |
| 1208 } | 1260 } |
| 1209 listener.handleModifiers(modifierCount); | 1261 listener.handleModifiers(modifierCount); |
| 1210 var kind = hasTypeOrModifier | |
| 1211 ? ErrorKind.ExtraneousModifier | |
| 1212 : ErrorKind.ExtraneousModifierReplace; | |
| 1213 for (Token modifier in modifierList) { | 1262 for (Token modifier in modifierList) { |
| 1214 reportRecoverableError(modifier, kind, {'modifier': modifier}); | 1263 reportRecoverableErrorCodeWithToken( |
| 1264 modifier, |
| 1265 hasTypeOrModifier |
| 1266 ? codeExtraneousModifier |
| 1267 : codeExtraneousModifierReplace); |
| 1215 } | 1268 } |
| 1216 return null; | 1269 return null; |
| 1217 } | 1270 } |
| 1218 | 1271 |
| 1219 /// Removes the optional `covariant` token from the modifiers, if there | 1272 /// Removes the optional `covariant` token from the modifiers, if there |
| 1220 /// is no `static` in the list, and `covariant` is the first modifier. | 1273 /// is no `static` in the list, and `covariant` is the first modifier. |
| 1221 Link<Token> removeOptCovariantTokenIfNotStatic(Link<Token> modifiers) { | 1274 Link<Token> removeOptCovariantTokenIfNotStatic(Link<Token> modifiers) { |
| 1222 if (modifiers.isEmpty || | 1275 if (modifiers.isEmpty || |
| 1223 !identical(modifiers.first.stringValue, 'covariant')) { | 1276 !identical(modifiers.first.stringValue, 'covariant')) { |
| 1224 return modifiers; | 1277 return modifiers; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1249 Token varFinalOrConst = | 1302 Token varFinalOrConst = |
| 1250 expectVarFinalOrConst(modifiers, hasType, !isTopLevel); | 1303 expectVarFinalOrConst(modifiers, hasType, !isTopLevel); |
| 1251 bool isVar = false; | 1304 bool isVar = false; |
| 1252 bool hasModifier = false; | 1305 bool hasModifier = false; |
| 1253 if (varFinalOrConst != null) { | 1306 if (varFinalOrConst != null) { |
| 1254 hasModifier = true; | 1307 hasModifier = true; |
| 1255 isVar = optional('var', varFinalOrConst); | 1308 isVar = optional('var', varFinalOrConst); |
| 1256 } | 1309 } |
| 1257 | 1310 |
| 1258 if (getOrSet != null) { | 1311 if (getOrSet != null) { |
| 1259 var kind = (hasModifier || hasType) | 1312 reportRecoverableErrorCodeWithToken( |
| 1260 ? ErrorKind.ExtraneousModifier | 1313 getOrSet, |
| 1261 : ErrorKind.ExtraneousModifierReplace; | 1314 hasModifier || hasType |
| 1262 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); | 1315 ? codeExtraneousModifier |
| 1316 : codeExtraneousModifierReplace); |
| 1263 } | 1317 } |
| 1264 | 1318 |
| 1265 if (!hasType) { | 1319 if (!hasType) { |
| 1266 listener.handleNoType(name); | 1320 listener.handleNoType(name); |
| 1267 } else if (optional('void', type) && | 1321 } else if (optional('void', type) && |
| 1268 !isGeneralizedFunctionType(type.next)) { | 1322 !isGeneralizedFunctionType(type.next)) { |
| 1269 listener.handleNoType(name); | 1323 listener.handleNoType(name); |
| 1270 // TODO(ahe): This error is reported twice, second time is from | 1324 // TODO(ahe): This error is reported twice, second time is from |
| 1271 // [parseVariablesDeclarationMaybeSemicolon] via | 1325 // [parseVariablesDeclarationMaybeSemicolon] via |
| 1272 // [PartialFieldListElement.parseNode]. | 1326 // [PartialFieldListElement.parseNode]. |
| 1273 reportRecoverableError(type, ErrorKind.InvalidVoid); | 1327 reportRecoverableErrorCode(type, codeInvalidVoid); |
| 1274 } else { | 1328 } else { |
| 1275 parseType(type); | 1329 parseType(type); |
| 1276 if (isVar) { | 1330 if (isVar) { |
| 1277 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, | 1331 reportRecoverableErrorCodeWithToken( |
| 1278 {'modifier': modifiers.head}); | 1332 modifiers.head, codeExtraneousModifier); |
| 1279 } | 1333 } |
| 1280 } | 1334 } |
| 1281 | 1335 |
| 1282 IdentifierContext context = isTopLevel | 1336 IdentifierContext context = isTopLevel |
| 1283 ? IdentifierContext.topLevelVariableDeclaration | 1337 ? IdentifierContext.topLevelVariableDeclaration |
| 1284 : IdentifierContext.fieldDeclaration; | 1338 : IdentifierContext.fieldDeclaration; |
| 1285 Token token = parseIdentifier(name, context); | 1339 Token token = parseIdentifier(name, context); |
| 1286 | 1340 |
| 1287 int fieldCount = 1; | 1341 int fieldCount = 1; |
| 1288 token = parseFieldInitializerOpt(token); | 1342 token = parseFieldInitializerOpt(token); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1304 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, | 1358 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, |
| 1305 Token getOrSet, Token name) { | 1359 Token getOrSet, Token name) { |
| 1306 listener.beginTopLevelMethod(start, name); | 1360 listener.beginTopLevelMethod(start, name); |
| 1307 Token externalModifier; | 1361 Token externalModifier; |
| 1308 // TODO(johnniwinther): Move error reporting to resolution to give more | 1362 // TODO(johnniwinther): Move error reporting to resolution to give more |
| 1309 // specific error messages. | 1363 // specific error messages. |
| 1310 for (Token modifier in modifiers) { | 1364 for (Token modifier in modifiers) { |
| 1311 if (externalModifier == null && optional('external', modifier)) { | 1365 if (externalModifier == null && optional('external', modifier)) { |
| 1312 externalModifier = modifier; | 1366 externalModifier = modifier; |
| 1313 } else { | 1367 } else { |
| 1314 reportRecoverableError( | 1368 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier); |
| 1315 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); | |
| 1316 } | 1369 } |
| 1317 } | 1370 } |
| 1318 if (externalModifier != null) { | 1371 if (externalModifier != null) { |
| 1319 parseModifier(externalModifier); | 1372 parseModifier(externalModifier); |
| 1320 listener.handleModifiers(1); | 1373 listener.handleModifiers(1); |
| 1321 } else { | 1374 } else { |
| 1322 listener.handleModifiers(0); | 1375 listener.handleModifiers(0); |
| 1323 } | 1376 } |
| 1324 | 1377 |
| 1325 if (type == null) { | 1378 if (type == null) { |
| 1326 listener.handleNoType(name); | 1379 listener.handleNoType(name); |
| 1327 } else { | 1380 } else { |
| 1328 parseReturnTypeOpt(type); | 1381 parseReturnTypeOpt(type); |
| 1329 } | 1382 } |
| 1330 Token token = | 1383 Token token = |
| 1331 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration); | 1384 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration); |
| 1332 | 1385 |
| 1333 if (getOrSet == null) { | 1386 if (getOrSet == null) { |
| 1334 token = parseTypeVariablesOpt(token); | 1387 token = parseTypeVariablesOpt(token); |
| 1335 } else { | 1388 } else { |
| 1336 listener.handleNoTypeVariables(token); | 1389 listener.handleNoTypeVariables(token); |
| 1337 } | 1390 } |
| 1338 token = parseFormalParametersOpt(token); | 1391 token = parseFormalParametersOpt(token); |
| 1339 AsyncModifier savedAsyncModifier = asyncState; | 1392 AsyncModifier savedAsyncModifier = asyncState; |
| 1340 Token asyncToken = token; | 1393 Token asyncToken = token; |
| 1341 token = parseAsyncModifier(token); | 1394 token = parseAsyncModifier(token); |
| 1342 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { | 1395 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { |
| 1343 reportRecoverableError(asyncToken, ErrorKind.SetterNotSync); | 1396 reportRecoverableErrorCode(asyncToken, codeSetterNotSync); |
| 1344 } | 1397 } |
| 1345 token = parseFunctionBody(token, false, externalModifier != null); | 1398 token = parseFunctionBody(token, false, externalModifier != null); |
| 1346 asyncState = savedAsyncModifier; | 1399 asyncState = savedAsyncModifier; |
| 1347 Token endToken = token; | 1400 Token endToken = token; |
| 1348 token = token.next; | 1401 token = token.next; |
| 1349 listener.endTopLevelMethod(start, getOrSet, endToken); | 1402 listener.endTopLevelMethod(start, getOrSet, endToken); |
| 1350 return token; | 1403 return token; |
| 1351 } | 1404 } |
| 1352 | 1405 |
| 1353 /// Looks ahead to find the name of a member. Returns a link of the modifiers, | 1406 /// Looks ahead to find the name of a member. Returns a link of the modifiers, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 // type '.' ... | 1480 // type '.' ... |
| 1428 if (token.next.next.isIdentifier()) { | 1481 if (token.next.next.isIdentifier()) { |
| 1429 // type '.' identifier | 1482 // type '.' identifier |
| 1430 token = token.next.next; | 1483 token = token.next.next; |
| 1431 } | 1484 } |
| 1432 } | 1485 } |
| 1433 if (optional('<', token.next)) { | 1486 if (optional('<', token.next)) { |
| 1434 if (token.next is BeginGroupToken) { | 1487 if (token.next is BeginGroupToken) { |
| 1435 BeginGroupToken beginGroup = token.next; | 1488 BeginGroupToken beginGroup = token.next; |
| 1436 if (beginGroup.endGroup == null) { | 1489 if (beginGroup.endGroup == null) { |
| 1437 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); | 1490 token = reportUnmatchedToken(beginGroup).next; |
| 1438 } else { | 1491 } else { |
| 1439 token = beginGroup.endGroup; | 1492 token = beginGroup.endGroup; |
| 1440 } | 1493 } |
| 1441 } | 1494 } |
| 1442 } | 1495 } |
| 1443 } | 1496 } |
| 1444 token = token.next; | 1497 token = token.next; |
| 1445 } | 1498 } |
| 1446 while (isGeneralizedFunctionType(token)) { | 1499 while (isGeneralizedFunctionType(token)) { |
| 1447 token = token.next; | 1500 token = token.next; |
| 1448 if (optional('<', token)) { | 1501 if (optional('<', token)) { |
| 1449 if (token is BeginGroupToken) { | 1502 if (token is BeginGroupToken) { |
| 1450 BeginGroupToken beginGroup = token; | 1503 BeginGroupToken beginGroup = token; |
| 1451 if (beginGroup.endGroup == null) { | 1504 if (beginGroup.endGroup == null) { |
| 1452 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); | 1505 token = reportUnmatchedToken(beginGroup).next; |
| 1453 } else { | 1506 } else { |
| 1454 token = beginGroup.endGroup.next; | 1507 token = beginGroup.endGroup.next; |
| 1455 } | 1508 } |
| 1456 } | 1509 } |
| 1457 } | 1510 } |
| 1458 if (!optional('(', token)) { | 1511 if (!optional('(', token)) { |
| 1459 if (optional(';', token)) { | 1512 if (optional(';', token)) { |
| 1460 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); | 1513 reportRecoverableErrorCode(token, codeExpectedOpenParens); |
| 1461 } | 1514 } |
| 1462 token = expect("(", token); | 1515 token = expect("(", token); |
| 1463 } | 1516 } |
| 1464 if (token is BeginGroupToken) { | 1517 if (token is BeginGroupToken) { |
| 1465 BeginGroupToken beginGroup = token; | 1518 BeginGroupToken beginGroup = token; |
| 1466 if (beginGroup.endGroup == null) { | 1519 if (beginGroup.endGroup == null) { |
| 1467 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); | 1520 token = reportUnmatchedToken(beginGroup).next; |
| 1468 } else { | 1521 } else { |
| 1469 token = beginGroup.endGroup.next; | 1522 token = beginGroup.endGroup.next; |
| 1470 } | 1523 } |
| 1471 } | 1524 } |
| 1472 } | 1525 } |
| 1473 } | 1526 } |
| 1474 return listener.handleMemberName(const Link<Token>()); | 1527 return listener.handleMemberName(const Link<Token>()); |
| 1475 } | 1528 } |
| 1476 | 1529 |
| 1477 Token parseFieldInitializerOpt(Token token) { | 1530 Token parseFieldInitializerOpt(Token token) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 } while (optional(',', token)); | 1576 } while (optional(',', token)); |
| 1524 mayParseFunctionExpressions = old; | 1577 mayParseFunctionExpressions = old; |
| 1525 listener.endInitializers(count, begin, token); | 1578 listener.endInitializers(count, begin, token); |
| 1526 return token; | 1579 return token; |
| 1527 } | 1580 } |
| 1528 | 1581 |
| 1529 Token parseLiteralStringOrRecoverExpression(Token token) { | 1582 Token parseLiteralStringOrRecoverExpression(Token token) { |
| 1530 if (identical(token.kind, STRING_TOKEN)) { | 1583 if (identical(token.kind, STRING_TOKEN)) { |
| 1531 return parseLiteralString(token); | 1584 return parseLiteralString(token); |
| 1532 } else { | 1585 } else { |
| 1533 reportRecoverableError(token, ErrorKind.ExpectedString); | 1586 reportRecoverableErrorCodeWithToken(token, codeExpectedString); |
| 1534 return parseRecoverExpression(token); | 1587 return parseRecoverExpression(token); |
| 1535 } | 1588 } |
| 1536 } | 1589 } |
| 1537 | 1590 |
| 1538 Token expectSemicolon(Token token) { | 1591 Token expectSemicolon(Token token) { |
| 1539 return expect(';', token); | 1592 return expect(';', token); |
| 1540 } | 1593 } |
| 1541 | 1594 |
| 1542 bool isModifier(Token token) { | 1595 bool isModifier(Token token) { |
| 1543 final String value = token.stringValue; | 1596 final String value = token.stringValue; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1555 return token.next; | 1608 return token.next; |
| 1556 } | 1609 } |
| 1557 | 1610 |
| 1558 void parseModifierList(Link<Token> tokens) { | 1611 void parseModifierList(Link<Token> tokens) { |
| 1559 int count = 0; | 1612 int count = 0; |
| 1560 for (; !tokens.isEmpty; tokens = tokens.tail) { | 1613 for (; !tokens.isEmpty; tokens = tokens.tail) { |
| 1561 Token token = tokens.head; | 1614 Token token = tokens.head; |
| 1562 if (isModifier(token)) { | 1615 if (isModifier(token)) { |
| 1563 parseModifier(token); | 1616 parseModifier(token); |
| 1564 } else { | 1617 } else { |
| 1565 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 1618 reportUnexpectedToken(token); |
| 1566 // Skip the remaining modifiers. | 1619 // Skip the remaining modifiers. |
| 1567 break; | 1620 break; |
| 1568 } | 1621 } |
| 1569 count++; | 1622 count++; |
| 1570 } | 1623 } |
| 1571 listener.handleModifiers(count); | 1624 listener.handleModifiers(count); |
| 1572 } | 1625 } |
| 1573 | 1626 |
| 1574 Token parseModifiers(Token token) { | 1627 Token parseModifiers(Token token) { |
| 1575 // TODO(ahe): The calling convention of this method probably needs to | 1628 // TODO(ahe): The calling convention of this method probably needs to |
| 1576 // change. For example, this is parsed as a local variable declaration: | 1629 // change. For example, this is parsed as a local variable declaration: |
| 1577 // `abstract foo;`. Ideally, this example should be handled as a local | 1630 // `abstract foo;`. Ideally, this example should be handled as a local |
| 1578 // variable having the type `abstract` (which should be reported as | 1631 // variable having the type `abstract` (which should be reported as |
| 1579 // `ErrorKind.BuiltInIdentifierAsType` by [parseIdentifier]). | 1632 // `codeBuiltInIdentifierAsType` by [parseIdentifier]). |
| 1580 int count = 0; | 1633 int count = 0; |
| 1581 while (identical(token.kind, KEYWORD_TOKEN)) { | 1634 while (identical(token.kind, KEYWORD_TOKEN)) { |
| 1582 if (!isModifier(token)) break; | 1635 if (!isModifier(token)) break; |
| 1583 token = parseModifier(token); | 1636 token = parseModifier(token); |
| 1584 count++; | 1637 count++; |
| 1585 } | 1638 } |
| 1586 listener.handleModifiers(count); | 1639 listener.handleModifiers(count); |
| 1587 return token; | 1640 return token; |
| 1588 } | 1641 } |
| 1589 | 1642 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1679 /// If [token] is not the start of a type, null is returned. | 1732 /// If [token] is not the start of a type, null is returned. |
| 1680 Token peekAfterIfType(Token token) { | 1733 Token peekAfterIfType(Token token) { |
| 1681 if (!optional('void', token) && !token.isIdentifier()) { | 1734 if (!optional('void', token) && !token.isIdentifier()) { |
| 1682 return null; | 1735 return null; |
| 1683 } | 1736 } |
| 1684 return peekAfterType(token); | 1737 return peekAfterType(token); |
| 1685 } | 1738 } |
| 1686 | 1739 |
| 1687 Token skipClassBody(Token token) { | 1740 Token skipClassBody(Token token) { |
| 1688 if (!optional('{', token)) { | 1741 if (!optional('{', token)) { |
| 1689 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip) | 1742 return reportUnrecoverableErrorCodeWithToken( |
| 1690 ?.next; | 1743 token, codeExpectedClassBodyToSkip) |
| 1744 .next; |
| 1691 } | 1745 } |
| 1692 BeginGroupToken beginGroupToken = token; | 1746 BeginGroupToken beginGroupToken = token; |
| 1693 Token endGroup = beginGroupToken.endGroup; | 1747 Token endGroup = beginGroupToken.endGroup; |
| 1694 if (endGroup == null) { | 1748 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
| 1695 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) | 1749 return reportUnmatchedToken(beginGroupToken).next; |
| 1696 ?.next; | |
| 1697 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | |
| 1698 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) | |
| 1699 ?.next; | |
| 1700 } | 1750 } |
| 1701 return endGroup; | 1751 return endGroup; |
| 1702 } | 1752 } |
| 1703 | 1753 |
| 1704 Token parseClassBody(Token token) { | 1754 Token parseClassBody(Token token) { |
| 1705 Token begin = token; | 1755 Token begin = token; |
| 1706 listener.beginClassBody(token); | 1756 listener.beginClassBody(token); |
| 1707 if (!optional('{', token)) { | 1757 if (!optional('{', token)) { |
| 1708 token = | 1758 token = |
| 1709 reportUnrecoverableError(token, ErrorKind.ExpectedClassBody)?.next; | 1759 reportUnrecoverableErrorCodeWithToken(token, codeExpectedClassBody) |
| 1760 .next; |
| 1710 } | 1761 } |
| 1711 token = token.next; | 1762 token = token.next; |
| 1712 int count = 0; | 1763 int count = 0; |
| 1713 while (notEofOrValue('}', token)) { | 1764 while (notEofOrValue('}', token)) { |
| 1714 token = parseMember(token); | 1765 token = parseMember(token); |
| 1715 ++count; | 1766 ++count; |
| 1716 } | 1767 } |
| 1717 expect('}', token); | 1768 expect('}', token); |
| 1718 listener.endClassBody(count, begin, token); | 1769 listener.endClassBody(count, begin, token); |
| 1719 return token; | 1770 return token; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1736 listener.beginMember(token); | 1787 listener.beginMember(token); |
| 1737 if (isFactoryDeclaration(token)) { | 1788 if (isFactoryDeclaration(token)) { |
| 1738 token = parseFactoryMethod(token); | 1789 token = parseFactoryMethod(token); |
| 1739 listener.endMember(); | 1790 listener.endMember(); |
| 1740 assert(token != null); | 1791 assert(token != null); |
| 1741 return token; | 1792 return token; |
| 1742 } | 1793 } |
| 1743 | 1794 |
| 1744 Link<Token> identifiers = findMemberName(token); | 1795 Link<Token> identifiers = findMemberName(token); |
| 1745 if (identifiers.isEmpty) { | 1796 if (identifiers.isEmpty) { |
| 1746 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) | 1797 return reportUnrecoverableErrorCodeWithToken( |
| 1747 ?.next; | 1798 start, codeExpectedDeclaration) |
| 1799 .next; |
| 1748 } | 1800 } |
| 1749 Token afterName = identifiers.head; | 1801 Token afterName = identifiers.head; |
| 1750 identifiers = identifiers.tail; | 1802 identifiers = identifiers.tail; |
| 1751 | 1803 |
| 1752 if (identifiers.isEmpty) { | 1804 if (identifiers.isEmpty) { |
| 1753 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) | 1805 return reportUnrecoverableErrorCodeWithToken( |
| 1754 ?.next; | 1806 start, codeExpectedDeclaration) |
| 1807 .next; |
| 1755 } | 1808 } |
| 1756 Token name = identifiers.head; | 1809 Token name = identifiers.head; |
| 1757 identifiers = identifiers.tail; | 1810 identifiers = identifiers.tail; |
| 1758 if (!identifiers.isEmpty) { | 1811 if (!identifiers.isEmpty) { |
| 1759 if (optional('operator', identifiers.head)) { | 1812 if (optional('operator', identifiers.head)) { |
| 1760 name = identifiers.head; | 1813 name = identifiers.head; |
| 1761 identifiers = identifiers.tail; | 1814 identifiers = identifiers.tail; |
| 1762 } | 1815 } |
| 1763 } | 1816 } |
| 1764 Token getOrSet; | 1817 Token getOrSet; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1796 isField = !optional("get", getOrSet); | 1849 isField = !optional("get", getOrSet); |
| 1797 // TODO(ahe): This feels like a hack. | 1850 // TODO(ahe): This feels like a hack. |
| 1798 } else { | 1851 } else { |
| 1799 isField = true; | 1852 isField = true; |
| 1800 } | 1853 } |
| 1801 break; | 1854 break; |
| 1802 } else if ((identical(value, '=')) || (identical(value, ','))) { | 1855 } else if ((identical(value, '=')) || (identical(value, ','))) { |
| 1803 isField = true; | 1856 isField = true; |
| 1804 break; | 1857 break; |
| 1805 } else { | 1858 } else { |
| 1806 token = | 1859 token = reportUnexpectedToken(token).next; |
| 1807 reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; | |
| 1808 if (identical(token.kind, EOF_TOKEN)) { | 1860 if (identical(token.kind, EOF_TOKEN)) { |
| 1809 // TODO(ahe): This is a hack, see parseTopLevelMember. | 1861 // TODO(ahe): This is a hack, see parseTopLevelMember. |
| 1810 listener.endFields(1, null, start, token); | 1862 listener.endFields(1, null, start, token); |
| 1811 listener.endMember(); | 1863 listener.endMember(); |
| 1812 return token; | 1864 return token; |
| 1813 } | 1865 } |
| 1814 } | 1866 } |
| 1815 } | 1867 } |
| 1816 | 1868 |
| 1817 var modifiers = identifiers.reverse(); | 1869 var modifiers = identifiers.reverse(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1830 Token constModifier; | 1882 Token constModifier; |
| 1831 int modifierCount = 0; | 1883 int modifierCount = 0; |
| 1832 int allowedModifierCount = 1; | 1884 int allowedModifierCount = 1; |
| 1833 // TODO(johnniwinther): Move error reporting to resolution to give more | 1885 // TODO(johnniwinther): Move error reporting to resolution to give more |
| 1834 // specific error messages. | 1886 // specific error messages. |
| 1835 for (Token modifier in modifiers) { | 1887 for (Token modifier in modifiers) { |
| 1836 if (externalModifier == null && optional('external', modifier)) { | 1888 if (externalModifier == null && optional('external', modifier)) { |
| 1837 modifierCount++; | 1889 modifierCount++; |
| 1838 externalModifier = modifier; | 1890 externalModifier = modifier; |
| 1839 if (modifierCount != allowedModifierCount) { | 1891 if (modifierCount != allowedModifierCount) { |
| 1840 reportRecoverableError( | 1892 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier); |
| 1841 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); | |
| 1842 } | 1893 } |
| 1843 allowedModifierCount++; | 1894 allowedModifierCount++; |
| 1844 } else if (staticModifier == null && optional('static', modifier)) { | 1895 } else if (staticModifier == null && optional('static', modifier)) { |
| 1845 modifierCount++; | 1896 modifierCount++; |
| 1846 staticModifier = modifier; | 1897 staticModifier = modifier; |
| 1847 if (modifierCount != allowedModifierCount) { | 1898 if (modifierCount != allowedModifierCount) { |
| 1848 reportRecoverableError( | 1899 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier); |
| 1849 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); | |
| 1850 } | 1900 } |
| 1851 } else if (constModifier == null && optional('const', modifier)) { | 1901 } else if (constModifier == null && optional('const', modifier)) { |
| 1852 modifierCount++; | 1902 modifierCount++; |
| 1853 constModifier = modifier; | 1903 constModifier = modifier; |
| 1854 if (modifierCount != allowedModifierCount) { | 1904 if (modifierCount != allowedModifierCount) { |
| 1855 reportRecoverableError( | 1905 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier); |
| 1856 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); | |
| 1857 } | 1906 } |
| 1858 } else { | 1907 } else { |
| 1859 reportRecoverableError( | 1908 reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier); |
| 1860 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); | |
| 1861 } | 1909 } |
| 1862 } | 1910 } |
| 1863 if (getOrSet != null && constModifier != null) { | 1911 if (getOrSet != null && constModifier != null) { |
| 1864 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier, | 1912 reportRecoverableErrorCodeWithToken( |
| 1865 {'modifier': constModifier}); | 1913 constModifier, codeExtraneousModifier); |
| 1866 } | 1914 } |
| 1867 parseModifierList(modifiers); | 1915 parseModifierList(modifiers); |
| 1868 | 1916 |
| 1869 if (type == null) { | 1917 if (type == null) { |
| 1870 listener.handleNoType(name); | 1918 listener.handleNoType(name); |
| 1871 } else { | 1919 } else { |
| 1872 parseReturnTypeOpt(type); | 1920 parseReturnTypeOpt(type); |
| 1873 } | 1921 } |
| 1874 Token token; | 1922 Token token; |
| 1875 if (optional('operator', name)) { | 1923 if (optional('operator', name)) { |
| 1876 token = parseOperatorName(name); | 1924 token = parseOperatorName(name); |
| 1877 if (staticModifier != null) { | 1925 if (staticModifier != null) { |
| 1878 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier, | 1926 reportRecoverableErrorCodeWithToken( |
| 1879 {'modifier': staticModifier}); | 1927 staticModifier, codeExtraneousModifier); |
| 1880 } | 1928 } |
| 1881 } else { | 1929 } else { |
| 1882 token = parseIdentifier(name, IdentifierContext.methodDeclaration); | 1930 token = parseIdentifier(name, IdentifierContext.methodDeclaration); |
| 1883 } | 1931 } |
| 1884 | 1932 |
| 1885 token = parseQualifiedRestOpt( | 1933 token = parseQualifiedRestOpt( |
| 1886 token, IdentifierContext.methodDeclarationContinuation); | 1934 token, IdentifierContext.methodDeclarationContinuation); |
| 1887 if (getOrSet == null) { | 1935 if (getOrSet == null) { |
| 1888 token = parseTypeVariablesOpt(token); | 1936 token = parseTypeVariablesOpt(token); |
| 1889 } else { | 1937 } else { |
| 1890 listener.handleNoTypeVariables(token); | 1938 listener.handleNoTypeVariables(token); |
| 1891 } | 1939 } |
| 1892 token = parseFormalParametersOpt(token); | 1940 token = parseFormalParametersOpt(token); |
| 1893 token = parseInitializersOpt(token); | 1941 token = parseInitializersOpt(token); |
| 1894 AsyncModifier savedAsyncModifier = asyncState; | 1942 AsyncModifier savedAsyncModifier = asyncState; |
| 1895 Token asyncToken = token; | 1943 Token asyncToken = token; |
| 1896 token = parseAsyncModifier(token); | 1944 token = parseAsyncModifier(token); |
| 1897 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { | 1945 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { |
| 1898 reportRecoverableError(asyncToken, ErrorKind.SetterNotSync); | 1946 reportRecoverableErrorCode(asyncToken, codeSetterNotSync); |
| 1899 } | 1947 } |
| 1900 if (optional('=', token)) { | 1948 if (optional('=', token)) { |
| 1901 token = parseRedirectingFactoryBody(token); | 1949 token = parseRedirectingFactoryBody(token); |
| 1902 } else { | 1950 } else { |
| 1903 token = parseFunctionBody( | 1951 token = parseFunctionBody( |
| 1904 token, false, staticModifier == null || externalModifier != null); | 1952 token, false, staticModifier == null || externalModifier != null); |
| 1905 } | 1953 } |
| 1906 asyncState = savedAsyncModifier; | 1954 asyncState = savedAsyncModifier; |
| 1907 listener.endMethod(getOrSet, start, token); | 1955 listener.endMethod(getOrSet, start, token); |
| 1908 return token.next; | 1956 return token.next; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1922 } | 1970 } |
| 1923 listener.handleModifiers(modifierCount); | 1971 listener.handleModifiers(modifierCount); |
| 1924 Token factoryKeyword = token; | 1972 Token factoryKeyword = token; |
| 1925 listener.beginFactoryMethod(factoryKeyword); | 1973 listener.beginFactoryMethod(factoryKeyword); |
| 1926 token = expect('factory', token); | 1974 token = expect('factory', token); |
| 1927 token = parseConstructorReference(token); | 1975 token = parseConstructorReference(token); |
| 1928 token = parseFormalParameters(token); | 1976 token = parseFormalParameters(token); |
| 1929 Token asyncToken = token; | 1977 Token asyncToken = token; |
| 1930 token = parseAsyncModifier(token); | 1978 token = parseAsyncModifier(token); |
| 1931 if (!inPlainSync) { | 1979 if (!inPlainSync) { |
| 1932 reportRecoverableError(asyncToken, ErrorKind.FactoryNotSync); | 1980 reportRecoverableErrorCode(asyncToken, codeFactoryNotSync); |
| 1933 } | 1981 } |
| 1934 if (optional('=', token)) { | 1982 if (optional('=', token)) { |
| 1935 token = parseRedirectingFactoryBody(token); | 1983 token = parseRedirectingFactoryBody(token); |
| 1936 } else { | 1984 } else { |
| 1937 token = parseFunctionBody(token, false, isExternal); | 1985 token = parseFunctionBody(token, false, isExternal); |
| 1938 } | 1986 } |
| 1939 listener.endFactoryMethod(start, factoryKeyword, token); | 1987 listener.endFactoryMethod(start, factoryKeyword, token); |
| 1940 return token.next; | 1988 return token.next; |
| 1941 } | 1989 } |
| 1942 | 1990 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 listener.endRedirectingFactoryBody(equals, semicolon); | 2122 listener.endRedirectingFactoryBody(equals, semicolon); |
| 2075 return token; | 2123 return token; |
| 2076 } | 2124 } |
| 2077 | 2125 |
| 2078 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 2126 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
| 2079 assert(!isExpression); | 2127 assert(!isExpression); |
| 2080 token = skipAsyncModifier(token); | 2128 token = skipAsyncModifier(token); |
| 2081 String value = token.stringValue; | 2129 String value = token.stringValue; |
| 2082 if (identical(value, ';')) { | 2130 if (identical(value, ';')) { |
| 2083 if (!allowAbstract) { | 2131 if (!allowAbstract) { |
| 2084 reportRecoverableError(token, ErrorKind.ExpectedBody); | 2132 reportRecoverableErrorCode(token, codeExpectedBody); |
| 2085 } | 2133 } |
| 2086 listener.handleNoFunctionBody(token); | 2134 listener.handleNoFunctionBody(token); |
| 2087 } else { | 2135 } else { |
| 2088 if (identical(value, '=>')) { | 2136 if (identical(value, '=>')) { |
| 2089 token = parseExpression(token.next); | 2137 token = parseExpression(token.next); |
| 2090 expectSemicolon(token); | 2138 expectSemicolon(token); |
| 2091 listener.handleFunctionBodySkipped(token, true); | 2139 listener.handleFunctionBodySkipped(token, true); |
| 2092 } else if (identical(value, '=')) { | 2140 } else if (identical(value, '=')) { |
| 2093 reportRecoverableError(token, ErrorKind.ExpectedBody); | 2141 reportRecoverableErrorCode(token, codeExpectedBody); |
| 2094 token = parseExpression(token.next); | 2142 token = parseExpression(token.next); |
| 2095 expectSemicolon(token); | 2143 expectSemicolon(token); |
| 2096 listener.handleFunctionBodySkipped(token, true); | 2144 listener.handleFunctionBodySkipped(token, true); |
| 2097 } else { | 2145 } else { |
| 2098 token = skipBlock(token); | 2146 token = skipBlock(token); |
| 2099 listener.handleFunctionBodySkipped(token, false); | 2147 listener.handleFunctionBodySkipped(token, false); |
| 2100 } | 2148 } |
| 2101 } | 2149 } |
| 2102 return token; | 2150 return token; |
| 2103 } | 2151 } |
| 2104 | 2152 |
| 2105 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 2153 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
| 2106 if (optional(';', token)) { | 2154 if (optional(';', token)) { |
| 2107 if (!allowAbstract) { | 2155 if (!allowAbstract) { |
| 2108 reportRecoverableError(token, ErrorKind.ExpectedBody); | 2156 reportRecoverableErrorCode(token, codeExpectedBody); |
| 2109 } | 2157 } |
| 2110 listener.handleEmptyFunctionBody(token); | 2158 listener.handleEmptyFunctionBody(token); |
| 2111 return token; | 2159 return token; |
| 2112 } else if (optional('=>', token)) { | 2160 } else if (optional('=>', token)) { |
| 2113 Token begin = token; | 2161 Token begin = token; |
| 2114 token = parseExpression(token.next); | 2162 token = parseExpression(token.next); |
| 2115 if (!isExpression) { | 2163 if (!isExpression) { |
| 2116 expectSemicolon(token); | 2164 expectSemicolon(token); |
| 2117 listener.handleExpressionFunctionBody(begin, token); | 2165 listener.handleExpressionFunctionBody(begin, token); |
| 2118 } else { | 2166 } else { |
| 2119 listener.handleExpressionFunctionBody(begin, null); | 2167 listener.handleExpressionFunctionBody(begin, null); |
| 2120 } | 2168 } |
| 2121 return token; | 2169 return token; |
| 2122 } else if (optional('=', token)) { | 2170 } else if (optional('=', token)) { |
| 2123 Token begin = token; | 2171 Token begin = token; |
| 2124 // Recover from a bad factory method. | 2172 // Recover from a bad factory method. |
| 2125 reportRecoverableError(token, ErrorKind.ExpectedBody); | 2173 reportRecoverableErrorCode(token, codeExpectedBody); |
| 2126 token = parseExpression(token.next); | 2174 token = parseExpression(token.next); |
| 2127 if (!isExpression) { | 2175 if (!isExpression) { |
| 2128 expectSemicolon(token); | 2176 expectSemicolon(token); |
| 2129 listener.handleExpressionFunctionBody(begin, token); | 2177 listener.handleExpressionFunctionBody(begin, token); |
| 2130 } else { | 2178 } else { |
| 2131 listener.handleExpressionFunctionBody(begin, null); | 2179 listener.handleExpressionFunctionBody(begin, null); |
| 2132 } | 2180 } |
| 2133 return token; | 2181 return token; |
| 2134 } | 2182 } |
| 2135 Token begin = token; | 2183 Token begin = token; |
| 2136 int statementCount = 0; | 2184 int statementCount = 0; |
| 2137 if (!optional('{', token)) { | 2185 if (!optional('{', token)) { |
| 2138 token = | 2186 token = |
| 2139 reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody)?.next; | 2187 reportUnrecoverableErrorCodeWithToken(token, codeExpectedFunctionBody) |
| 2188 .next; |
| 2140 listener.handleInvalidFunctionBody(token); | 2189 listener.handleInvalidFunctionBody(token); |
| 2141 return token; | 2190 return token; |
| 2142 } | 2191 } |
| 2143 | 2192 |
| 2144 listener.beginBlockFunctionBody(begin); | 2193 listener.beginBlockFunctionBody(begin); |
| 2145 token = token.next; | 2194 token = token.next; |
| 2146 while (notEofOrValue('}', token)) { | 2195 while (notEofOrValue('}', token)) { |
| 2147 token = parseStatement(token); | 2196 token = parseStatement(token); |
| 2148 ++statementCount; | 2197 ++statementCount; |
| 2149 } | 2198 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2187 asyncState = AsyncModifier.Async; | 2236 asyncState = AsyncModifier.Async; |
| 2188 } | 2237 } |
| 2189 } else if (optional('sync', token)) { | 2238 } else if (optional('sync', token)) { |
| 2190 async = token; | 2239 async = token; |
| 2191 token = token.next; | 2240 token = token.next; |
| 2192 if (optional('*', token)) { | 2241 if (optional('*', token)) { |
| 2193 asyncState = AsyncModifier.SyncStar; | 2242 asyncState = AsyncModifier.SyncStar; |
| 2194 star = token; | 2243 star = token; |
| 2195 token = token.next; | 2244 token = token.next; |
| 2196 } else { | 2245 } else { |
| 2197 reportRecoverableError(async, ErrorKind.InvalidSyncModifier); | 2246 reportRecoverableErrorCode(async, codeInvalidSyncModifier); |
| 2198 } | 2247 } |
| 2199 } | 2248 } |
| 2200 listener.handleAsyncModifier(async, star); | 2249 listener.handleAsyncModifier(async, star); |
| 2201 if (inGenerator && optional('=>', token)) { | 2250 if (inGenerator && optional('=>', token)) { |
| 2202 reportRecoverableError(token, ErrorKind.GeneratorReturnsValue); | 2251 reportRecoverableErrorCode(token, codeGeneratorReturnsValue); |
| 2203 } else if (!inPlainSync && optional(';', token)) { | 2252 } else if (!inPlainSync && optional(';', token)) { |
| 2204 reportRecoverableError(token, ErrorKind.AbstractNotSync); | 2253 reportRecoverableErrorCode(token, codeAbstractNotSync); |
| 2205 } | 2254 } |
| 2206 return token; | 2255 return token; |
| 2207 } | 2256 } |
| 2208 | 2257 |
| 2209 int statementDepth = 0; | 2258 int statementDepth = 0; |
| 2210 Token parseStatement(Token token) { | 2259 Token parseStatement(Token token) { |
| 2211 if (statementDepth++ > 500) { | 2260 if (statementDepth++ > 500) { |
| 2212 // This happens for degenerate programs, for example, a lot of nested | 2261 // This happens for degenerate programs, for example, a lot of nested |
| 2213 // if-statements. The language test deep_nesting2_negative_test, for | 2262 // if-statements. The language test deep_nesting2_negative_test, for |
| 2214 // example, provokes this. | 2263 // example, provokes this. |
| 2215 return reportUnrecoverableError(token, ErrorKind.StackOverflow)?.next; | 2264 return reportUnrecoverableErrorCode(token, codeStackOverflow).next; |
| 2216 } | 2265 } |
| 2217 Token result = parseStatementX(token); | 2266 Token result = parseStatementX(token); |
| 2218 statementDepth--; | 2267 statementDepth--; |
| 2219 return result; | 2268 return result; |
| 2220 } | 2269 } |
| 2221 | 2270 |
| 2222 Token parseStatementX(Token token) { | 2271 Token parseStatementX(Token token) { |
| 2223 final value = token.stringValue; | 2272 final value = token.stringValue; |
| 2224 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 2273 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
| 2225 return parseExpressionStatementOrDeclaration(token); | 2274 return parseExpressionStatementOrDeclaration(token); |
| 2226 } else if (identical(value, '{')) { | 2275 } else if (identical(value, '{')) { |
| 2227 return parseBlock(token); | 2276 return parseBlock(token); |
| 2228 } else if (identical(value, 'return')) { | 2277 } else if (identical(value, 'return')) { |
| 2229 return parseReturnStatement(token); | 2278 return parseReturnStatement(token); |
| 2230 } else if (identical(value, 'var') || identical(value, 'final')) { | 2279 } else if (identical(value, 'var') || identical(value, 'final')) { |
| 2231 return parseVariablesDeclaration(token); | 2280 return parseVariablesDeclaration(token); |
| 2232 } else if (identical(value, 'if')) { | 2281 } else if (identical(value, 'if')) { |
| 2233 return parseIfStatement(token); | 2282 return parseIfStatement(token); |
| 2234 } else if (identical(value, 'await') && optional('for', token.next)) { | 2283 } else if (identical(value, 'await') && optional('for', token.next)) { |
| 2235 if (!inAsync) { | 2284 if (!inAsync) { |
| 2236 reportRecoverableError(token, ErrorKind.AwaitForNotAsync); | 2285 reportRecoverableErrorCode(token, codeAwaitForNotAsync); |
| 2237 } | 2286 } |
| 2238 return parseForStatement(token, token.next); | 2287 return parseForStatement(token, token.next); |
| 2239 } else if (identical(value, 'for')) { | 2288 } else if (identical(value, 'for')) { |
| 2240 return parseForStatement(null, token); | 2289 return parseForStatement(null, token); |
| 2241 } else if (identical(value, 'rethrow')) { | 2290 } else if (identical(value, 'rethrow')) { |
| 2242 return parseRethrowStatement(token); | 2291 return parseRethrowStatement(token); |
| 2243 } else if (identical(value, 'throw') && optional(';', token.next)) { | 2292 } else if (identical(value, 'throw') && optional(';', token.next)) { |
| 2244 // TODO(kasperl): Stop dealing with throw here. | 2293 // TODO(kasperl): Stop dealing with throw here. |
| 2245 return parseRethrowStatement(token); | 2294 return parseRethrowStatement(token); |
| 2246 } else if (identical(value, 'void')) { | 2295 } else if (identical(value, 'void')) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2264 } else if (identical(value, 'yield')) { | 2313 } else if (identical(value, 'yield')) { |
| 2265 switch (asyncState) { | 2314 switch (asyncState) { |
| 2266 case AsyncModifier.Sync: | 2315 case AsyncModifier.Sync: |
| 2267 return parseExpressionStatementOrDeclaration(token); | 2316 return parseExpressionStatementOrDeclaration(token); |
| 2268 | 2317 |
| 2269 case AsyncModifier.SyncStar: | 2318 case AsyncModifier.SyncStar: |
| 2270 case AsyncModifier.AsyncStar: | 2319 case AsyncModifier.AsyncStar: |
| 2271 return parseYieldStatement(token); | 2320 return parseYieldStatement(token); |
| 2272 | 2321 |
| 2273 case AsyncModifier.Async: | 2322 case AsyncModifier.Async: |
| 2274 reportRecoverableError(token, ErrorKind.YieldNotGenerator); | 2323 reportRecoverableErrorCode(token, codeYieldNotGenerator); |
| 2275 return parseYieldStatement(token); | 2324 return parseYieldStatement(token); |
| 2276 } | 2325 } |
| 2277 throw "Internal error: Unknown asyncState: '$asyncState'."; | 2326 throw "Internal error: Unknown asyncState: '$asyncState'."; |
| 2278 } else if (identical(value, 'const')) { | 2327 } else if (identical(value, 'const')) { |
| 2279 return parseExpressionStatementOrConstDeclaration(token); | 2328 return parseExpressionStatementOrConstDeclaration(token); |
| 2280 } else if (token.isIdentifier()) { | 2329 } else if (token.isIdentifier()) { |
| 2281 return parseExpressionStatementOrDeclaration(token); | 2330 return parseExpressionStatementOrDeclaration(token); |
| 2282 } else { | 2331 } else { |
| 2283 return parseExpressionStatement(token); | 2332 return parseExpressionStatement(token); |
| 2284 } | 2333 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2302 Token parseReturnStatement(Token token) { | 2351 Token parseReturnStatement(Token token) { |
| 2303 Token begin = token; | 2352 Token begin = token; |
| 2304 listener.beginReturnStatement(begin); | 2353 listener.beginReturnStatement(begin); |
| 2305 assert(identical('return', token.stringValue)); | 2354 assert(identical('return', token.stringValue)); |
| 2306 token = token.next; | 2355 token = token.next; |
| 2307 if (optional(';', token)) { | 2356 if (optional(';', token)) { |
| 2308 listener.endReturnStatement(false, begin, token); | 2357 listener.endReturnStatement(false, begin, token); |
| 2309 } else { | 2358 } else { |
| 2310 token = parseExpression(token); | 2359 token = parseExpression(token); |
| 2311 if (inGenerator) { | 2360 if (inGenerator) { |
| 2312 reportRecoverableError(begin.next, ErrorKind.GeneratorReturnsValue); | 2361 reportRecoverableErrorCode(begin.next, codeGeneratorReturnsValue); |
| 2313 } | 2362 } |
| 2314 listener.endReturnStatement(true, begin, token); | 2363 listener.endReturnStatement(true, begin, token); |
| 2315 } | 2364 } |
| 2316 return expectSemicolon(token); | 2365 return expectSemicolon(token); |
| 2317 } | 2366 } |
| 2318 | 2367 |
| 2319 Token peekIdentifierAfterType(Token token) { | 2368 Token peekIdentifierAfterType(Token token) { |
| 2320 Token peek = peekAfterType(token); | 2369 Token peek = peekAfterType(token); |
| 2321 if (peek != null && peek.isIdentifier()) { | 2370 if (peek != null && peek.isIdentifier()) { |
| 2322 // We are looking at "type identifier". | 2371 // We are looking at "type identifier". |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2527 continue; | 2576 continue; |
| 2528 } | 2577 } |
| 2529 } | 2578 } |
| 2530 if (!mayParseFunctionExpressions && identical(value, '{')) { | 2579 if (!mayParseFunctionExpressions && identical(value, '{')) { |
| 2531 break; | 2580 break; |
| 2532 } | 2581 } |
| 2533 if (token is BeginGroupToken) { | 2582 if (token is BeginGroupToken) { |
| 2534 BeginGroupToken begin = token; | 2583 BeginGroupToken begin = token; |
| 2535 token = (begin.endGroup != null) ? begin.endGroup : token; | 2584 token = (begin.endGroup != null) ? begin.endGroup : token; |
| 2536 } else if (token is ErrorToken) { | 2585 } else if (token is ErrorToken) { |
| 2537 reportErrorToken(token, false)?.next; | 2586 reportErrorToken(token, false).next; |
| 2538 } | 2587 } |
| 2539 token = token.next; | 2588 token = token.next; |
| 2540 } | 2589 } |
| 2541 return token; | 2590 return token; |
| 2542 } | 2591 } |
| 2543 | 2592 |
| 2544 Token parseRecoverExpression(Token token) => parseExpression(token); | 2593 Token parseRecoverExpression(Token token) => parseExpression(token); |
| 2545 | 2594 |
| 2546 int expressionDepth = 0; | 2595 int expressionDepth = 0; |
| 2547 Token parseExpression(Token token) { | 2596 Token parseExpression(Token token) { |
| 2548 if (expressionDepth++ > 500) { | 2597 if (expressionDepth++ > 500) { |
| 2549 // This happens in degenerate programs, for example, with a lot of nested | 2598 // This happens in degenerate programs, for example, with a lot of nested |
| 2550 // list literals. This is provoked by, for examaple, the language test | 2599 // list literals. This is provoked by, for examaple, the language test |
| 2551 // deep_nesting1_negative_test. | 2600 // deep_nesting1_negative_test. |
| 2552 return reportUnrecoverableError(token, ErrorKind.StackOverflow)?.next; | 2601 return reportUnrecoverableErrorCode(token, codeStackOverflow).next; |
| 2553 } | 2602 } |
| 2554 listener.beginExpression(token); | 2603 listener.beginExpression(token); |
| 2555 Token result = optional('throw', token) | 2604 Token result = optional('throw', token) |
| 2556 ? parseThrowExpression(token, true) | 2605 ? parseThrowExpression(token, true) |
| 2557 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); | 2606 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); |
| 2558 expressionDepth--; | 2607 expressionDepth--; |
| 2559 return result; | 2608 return result; |
| 2560 } | 2609 } |
| 2561 | 2610 |
| 2562 Token parseExpressionWithoutCascade(Token token) { | 2611 Token parseExpressionWithoutCascade(Token token) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2610 token.next, IdentifierContext.expressionContinuation); | 2659 token.next, IdentifierContext.expressionContinuation); |
| 2611 listener.handleBinaryExpression(operator); | 2660 listener.handleBinaryExpression(operator); |
| 2612 } else if ((identical(info, OPEN_PAREN_INFO)) || | 2661 } else if ((identical(info, OPEN_PAREN_INFO)) || |
| 2613 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { | 2662 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { |
| 2614 token = parseArgumentOrIndexStar(token); | 2663 token = parseArgumentOrIndexStar(token); |
| 2615 } else if ((identical(info, PLUS_PLUS_INFO)) || | 2664 } else if ((identical(info, PLUS_PLUS_INFO)) || |
| 2616 (identical(info, MINUS_MINUS_INFO))) { | 2665 (identical(info, MINUS_MINUS_INFO))) { |
| 2617 listener.handleUnaryPostfixAssignmentExpression(token); | 2666 listener.handleUnaryPostfixAssignmentExpression(token); |
| 2618 token = token.next; | 2667 token = token.next; |
| 2619 } else { | 2668 } else { |
| 2620 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken) | 2669 token = reportUnexpectedToken(token).next; |
| 2621 ?.next; | |
| 2622 } | 2670 } |
| 2623 } else if (identical(info, IS_INFO)) { | 2671 } else if (identical(info, IS_INFO)) { |
| 2624 token = parseIsOperatorRest(token); | 2672 token = parseIsOperatorRest(token); |
| 2625 } else if (identical(info, AS_INFO)) { | 2673 } else if (identical(info, AS_INFO)) { |
| 2626 token = parseAsOperatorRest(token); | 2674 token = parseAsOperatorRest(token); |
| 2627 } else if (identical(info, QUESTION_INFO)) { | 2675 } else if (identical(info, QUESTION_INFO)) { |
| 2628 token = parseConditionalExpressionRest(token); | 2676 token = parseConditionalExpressionRest(token); |
| 2629 } else { | 2677 } else { |
| 2630 // Left associative, so we recurse at the next higher | 2678 // Left associative, so we recurse at the next higher |
| 2631 // precedence level. | 2679 // precedence level. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2651 listener.beginCascade(token); | 2699 listener.beginCascade(token); |
| 2652 assert(optional('..', token)); | 2700 assert(optional('..', token)); |
| 2653 Token cascadeOperator = token; | 2701 Token cascadeOperator = token; |
| 2654 token = token.next; | 2702 token = token.next; |
| 2655 if (optional('[', token)) { | 2703 if (optional('[', token)) { |
| 2656 token = parseArgumentOrIndexStar(token); | 2704 token = parseArgumentOrIndexStar(token); |
| 2657 } else if (token.isIdentifier()) { | 2705 } else if (token.isIdentifier()) { |
| 2658 token = parseSend(token, IdentifierContext.expressionContinuation); | 2706 token = parseSend(token, IdentifierContext.expressionContinuation); |
| 2659 listener.handleBinaryExpression(cascadeOperator); | 2707 listener.handleBinaryExpression(cascadeOperator); |
| 2660 } else { | 2708 } else { |
| 2661 return reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; | 2709 return reportUnexpectedToken(token).next; |
| 2662 } | 2710 } |
| 2663 Token mark; | 2711 Token mark; |
| 2664 do { | 2712 do { |
| 2665 mark = token; | 2713 mark = token; |
| 2666 if (optional('.', token)) { | 2714 if (optional('.', token)) { |
| 2667 Token period = token; | 2715 Token period = token; |
| 2668 token = parseSend(token.next, IdentifierContext.expressionContinuation); | 2716 token = parseSend(token.next, IdentifierContext.expressionContinuation); |
| 2669 listener.handleBinaryExpression(period); | 2717 listener.handleBinaryExpression(period); |
| 2670 } | 2718 } |
| 2671 token = parseArgumentOrIndexStar(token); | 2719 token = parseArgumentOrIndexStar(token); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2684 String value = token.stringValue; | 2732 String value = token.stringValue; |
| 2685 // Prefix: | 2733 // Prefix: |
| 2686 if (optional('await', token)) { | 2734 if (optional('await', token)) { |
| 2687 if (inPlainSync) { | 2735 if (inPlainSync) { |
| 2688 return parsePrimary(token, IdentifierContext.expression); | 2736 return parsePrimary(token, IdentifierContext.expression); |
| 2689 } else { | 2737 } else { |
| 2690 return parseAwaitExpression(token, allowCascades); | 2738 return parseAwaitExpression(token, allowCascades); |
| 2691 } | 2739 } |
| 2692 } else if (identical(value, '+')) { | 2740 } else if (identical(value, '+')) { |
| 2693 // Dart no longer allows prefix-plus. | 2741 // Dart no longer allows prefix-plus. |
| 2694 reportRecoverableError(token, ErrorKind.UnsupportedPrefixPlus); | 2742 reportRecoverableErrorCode(token, codeUnsupportedPrefixPlus); |
| 2695 return parseUnaryExpression(token.next, allowCascades); | 2743 return parseUnaryExpression(token.next, allowCascades); |
| 2696 } else if ((identical(value, '!')) || | 2744 } else if ((identical(value, '!')) || |
| 2697 (identical(value, '-')) || | 2745 (identical(value, '-')) || |
| 2698 (identical(value, '~'))) { | 2746 (identical(value, '~'))) { |
| 2699 Token operator = token; | 2747 Token operator = token; |
| 2700 // Right associative, so we recurse at the same precedence | 2748 // Right associative, so we recurse at the same precedence |
| 2701 // level. | 2749 // level. |
| 2702 token = parsePrecedenceExpression( | 2750 token = parsePrecedenceExpression( |
| 2703 token.next, POSTFIX_PRECEDENCE, allowCascades); | 2751 token.next, POSTFIX_PRECEDENCE, allowCascades); |
| 2704 listener.handleUnaryPrefixExpression(operator); | 2752 listener.handleUnaryPrefixExpression(operator); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2784 listener.handleNoTypeArguments(token); | 2832 listener.handleNoTypeArguments(token); |
| 2785 return parseLiteralMapSuffix(token, null); | 2833 return parseLiteralMapSuffix(token, null); |
| 2786 } else if (kind == LT_TOKEN) { | 2834 } else if (kind == LT_TOKEN) { |
| 2787 return parseLiteralListOrMapOrFunction(token, null); | 2835 return parseLiteralListOrMapOrFunction(token, null); |
| 2788 } else { | 2836 } else { |
| 2789 return expressionExpected(token); | 2837 return expressionExpected(token); |
| 2790 } | 2838 } |
| 2791 } | 2839 } |
| 2792 | 2840 |
| 2793 Token expressionExpected(Token token) { | 2841 Token expressionExpected(Token token) { |
| 2794 token = reportUnrecoverableError(token, ErrorKind.ExpectedExpression)?.next; | 2842 token = reportUnrecoverableErrorCodeWithToken(token, codeExpectedExpression) |
| 2843 .next; |
| 2795 listener.handleInvalidExpression(token); | 2844 listener.handleInvalidExpression(token); |
| 2796 return token; | 2845 return token; |
| 2797 } | 2846 } |
| 2798 | 2847 |
| 2799 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 2848 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
| 2800 BeginGroupToken beginGroup = token; | 2849 BeginGroupToken beginGroup = token; |
| 2801 // TODO(eernst): Check for NPE as described in issue 26252. | 2850 // TODO(eernst): Check for NPE as described in issue 26252. |
| 2802 Token nextToken = beginGroup.endGroup.next; | 2851 Token nextToken = beginGroup.endGroup.next; |
| 2803 int kind = nextToken.kind; | 2852 int kind = nextToken.kind; |
| 2804 if (mayParseFunctionExpressions && | 2853 if (mayParseFunctionExpressions && |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2819 } | 2868 } |
| 2820 | 2869 |
| 2821 Token parseParenthesizedExpression(Token token) { | 2870 Token parseParenthesizedExpression(Token token) { |
| 2822 // We expect [begin] to be of type [BeginGroupToken], but we don't know for | 2871 // We expect [begin] to be of type [BeginGroupToken], but we don't know for |
| 2823 // sure until after calling expect. | 2872 // sure until after calling expect. |
| 2824 dynamic begin = token; | 2873 dynamic begin = token; |
| 2825 token = expect('(', token); | 2874 token = expect('(', token); |
| 2826 // [begin] is now known to have type [BeginGroupToken]. | 2875 // [begin] is now known to have type [BeginGroupToken]. |
| 2827 token = parseExpression(token); | 2876 token = parseExpression(token); |
| 2828 if (!identical(begin.endGroup, token)) { | 2877 if (!identical(begin.endGroup, token)) { |
| 2829 reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; | 2878 reportUnexpectedToken(token).next; |
| 2830 token = begin.endGroup; | 2879 token = begin.endGroup; |
| 2831 } | 2880 } |
| 2832 listener.handleParenthesizedExpression(begin); | 2881 listener.handleParenthesizedExpression(begin); |
| 2833 return expect(')', token); | 2882 return expect(')', token); |
| 2834 } | 2883 } |
| 2835 | 2884 |
| 2836 Token parseThisExpression(Token token, IdentifierContext context) { | 2885 Token parseThisExpression(Token token, IdentifierContext context) { |
| 2837 Token beginToken = token; | 2886 Token beginToken = token; |
| 2838 listener.handleThisExpression(token, context); | 2887 listener.handleThisExpression(token, context); |
| 2839 token = token.next; | 2888 token = token.next; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2923 Token nextToken = beginGroup.endGroup.next; | 2972 Token nextToken = beginGroup.endGroup.next; |
| 2924 int kind = nextToken.kind; | 2973 int kind = nextToken.kind; |
| 2925 if (identical(kind, FUNCTION_TOKEN) || | 2974 if (identical(kind, FUNCTION_TOKEN) || |
| 2926 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || | 2975 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || |
| 2927 (identical(kind, KEYWORD_TOKEN) && | 2976 (identical(kind, KEYWORD_TOKEN) && |
| 2928 (optional('async', nextToken) || optional('sync', nextToken)))) { | 2977 (optional('async', nextToken) || optional('sync', nextToken)))) { |
| 2929 return parseUnnamedFunction(token); | 2978 return parseUnnamedFunction(token); |
| 2930 } | 2979 } |
| 2931 // Fall through. | 2980 // Fall through. |
| 2932 } | 2981 } |
| 2933 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 2982 return reportUnexpectedToken(token).next; |
| 2934 return null; | |
| 2935 } | 2983 } |
| 2936 | 2984 |
| 2937 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral. | 2985 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral. |
| 2938 /// | 2986 /// |
| 2939 /// Where | 2987 /// Where |
| 2940 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' | 2988 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' |
| 2941 /// genericMapLiteral ::= | 2989 /// genericMapLiteral ::= |
| 2942 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' | 2990 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' |
| 2943 /// genericFunctionLiteral ::= | 2991 /// genericFunctionLiteral ::= |
| 2944 /// typeParameters formalParameterList functionBody | 2992 /// typeParameters formalParameterList functionBody |
| 2945 /// Provide token for [constKeyword] if preceded by 'const', null if not. | 2993 /// Provide token for [constKeyword] if preceded by 'const', null if not. |
| 2946 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) { | 2994 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) { |
| 2947 assert(optional('<', token)); | 2995 assert(optional('<', token)); |
| 2948 BeginGroupToken begin = token; | 2996 BeginGroupToken begin = token; |
| 2949 if (constKeyword == null && | 2997 if (constKeyword == null && |
| 2950 begin.endGroup != null && | 2998 begin.endGroup != null && |
| 2951 identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) { | 2999 identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) { |
| 2952 token = parseTypeVariablesOpt(token); | 3000 token = parseTypeVariablesOpt(token); |
| 2953 return parseLiteralFunctionSuffix(token); | 3001 return parseLiteralFunctionSuffix(token); |
| 2954 } else { | 3002 } else { |
| 2955 token = parseTypeArgumentsOpt(token); | 3003 token = parseTypeArgumentsOpt(token); |
| 2956 if (optional('{', token)) { | 3004 if (optional('{', token)) { |
| 2957 return parseLiteralMapSuffix(token, constKeyword); | 3005 return parseLiteralMapSuffix(token, constKeyword); |
| 2958 } else if ((optional('[', token)) || (optional('[]', token))) { | 3006 } else if ((optional('[', token)) || (optional('[]', token))) { |
| 2959 return parseLiteralListSuffix(token, constKeyword); | 3007 return parseLiteralListSuffix(token, constKeyword); |
| 2960 } | 3008 } |
| 2961 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 3009 return reportUnexpectedToken(token).next; |
| 2962 return null; | |
| 2963 } | 3010 } |
| 2964 } | 3011 } |
| 2965 | 3012 |
| 2966 Token parseMapLiteralEntry(Token token) { | 3013 Token parseMapLiteralEntry(Token token) { |
| 2967 listener.beginLiteralMapEntry(token); | 3014 listener.beginLiteralMapEntry(token); |
| 2968 // Assume the listener rejects non-string keys. | 3015 // Assume the listener rejects non-string keys. |
| 2969 token = parseExpression(token); | 3016 token = parseExpression(token); |
| 2970 Token colon = token; | 3017 Token colon = token; |
| 2971 token = expect(':', token); | 3018 token = expect(':', token); |
| 2972 token = parseExpression(token); | 3019 token = parseExpression(token); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3008 } | 3055 } |
| 3009 } | 3056 } |
| 3010 return false; | 3057 return false; |
| 3011 } | 3058 } |
| 3012 | 3059 |
| 3013 Token parseRequiredArguments(Token token) { | 3060 Token parseRequiredArguments(Token token) { |
| 3014 if (optional('(', token)) { | 3061 if (optional('(', token)) { |
| 3015 token = parseArguments(token); | 3062 token = parseArguments(token); |
| 3016 } else { | 3063 } else { |
| 3017 listener.handleNoArguments(token); | 3064 listener.handleNoArguments(token); |
| 3018 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; | 3065 token = reportUnexpectedToken(token).next; |
| 3019 } | 3066 } |
| 3020 return token; | 3067 return token; |
| 3021 } | 3068 } |
| 3022 | 3069 |
| 3023 Token parseNewExpression(Token token) { | 3070 Token parseNewExpression(Token token) { |
| 3024 Token newKeyword = token; | 3071 Token newKeyword = token; |
| 3025 token = expect('new', token); | 3072 token = expect('new', token); |
| 3026 listener.beginNewExpression(newKeyword); | 3073 listener.beginNewExpression(newKeyword); |
| 3027 token = parseConstructorReference(token); | 3074 token = parseConstructorReference(token); |
| 3028 token = parseRequiredArguments(token); | 3075 token = parseRequiredArguments(token); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3213 if (optional('!', token.next)) { | 3260 if (optional('!', token.next)) { |
| 3214 token = token.next; | 3261 token = token.next; |
| 3215 not = token; | 3262 not = token; |
| 3216 } | 3263 } |
| 3217 token = parseType(token.next); | 3264 token = parseType(token.next); |
| 3218 listener.handleIsOperator(operator, not, token); | 3265 listener.handleIsOperator(operator, not, token); |
| 3219 String value = token.stringValue; | 3266 String value = token.stringValue; |
| 3220 if (identical(value, 'is') || identical(value, 'as')) { | 3267 if (identical(value, 'is') || identical(value, 'as')) { |
| 3221 // The is- and as-operators cannot be chained, but they can take part of | 3268 // The is- and as-operators cannot be chained, but they can take part of |
| 3222 // expressions like: foo is Foo || foo is Bar. | 3269 // expressions like: foo is Foo || foo is Bar. |
| 3223 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 3270 reportUnexpectedToken(token); |
| 3224 } | 3271 } |
| 3225 return token; | 3272 return token; |
| 3226 } | 3273 } |
| 3227 | 3274 |
| 3228 Token parseAsOperatorRest(Token token) { | 3275 Token parseAsOperatorRest(Token token) { |
| 3229 assert(optional('as', token)); | 3276 assert(optional('as', token)); |
| 3230 Token operator = token; | 3277 Token operator = token; |
| 3231 token = parseType(token.next); | 3278 token = parseType(token.next); |
| 3232 listener.handleAsOperator(operator, token); | 3279 listener.handleAsOperator(operator, token); |
| 3233 String value = token.stringValue; | 3280 String value = token.stringValue; |
| 3234 if (identical(value, 'is') || identical(value, 'as')) { | 3281 if (identical(value, 'is') || identical(value, 'as')) { |
| 3235 // The is- and as-operators cannot be chained. | 3282 // The is- and as-operators cannot be chained. |
| 3236 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 3283 reportUnexpectedToken(token); |
| 3237 } | 3284 } |
| 3238 return token; | 3285 return token; |
| 3239 } | 3286 } |
| 3240 | 3287 |
| 3241 Token parseVariablesDeclaration(Token token) { | 3288 Token parseVariablesDeclaration(Token token) { |
| 3242 return parseVariablesDeclarationMaybeSemicolon(token, true); | 3289 return parseVariablesDeclarationMaybeSemicolon(token, true); |
| 3243 } | 3290 } |
| 3244 | 3291 |
| 3245 Token parseVariablesDeclarationNoSemicolon(Token token) { | 3292 Token parseVariablesDeclarationNoSemicolon(Token token) { |
| 3246 // Only called when parsing a for loop, so this is for parsing locals. | 3293 // Only called when parsing a for loop, so this is for parsing locals. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3301 Token forKeyword = token; | 3348 Token forKeyword = token; |
| 3302 listener.beginForStatement(forKeyword); | 3349 listener.beginForStatement(forKeyword); |
| 3303 token = expect('for', token); | 3350 token = expect('for', token); |
| 3304 Token leftParenthesis = token; | 3351 Token leftParenthesis = token; |
| 3305 token = expect('(', token); | 3352 token = expect('(', token); |
| 3306 token = parseVariablesDeclarationOrExpressionOpt(token); | 3353 token = parseVariablesDeclarationOrExpressionOpt(token); |
| 3307 if (optional('in', token)) { | 3354 if (optional('in', token)) { |
| 3308 return parseForInRest(awaitToken, forKeyword, leftParenthesis, token); | 3355 return parseForInRest(awaitToken, forKeyword, leftParenthesis, token); |
| 3309 } else { | 3356 } else { |
| 3310 if (awaitToken != null) { | 3357 if (awaitToken != null) { |
| 3311 reportRecoverableError(awaitToken, ErrorKind.InvalidAwaitFor); | 3358 reportRecoverableErrorCode(awaitToken, codeInvalidAwaitFor); |
| 3312 } | 3359 } |
| 3313 return parseForRest(forKeyword, leftParenthesis, token); | 3360 return parseForRest(forKeyword, leftParenthesis, token); |
| 3314 } | 3361 } |
| 3315 } | 3362 } |
| 3316 | 3363 |
| 3317 Token parseVariablesDeclarationOrExpressionOpt(Token token) { | 3364 Token parseVariablesDeclarationOrExpressionOpt(Token token) { |
| 3318 final String value = token.stringValue; | 3365 final String value = token.stringValue; |
| 3319 if (identical(value, ';')) { | 3366 if (identical(value, ';')) { |
| 3320 listener.handleNoExpression(token); | 3367 listener.handleNoExpression(token); |
| 3321 return token; | 3368 return token; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3414 } | 3461 } |
| 3415 listener.endBlock(statementCount, begin, token); | 3462 listener.endBlock(statementCount, begin, token); |
| 3416 return expect('}', token); | 3463 return expect('}', token); |
| 3417 } | 3464 } |
| 3418 | 3465 |
| 3419 Token parseAwaitExpression(Token token, bool allowCascades) { | 3466 Token parseAwaitExpression(Token token, bool allowCascades) { |
| 3420 Token awaitToken = token; | 3467 Token awaitToken = token; |
| 3421 listener.beginAwaitExpression(awaitToken); | 3468 listener.beginAwaitExpression(awaitToken); |
| 3422 token = expect('await', token); | 3469 token = expect('await', token); |
| 3423 if (!inAsync) { | 3470 if (!inAsync) { |
| 3424 reportRecoverableError(awaitToken, ErrorKind.AwaitNotAsync); | 3471 reportRecoverableErrorCode(awaitToken, codeAwaitNotAsync); |
| 3425 } | 3472 } |
| 3426 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades); | 3473 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades); |
| 3427 listener.endAwaitExpression(awaitToken, token); | 3474 listener.endAwaitExpression(awaitToken, token); |
| 3428 return token; | 3475 return token; |
| 3429 } | 3476 } |
| 3430 | 3477 |
| 3431 Token parseThrowExpression(Token token, bool allowCascades) { | 3478 Token parseThrowExpression(Token token, bool allowCascades) { |
| 3432 Token throwToken = token; | 3479 Token throwToken = token; |
| 3433 listener.beginThrowExpression(throwToken); | 3480 listener.beginThrowExpression(throwToken); |
| 3434 token = expect('throw', token); | 3481 token = expect('throw', token); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3482 value = token.stringValue; // while condition | 3529 value = token.stringValue; // while condition |
| 3483 } | 3530 } |
| 3484 | 3531 |
| 3485 Token finallyKeyword = null; | 3532 Token finallyKeyword = null; |
| 3486 if (optional('finally', token)) { | 3533 if (optional('finally', token)) { |
| 3487 finallyKeyword = token; | 3534 finallyKeyword = token; |
| 3488 token = parseBlock(token.next); | 3535 token = parseBlock(token.next); |
| 3489 listener.handleFinallyBlock(finallyKeyword); | 3536 listener.handleFinallyBlock(finallyKeyword); |
| 3490 } else { | 3537 } else { |
| 3491 if (catchCount == 0) { | 3538 if (catchCount == 0) { |
| 3492 reportRecoverableError(tryKeyword, ErrorKind.OnlyTry); | 3539 reportRecoverableErrorCode(tryKeyword, codeOnlyTry); |
| 3493 } | 3540 } |
| 3494 } | 3541 } |
| 3495 listener.endTryStatement(catchCount, tryKeyword, finallyKeyword); | 3542 listener.endTryStatement(catchCount, tryKeyword, finallyKeyword); |
| 3496 return token; | 3543 return token; |
| 3497 } | 3544 } |
| 3498 | 3545 |
| 3499 Token parseSwitchStatement(Token token) { | 3546 Token parseSwitchStatement(Token token) { |
| 3500 assert(optional('switch', token)); | 3547 assert(optional('switch', token)); |
| 3501 Token switchKeyword = token; | 3548 Token switchKeyword = token; |
| 3502 listener.beginSwitchStatement(switchKeyword); | 3549 listener.beginSwitchStatement(switchKeyword); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3561 Token caseKeyword = token; | 3608 Token caseKeyword = token; |
| 3562 token = parseExpression(token.next); | 3609 token = parseExpression(token.next); |
| 3563 Token colonToken = token; | 3610 Token colonToken = token; |
| 3564 token = expect(':', token); | 3611 token = expect(':', token); |
| 3565 listener.handleCaseMatch(caseKeyword, colonToken); | 3612 listener.handleCaseMatch(caseKeyword, colonToken); |
| 3566 expressionCount++; | 3613 expressionCount++; |
| 3567 peek = peekPastLabels(token); | 3614 peek = peekPastLabels(token); |
| 3568 } else { | 3615 } else { |
| 3569 if (expressionCount == 0) { | 3616 if (expressionCount == 0) { |
| 3570 // TODO(ahe): This is probably easy to recover from. | 3617 // TODO(ahe): This is probably easy to recover from. |
| 3571 reportUnrecoverableError( | 3618 reportUnrecoverableErrorCodeWithString( |
| 3572 token, ErrorKind.ExpectedButGot, {"expected": "case"}); | 3619 token, codeExpectedButGot, "case"); |
| 3573 } | 3620 } |
| 3574 break; | 3621 break; |
| 3575 } | 3622 } |
| 3576 } | 3623 } |
| 3577 listener.beginSwitchCase(labelCount, expressionCount, begin); | 3624 listener.beginSwitchCase(labelCount, expressionCount, begin); |
| 3578 // Finally zero or more statements. | 3625 // Finally zero or more statements. |
| 3579 int statementCount = 0; | 3626 int statementCount = 0; |
| 3580 while (!identical(token.kind, EOF_TOKEN)) { | 3627 while (!identical(token.kind, EOF_TOKEN)) { |
| 3581 String value = peek.stringValue; | 3628 String value = peek.stringValue; |
| 3582 if ((identical(value, 'case')) || | 3629 if ((identical(value, 'case')) || |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3643 return expectSemicolon(token); | 3690 return expectSemicolon(token); |
| 3644 } | 3691 } |
| 3645 | 3692 |
| 3646 Token parseEmptyStatement(Token token) { | 3693 Token parseEmptyStatement(Token token) { |
| 3647 listener.handleEmptyStatement(token); | 3694 listener.handleEmptyStatement(token); |
| 3648 return expectSemicolon(token); | 3695 return expectSemicolon(token); |
| 3649 } | 3696 } |
| 3650 | 3697 |
| 3651 /// Don't call this method. Should only be used as a last resort when there | 3698 /// Don't call this method. Should only be used as a last resort when there |
| 3652 /// is no feasible way to recover from a parser error. | 3699 /// is no feasible way to recover from a parser error. |
| 3653 Token reportUnrecoverableError(Token token, ErrorKind kind, [Map arguments]) { | 3700 Token reportUnrecoverableError(Token token, FastaMessage format()) { |
| 3654 Token next; | 3701 Token next; |
| 3655 if (token is ErrorToken) { | 3702 if (token is ErrorToken) { |
| 3656 next = reportErrorToken(token, false); | 3703 next = reportErrorToken(token, false); |
| 3657 } else { | 3704 } else { |
| 3658 arguments ??= {}; | 3705 next = listener.handleUnrecoverableError(token, format()); |
| 3659 arguments.putIfAbsent("actual", () => token.lexeme); | |
| 3660 next = listener.handleUnrecoverableError(token, kind, arguments); | |
| 3661 } | 3706 } |
| 3662 return next ?? skipToEof(token); | 3707 return next ?? skipToEof(token); |
| 3663 } | 3708 } |
| 3664 | 3709 |
| 3665 void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) { | 3710 void reportRecoverableError(Token token, FastaMessage format()) { |
| 3666 if (token is ErrorToken) { | 3711 if (token is ErrorToken) { |
| 3667 reportErrorToken(token, true); | 3712 reportErrorToken(token, true); |
| 3668 } else { | 3713 } else { |
| 3669 arguments ??= {}; | 3714 listener.handleRecoverableError(token, format()); |
| 3670 listener.handleRecoverableError(token, kind, arguments); | |
| 3671 } | 3715 } |
| 3672 } | 3716 } |
| 3673 | 3717 |
| 3674 Token reportErrorToken(ErrorToken token, bool isRecoverable) { | 3718 Token reportErrorToken(ErrorToken token, bool isRecoverable) { |
| 3675 ErrorKind kind = token.errorCode; | 3719 FastaCode code = token.errorCode; |
| 3676 Map arguments = const {}; | 3720 FastaMessage message; |
| 3677 switch (kind) { | 3721 if (code == codeAsciiControlCharacter) { |
| 3678 case ErrorKind.AsciiControlCharacter: | 3722 message = codeAsciiControlCharacter.format( |
| 3679 case ErrorKind.NonAsciiIdentifier: | 3723 uri, token.charOffset, token.character); |
| 3680 case ErrorKind.NonAsciiWhitespace: | 3724 } else if (code == codeNonAsciiWhitespace) { |
| 3681 case ErrorKind.Encoding: | 3725 message = |
| 3682 String hex = token.character.toRadixString(16); | 3726 codeNonAsciiWhitespace.format(uri, token.charOffset, token.character); |
| 3683 if (hex.length < 4) { | 3727 } else if (code == codeEncoding) { |
| 3684 String padding = "0000".substring(hex.length); | 3728 message = codeEncoding.format(uri, token.charOffset); |
| 3685 hex = "$padding$hex"; | 3729 } else if (code == codeNonAsciiIdentifier) { |
| 3686 } | 3730 message = codeNonAsciiIdentifier.format(uri, token.charOffset, |
| 3687 arguments = {'characterHex': hex}; | 3731 new String.fromCharCodes([token.character]), token.character); |
| 3688 break; | 3732 } else if (code == codeUnterminatedString) { |
| 3689 | 3733 message = |
| 3690 case ErrorKind.UnterminatedString: | 3734 codeUnterminatedString.format(uri, token.charOffset, token.start); |
| 3691 arguments = {'quote': token.start}; | 3735 } else if (code == codeUnmatchedToken) { |
| 3692 break; | 3736 Token begin = token.begin; |
| 3693 | 3737 message = codeUnmatchedToken.format( |
| 3694 case ErrorKind.UnmatchedToken: | 3738 uri, token.charOffset, closeBraceFor(begin.lexeme), begin); |
| 3695 String begin = token.begin.lexeme; | 3739 } else if (code == codeUnspecified) { |
| 3696 String end = closeBraceFor(begin); | 3740 message = |
| 3697 arguments = {'begin': begin, 'end': end}; | 3741 codeUnspecified.format(uri, token.charOffset, token.assertionMessage); |
| 3698 break; | 3742 } else { |
| 3699 | 3743 message = code.format(uri, token.charOffset); |
| 3700 case ErrorKind.Unspecified: | |
| 3701 arguments = {"text": token.assertionMessage}; | |
| 3702 break; | |
| 3703 | |
| 3704 default: | |
| 3705 break; | |
| 3706 } | 3744 } |
| 3707 if (isRecoverable) { | 3745 if (isRecoverable) { |
| 3708 listener.handleRecoverableError(token, kind, arguments); | 3746 listener.handleRecoverableError(token, message); |
| 3709 return null; | 3747 return null; |
| 3710 } else { | 3748 } else { |
| 3711 return listener.handleUnrecoverableError(token, kind, arguments); | 3749 Token next = listener.handleUnrecoverableError(token, message); |
| 3750 return next ?? skipToEof(token); |
| 3712 } | 3751 } |
| 3713 } | 3752 } |
| 3753 |
| 3754 Token reportUnmatchedToken(BeginGroupToken token) { |
| 3755 return reportUnrecoverableError( |
| 3756 token, |
| 3757 () => codeUnmatchedToken.format( |
| 3758 uri, token.charOffset, closeBraceFor(token.lexeme), token)); |
| 3759 } |
| 3760 |
| 3761 Token reportUnexpectedToken(Token token) { |
| 3762 return reportUnrecoverableError( |
| 3763 token, () => codeUnexpectedToken.format(uri, token.charOffset, token)); |
| 3764 } |
| 3765 |
| 3766 void reportRecoverableErrorCode(Token token, FastaCode<NoArgument> code) { |
| 3767 reportRecoverableError(token, () => code.format(uri, token.charOffset)); |
| 3768 } |
| 3769 |
| 3770 Token reportUnrecoverableErrorCode(Token token, FastaCode<NoArgument> code) { |
| 3771 return reportUnrecoverableError( |
| 3772 token, () => code.format(uri, token.charOffset)); |
| 3773 } |
| 3774 |
| 3775 void reportRecoverableErrorCodeWithToken( |
| 3776 Token token, FastaCode<TokenArgument> code) { |
| 3777 reportRecoverableError( |
| 3778 token, () => code.format(uri, token.charOffset, token)); |
| 3779 } |
| 3780 |
| 3781 Token reportUnrecoverableErrorCodeWithToken( |
| 3782 Token token, FastaCode<TokenArgument> code) { |
| 3783 return reportUnrecoverableError( |
| 3784 token, () => code.format(uri, token.charOffset, token)); |
| 3785 } |
| 3786 |
| 3787 Token reportUnrecoverableErrorCodeWithString( |
| 3788 Token token, FastaCode<StringArgument> code, String string) { |
| 3789 return reportUnrecoverableError( |
| 3790 token, () => code.format(uri, token.charOffset, string)); |
| 3791 } |
| 3714 } | 3792 } |
| 3793 |
| 3794 typedef FastaMessage NoArgument(Uri uri, int charOffset); |
| 3795 |
| 3796 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); |
| 3797 |
| 3798 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); |
| OLD | NEW |