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 |