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 dart_parser.parser; | 5 library dart_parser.parser; |
6 | 6 |
7 import 'package:dart_scanner/src/keyword.dart' show | 7 import 'package:dart_scanner/src/keyword.dart' show |
8 Keyword; | 8 Keyword; |
9 | 9 |
10 import 'package:dart_scanner/src/precedence.dart' show | 10 import 'package:dart_scanner/src/precedence.dart' show |
11 ASSIGNMENT_PRECEDENCE, | 11 ASSIGNMENT_PRECEDENCE, |
12 AS_INFO, | 12 AS_INFO, |
13 CASCADE_PRECEDENCE, | 13 CASCADE_PRECEDENCE, |
| 14 EOF_INFO, |
14 EQUALITY_PRECEDENCE, | 15 EQUALITY_PRECEDENCE, |
15 GT_INFO, | 16 GT_INFO, |
16 IS_INFO, | 17 IS_INFO, |
17 MINUS_MINUS_INFO, | 18 MINUS_MINUS_INFO, |
18 OPEN_PAREN_INFO, | 19 OPEN_PAREN_INFO, |
19 OPEN_SQUARE_BRACKET_INFO, | 20 OPEN_SQUARE_BRACKET_INFO, |
20 PERIOD_INFO, | 21 PERIOD_INFO, |
21 PLUS_PLUS_INFO, | 22 PLUS_PLUS_INFO, |
22 POSTFIX_PRECEDENCE, | 23 POSTFIX_PRECEDENCE, |
23 PrecedenceInfo, | 24 PrecedenceInfo, |
24 QUESTION_INFO, | 25 QUESTION_INFO, |
25 QUESTION_PERIOD_INFO, | 26 QUESTION_PERIOD_INFO, |
26 RELATIONAL_PRECEDENCE; | 27 RELATIONAL_PRECEDENCE; |
27 | 28 |
28 import 'package:dart_scanner/src/token.dart' show | 29 import 'package:dart_scanner/src/token.dart' show |
| 30 BadInputToken, |
29 BeginGroupToken, | 31 BeginGroupToken, |
30 ErrorToken, | 32 ErrorToken, |
31 KeywordToken, | 33 KeywordToken, |
32 SymbolToken, | 34 SymbolToken, |
33 Token, | 35 Token, |
| 36 UnmatchedToken, |
| 37 UnterminatedToken, |
34 isUserDefinableOperator; | 38 isUserDefinableOperator; |
35 | 39 |
36 import 'package:dart_scanner/src/token_constants.dart' show | 40 import 'package:dart_scanner/src/token_constants.dart' show |
37 BAD_INPUT_TOKEN, | 41 BAD_INPUT_TOKEN, |
38 COMMA_TOKEN, | 42 COMMA_TOKEN, |
39 DOUBLE_TOKEN, | 43 DOUBLE_TOKEN, |
40 EOF_TOKEN, | 44 EOF_TOKEN, |
41 EQ_TOKEN, | 45 EQ_TOKEN, |
42 FUNCTION_TOKEN, | 46 FUNCTION_TOKEN, |
43 GT_TOKEN, | 47 GT_TOKEN, |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 listener.handleNoFormalParameters(token); | 417 listener.handleNoFormalParameters(token); |
414 return token; | 418 return token; |
415 } | 419 } |
416 } | 420 } |
417 | 421 |
418 Token skipFormalParameters(Token token) { | 422 Token skipFormalParameters(Token token) { |
419 // TODO(ahe): Shouldn't this be `beginFormalParameters`? | 423 // TODO(ahe): Shouldn't this be `beginFormalParameters`? |
420 listener.beginOptionalFormalParameters(token); | 424 listener.beginOptionalFormalParameters(token); |
421 if (!optional('(', token)) { | 425 if (!optional('(', token)) { |
422 if (optional(';', token)) { | 426 if (optional(';', token)) { |
423 listener.reportError(token, ErrorKind.ExpectedOpenParens); | 427 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); |
424 return token; | 428 return token; |
425 } | 429 } |
426 return listener.unexpected(token); | 430 return reportUnrecoverableError( |
| 431 token, ErrorKind.ExpectedButGot, {"expected": "("}); |
427 } | 432 } |
428 BeginGroupToken beginGroupToken = token; | 433 BeginGroupToken beginGroupToken = token; |
429 Token endToken = beginGroupToken.endGroup; | 434 Token endToken = beginGroupToken.endGroup; |
430 listener.endFormalParameters(0, token, endToken); | 435 listener.endFormalParameters(0, token, endToken); |
431 return endToken.next; | 436 return endToken.next; |
432 } | 437 } |
433 | 438 |
434 Token parseFormalParameters(Token token) { | 439 Token parseFormalParameters(Token token) { |
435 Token begin = token; | 440 Token begin = token; |
436 listener.beginFormalParameters(begin); | 441 listener.beginFormalParameters(begin); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 token = parseFormalParameters(token); | 495 token = parseFormalParameters(token); |
491 listener.endFunctionTypedFormalParameter(token); | 496 listener.endFunctionTypedFormalParameter(token); |
492 } | 497 } |
493 String value = token.stringValue; | 498 String value = token.stringValue; |
494 if ((identical('=', value)) || (identical(':', value))) { | 499 if ((identical('=', value)) || (identical(':', value))) { |
495 // TODO(ahe): Validate that these are only used for optional parameters. | 500 // TODO(ahe): Validate that these are only used for optional parameters. |
496 Token equal = token; | 501 Token equal = token; |
497 token = parseExpression(token.next); | 502 token = parseExpression(token.next); |
498 listener.handleValuedFormalParameter(equal, token); | 503 listener.handleValuedFormalParameter(equal, token); |
499 if (type.isRequired) { | 504 if (type.isRequired) { |
500 listener.reportError( | 505 reportRecoverableError( |
501 equal, ErrorKind.RequiredParameterWithDefault); | 506 equal, ErrorKind.RequiredParameterWithDefault); |
502 } else if (type.isPositional && identical(':', value)) { | 507 } else if (type.isPositional && identical(':', value)) { |
503 listener.reportError( | 508 reportRecoverableError( |
504 equal, ErrorKind.PositionalParameterWithEquals); | 509 equal, ErrorKind.PositionalParameterWithEquals); |
505 } | 510 } |
506 } | 511 } |
507 listener.endFormalParameter(thisKeyword); | 512 listener.endFormalParameter(thisKeyword); |
508 return token; | 513 return token; |
509 } | 514 } |
510 | 515 |
511 Token parseOptionalFormalParameters(Token token, bool isNamed) { | 516 Token parseOptionalFormalParameters(Token token, bool isNamed) { |
512 Token begin = token; | 517 Token begin = token; |
513 listener.beginOptionalFormalParameters(begin); | 518 listener.beginOptionalFormalParameters(begin); |
514 assert((isNamed && optional('{', token)) || optional('[', token)); | 519 assert((isNamed && optional('{', token)) || optional('[', token)); |
515 int parameterCount = 0; | 520 int parameterCount = 0; |
516 do { | 521 do { |
517 token = token.next; | 522 token = token.next; |
518 if (isNamed && optional('}', token)) { | 523 if (isNamed && optional('}', token)) { |
519 break; | 524 break; |
520 } else if (!isNamed && optional(']', token)) { | 525 } else if (!isNamed && optional(']', token)) { |
521 break; | 526 break; |
522 } | 527 } |
523 var type = | 528 var type = |
524 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 529 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
525 token = parseFormalParameter(token, type); | 530 token = parseFormalParameter(token, type); |
526 ++parameterCount; | 531 ++parameterCount; |
527 } while (optional(',', token)); | 532 } while (optional(',', token)); |
528 if (parameterCount == 0) { | 533 if (parameterCount == 0) { |
529 listener.reportError( | 534 reportRecoverableError( |
530 token, | 535 token, |
531 isNamed | 536 isNamed |
532 ? ErrorKind.EmptyNamedParameterList | 537 ? ErrorKind.EmptyNamedParameterList |
533 : ErrorKind.EmptyOptionalParameterList); | 538 : ErrorKind.EmptyOptionalParameterList); |
534 } | 539 } |
535 listener.endOptionalFormalParameters(parameterCount, begin, token); | 540 listener.endOptionalFormalParameters(parameterCount, begin, token); |
536 if (isNamed) { | 541 if (isNamed) { |
537 return expect('}', token); | 542 return expect('}', token); |
538 } else { | 543 } else { |
539 return expect(']', token); | 544 return expect(']', token); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 Token parseQualifiedRest(Token token) { | 661 Token parseQualifiedRest(Token token) { |
657 assert(optional('.', token)); | 662 assert(optional('.', token)); |
658 Token period = token; | 663 Token period = token; |
659 token = parseIdentifier(token.next); | 664 token = parseIdentifier(token.next); |
660 listener.handleQualified(period); | 665 listener.handleQualified(period); |
661 return token; | 666 return token; |
662 } | 667 } |
663 | 668 |
664 Token skipBlock(Token token) { | 669 Token skipBlock(Token token) { |
665 if (!optional('{', token)) { | 670 if (!optional('{', token)) { |
666 return listener.expectedBlockToSkip(token); | 671 return reportUnrecoverableError(token, ErrorKind.ExpectedBlockToSkip); |
667 } | 672 } |
668 BeginGroupToken beginGroupToken = token; | 673 BeginGroupToken beginGroupToken = token; |
669 Token endGroup = beginGroupToken.endGroup; | 674 Token endGroup = beginGroupToken.endGroup; |
670 if (endGroup == null) { | 675 if (endGroup == null) { |
671 return listener.unmatched(beginGroupToken); | 676 return reportUnrecoverableError( |
| 677 beginGroupToken, ErrorKind.UnmatchedToken); |
672 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | 678 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
673 return listener.unmatched(beginGroupToken); | 679 return reportUnrecoverableError( |
| 680 beginGroupToken, ErrorKind.UnmatchedToken); |
674 } | 681 } |
675 return beginGroupToken.endGroup; | 682 return beginGroupToken.endGroup; |
676 } | 683 } |
677 | 684 |
678 Token parseEnum(Token token) { | 685 Token parseEnum(Token token) { |
679 listener.beginEnum(token); | 686 listener.beginEnum(token); |
680 Token enumKeyword = token; | 687 Token enumKeyword = token; |
681 token = parseIdentifier(token.next); | 688 token = parseIdentifier(token.next); |
682 token = expect('{', token); | 689 token = expect('{', token); |
683 int count = 0; | 690 int count = 0; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 listener.endClassDeclaration( | 775 listener.endClassDeclaration( |
769 interfacesCount, begin, extendsKeyword, implementsKeyword, token); | 776 interfacesCount, begin, extendsKeyword, implementsKeyword, token); |
770 return token.next; | 777 return token.next; |
771 } | 778 } |
772 | 779 |
773 Token parseStringPart(Token token) { | 780 Token parseStringPart(Token token) { |
774 if (identical(token.kind, STRING_TOKEN)) { | 781 if (identical(token.kind, STRING_TOKEN)) { |
775 listener.handleStringPart(token); | 782 listener.handleStringPart(token); |
776 return token.next; | 783 return token.next; |
777 } else { | 784 } else { |
778 return listener.expected('string', token); | 785 return reportUnrecoverableError(token, ErrorKind.ExpectedString); |
779 } | 786 } |
780 } | 787 } |
781 | 788 |
782 Token parseIdentifier(Token token) { | 789 Token parseIdentifier(Token token) { |
783 if (!token.isIdentifier()) { | 790 if (!token.isIdentifier()) { |
784 token = listener.expectedIdentifier(token); | 791 token = reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier); |
785 } | 792 } |
786 listener.handleIdentifier(token); | 793 listener.handleIdentifier(token); |
787 return token.next; | 794 return token.next; |
788 } | 795 } |
789 | 796 |
790 Token expect(String string, Token token) { | 797 Token expect(String string, Token token) { |
791 if (!identical(string, token.stringValue)) { | 798 if (!identical(string, token.stringValue)) { |
792 return listener.expected(string, token); | 799 return reportUnrecoverableError( |
| 800 token, ErrorKind.ExpectedButGot, {"expected": string}); |
793 } | 801 } |
794 return token.next; | 802 return token.next; |
795 } | 803 } |
796 | 804 |
797 Token parseTypeVariable(Token token) { | 805 Token parseTypeVariable(Token token) { |
798 listener.beginTypeVariable(token); | 806 listener.beginTypeVariable(token); |
799 token = parseIdentifier(token); | 807 token = parseIdentifier(token); |
800 Token extendsOrSuper = null; | 808 Token extendsOrSuper = null; |
801 if (optional('extends', token) || optional('super', token)) { | 809 if (optional('extends', token) || optional('super', token)) { |
802 extendsOrSuper = token; | 810 extendsOrSuper = token; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 return !identical(token.kind, EOF_TOKEN) && | 844 return !identical(token.kind, EOF_TOKEN) && |
837 !identical(value, token.stringValue); | 845 !identical(value, token.stringValue); |
838 } | 846 } |
839 | 847 |
840 Token parseType(Token token) { | 848 Token parseType(Token token) { |
841 Token begin = token; | 849 Token begin = token; |
842 if (isValidTypeReference(token)) { | 850 if (isValidTypeReference(token)) { |
843 token = parseIdentifier(token); | 851 token = parseIdentifier(token); |
844 token = parseQualifiedRestOpt(token); | 852 token = parseQualifiedRestOpt(token); |
845 } else { | 853 } else { |
846 token = listener.expectedType(token); | 854 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); |
847 } | 855 } |
848 token = parseTypeArgumentsOpt(token); | 856 token = parseTypeArgumentsOpt(token); |
849 listener.endType(begin, token); | 857 listener.endType(begin, token); |
850 return token; | 858 return token; |
851 } | 859 } |
852 | 860 |
853 Token parseTypeArgumentsOpt(Token token) { | 861 Token parseTypeArgumentsOpt(Token token) { |
854 return parseStuff( | 862 return parseStuff( |
855 token, | 863 token, |
856 (t) => listener.beginTypeArguments(t), | 864 (t) => listener.beginTypeArguments(t), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 handleNoStuff(token); | 899 handleNoStuff(token); |
892 return token; | 900 return token; |
893 } | 901 } |
894 | 902 |
895 Token parseTopLevelMember(Token token) { | 903 Token parseTopLevelMember(Token token) { |
896 Token start = token; | 904 Token start = token; |
897 listener.beginTopLevelMember(token); | 905 listener.beginTopLevelMember(token); |
898 | 906 |
899 Link<Token> identifiers = findMemberName(token); | 907 Link<Token> identifiers = findMemberName(token); |
900 if (identifiers.isEmpty) { | 908 if (identifiers.isEmpty) { |
901 return listener.expectedDeclaration(start); | 909 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); |
902 } | 910 } |
903 Token afterName = identifiers.head; | 911 Token afterName = identifiers.head; |
904 identifiers = identifiers.tail; | 912 identifiers = identifiers.tail; |
905 | 913 |
906 if (identifiers.isEmpty) { | 914 if (identifiers.isEmpty) { |
907 return listener.expectedDeclaration(start); | 915 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); |
908 } | 916 } |
909 Token name = identifiers.head; | 917 Token name = identifiers.head; |
910 identifiers = identifiers.tail; | 918 identifiers = identifiers.tail; |
911 Token getOrSet; | 919 Token getOrSet; |
912 if (!identifiers.isEmpty) { | 920 if (!identifiers.isEmpty) { |
913 String value = identifiers.head.stringValue; | 921 String value = identifiers.head.stringValue; |
914 if ((identical(value, 'get')) || (identical(value, 'set'))) { | 922 if ((identical(value, 'get')) || (identical(value, 'set'))) { |
915 getOrSet = identifiers.head; | 923 getOrSet = identifiers.head; |
916 identifiers = identifiers.tail; | 924 identifiers = identifiers.tail; |
917 } | 925 } |
(...skipping 24 matching lines...) Expand all Loading... |
942 if (getOrSet != null) { | 950 if (getOrSet != null) { |
943 // If we found a "get" keyword, this must be an abstract | 951 // If we found a "get" keyword, this must be an abstract |
944 // getter. | 952 // getter. |
945 isField = (!identical(getOrSet.stringValue, 'get')); | 953 isField = (!identical(getOrSet.stringValue, 'get')); |
946 // TODO(ahe): This feels like a hack. | 954 // TODO(ahe): This feels like a hack. |
947 } else { | 955 } else { |
948 isField = true; | 956 isField = true; |
949 } | 957 } |
950 break; | 958 break; |
951 } else { | 959 } else { |
952 token = listener.unexpected(token); | 960 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
953 if (identical(token.kind, EOF_TOKEN)) return token; | 961 if (identical(token.kind, EOF_TOKEN)) return token; |
954 } | 962 } |
955 } | 963 } |
956 var modifiers = identifiers.reverse(); | 964 var modifiers = identifiers.reverse(); |
957 return isField | 965 return isField |
958 ? parseFields(start, modifiers, type, getOrSet, name, true) | 966 ? parseFields(start, modifiers, type, getOrSet, name, true) |
959 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); | 967 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); |
960 } | 968 } |
961 | 969 |
962 bool isVarFinalOrConst(Token token) { | 970 bool isVarFinalOrConst(Token token) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 parseModifier(varFinalOrConst); | 1021 parseModifier(varFinalOrConst); |
1014 modifierCount++; | 1022 modifierCount++; |
1015 hasTypeOrModifier = true; | 1023 hasTypeOrModifier = true; |
1016 modifierList.remove(varFinalOrConst); | 1024 modifierList.remove(varFinalOrConst); |
1017 } | 1025 } |
1018 listener.handleModifiers(modifierCount); | 1026 listener.handleModifiers(modifierCount); |
1019 var kind = hasTypeOrModifier | 1027 var kind = hasTypeOrModifier |
1020 ? ErrorKind.ExtraneousModifier | 1028 ? ErrorKind.ExtraneousModifier |
1021 : ErrorKind.ExtraneousModifierReplace; | 1029 : ErrorKind.ExtraneousModifierReplace; |
1022 for (Token modifier in modifierList) { | 1030 for (Token modifier in modifierList) { |
1023 listener.reportError(modifier, kind, {'modifier': modifier}); | 1031 reportRecoverableError(modifier, kind, {'modifier': modifier}); |
1024 } | 1032 } |
1025 return null; | 1033 return null; |
1026 } | 1034 } |
1027 | 1035 |
1028 /// Removes the optional `covariant` token from the modifiers, if there | 1036 /// Removes the optional `covariant` token from the modifiers, if there |
1029 /// is no `static` in the list, and `covariant` is the first modifier. | 1037 /// is no `static` in the list, and `covariant` is the first modifier. |
1030 Link<Token> removeOptCovariantTokenIfNotStatic(Link<Token> modifiers) { | 1038 Link<Token> removeOptCovariantTokenIfNotStatic(Link<Token> modifiers) { |
1031 if (modifiers.isEmpty || | 1039 if (modifiers.isEmpty || |
1032 !identical(modifiers.first.stringValue, 'covariant')) { | 1040 !identical(modifiers.first.stringValue, 'covariant')) { |
1033 return modifiers; | 1041 return modifiers; |
(...skipping 20 matching lines...) Expand all Loading... |
1054 bool hasModifier = false; | 1062 bool hasModifier = false; |
1055 if (varFinalOrConst != null) { | 1063 if (varFinalOrConst != null) { |
1056 hasModifier = true; | 1064 hasModifier = true; |
1057 isVar = optional('var', varFinalOrConst); | 1065 isVar = optional('var', varFinalOrConst); |
1058 } | 1066 } |
1059 | 1067 |
1060 if (getOrSet != null) { | 1068 if (getOrSet != null) { |
1061 var kind = (hasModifier || hasType) | 1069 var kind = (hasModifier || hasType) |
1062 ? ErrorKind.ExtraneousModifier | 1070 ? ErrorKind.ExtraneousModifier |
1063 : ErrorKind.ExtraneousModifierReplace; | 1071 : ErrorKind.ExtraneousModifierReplace; |
1064 listener.reportError(getOrSet, kind, {'modifier': getOrSet}); | 1072 reportRecoverableError(getOrSet, kind, {'modifier': getOrSet}); |
1065 } | 1073 } |
1066 | 1074 |
1067 if (!hasType) { | 1075 if (!hasType) { |
1068 listener.handleNoType(name); | 1076 listener.handleNoType(name); |
1069 } else if (optional('void', type)) { | 1077 } else if (optional('void', type)) { |
1070 listener.handleNoType(name); | 1078 listener.handleNoType(name); |
1071 // TODO(ahe): This error is reported twice, second time is from | 1079 // TODO(ahe): This error is reported twice, second time is from |
1072 // [parseVariablesDeclarationMaybeSemicolon] via | 1080 // [parseVariablesDeclarationMaybeSemicolon] via |
1073 // [PartialFieldListElement.parseNode]. | 1081 // [PartialFieldListElement.parseNode]. |
1074 listener.reportError(type, ErrorKind.InvalidVoid); | 1082 reportRecoverableError(type, ErrorKind.InvalidVoid); |
1075 } else { | 1083 } else { |
1076 parseType(type); | 1084 parseType(type); |
1077 if (isVar) { | 1085 if (isVar) { |
1078 listener.reportError(modifiers.head, ErrorKind.ExtraneousModifier, | 1086 reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier, |
1079 {'modifier': modifiers.head}); | 1087 {'modifier': modifiers.head}); |
1080 } | 1088 } |
1081 } | 1089 } |
1082 | 1090 |
1083 Token token = parseIdentifier(name); | 1091 Token token = parseIdentifier(name); |
1084 | 1092 |
1085 int fieldCount = 1; | 1093 int fieldCount = 1; |
1086 token = parseFieldInitializerOpt(token); | 1094 token = parseFieldInitializerOpt(token); |
1087 while (optional(',', token)) { | 1095 while (optional(',', token)) { |
1088 token = parseIdentifier(token.next); | 1096 token = parseIdentifier(token.next); |
(...skipping 12 matching lines...) Expand all Loading... |
1101 | 1109 |
1102 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, | 1110 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, |
1103 Token getOrSet, Token name) { | 1111 Token getOrSet, Token name) { |
1104 Token externalModifier; | 1112 Token externalModifier; |
1105 // TODO(johnniwinther): Move error reporting to resolution to give more | 1113 // TODO(johnniwinther): Move error reporting to resolution to give more |
1106 // specific error messages. | 1114 // specific error messages. |
1107 for (Token modifier in modifiers) { | 1115 for (Token modifier in modifiers) { |
1108 if (externalModifier == null && optional('external', modifier)) { | 1116 if (externalModifier == null && optional('external', modifier)) { |
1109 externalModifier = modifier; | 1117 externalModifier = modifier; |
1110 } else { | 1118 } else { |
1111 listener.reportError( | 1119 reportRecoverableError( |
1112 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); | 1120 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); |
1113 } | 1121 } |
1114 } | 1122 } |
1115 if (externalModifier != null) { | 1123 if (externalModifier != null) { |
1116 parseModifier(externalModifier); | 1124 parseModifier(externalModifier); |
1117 listener.handleModifiers(1); | 1125 listener.handleModifiers(1); |
1118 } else { | 1126 } else { |
1119 listener.handleModifiers(0); | 1127 listener.handleModifiers(0); |
1120 } | 1128 } |
1121 | 1129 |
(...skipping 10 matching lines...) Expand all Loading... |
1132 listener.handleNoTypeVariables(token); | 1140 listener.handleNoTypeVariables(token); |
1133 } | 1141 } |
1134 token = parseFormalParametersOpt(token); | 1142 token = parseFormalParametersOpt(token); |
1135 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1143 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
1136 token = parseAsyncModifier(token); | 1144 token = parseAsyncModifier(token); |
1137 token = parseFunctionBody(token, false, externalModifier != null); | 1145 token = parseFunctionBody(token, false, externalModifier != null); |
1138 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1146 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
1139 Token endToken = token; | 1147 Token endToken = token; |
1140 token = token.next; | 1148 token = token.next; |
1141 if (token.kind == BAD_INPUT_TOKEN) { | 1149 if (token.kind == BAD_INPUT_TOKEN) { |
1142 token = listener.unexpected(token); | 1150 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
1143 } | 1151 } |
1144 listener.endTopLevelMethod(start, getOrSet, endToken); | 1152 listener.endTopLevelMethod(start, getOrSet, endToken); |
1145 return token; | 1153 return token; |
1146 } | 1154 } |
1147 | 1155 |
1148 /// Looks ahead to find the name of a member. Returns a link of the modifiers, | 1156 /// Looks ahead to find the name of a member. Returns a link of the modifiers, |
1149 /// set/get, (operator) name, and either the start of the method body or the | 1157 /// set/get, (operator) name, and either the start of the method body or the |
1150 /// end of the declaration. | 1158 /// end of the declaration. |
1151 /// | 1159 /// |
1152 /// Examples: | 1160 /// Examples: |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 // type '.' ... | 1217 // type '.' ... |
1210 if (token.next.next.isIdentifier()) { | 1218 if (token.next.next.isIdentifier()) { |
1211 // type '.' identifier | 1219 // type '.' identifier |
1212 token = token.next.next; | 1220 token = token.next.next; |
1213 } | 1221 } |
1214 } | 1222 } |
1215 if (optional('<', token.next)) { | 1223 if (optional('<', token.next)) { |
1216 if (token.next is BeginGroupToken) { | 1224 if (token.next is BeginGroupToken) { |
1217 BeginGroupToken beginGroup = token.next; | 1225 BeginGroupToken beginGroup = token.next; |
1218 if (beginGroup.endGroup == null) { | 1226 if (beginGroup.endGroup == null) { |
1219 listener.unmatched(beginGroup); | 1227 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); |
1220 } | 1228 } |
1221 token = beginGroup.endGroup; | 1229 token = beginGroup.endGroup; |
1222 } | 1230 } |
1223 } | 1231 } |
1224 } | 1232 } |
1225 token = token.next; | 1233 token = token.next; |
1226 } | 1234 } |
1227 return const Link<Token>(); | 1235 return const Link<Token>(); |
1228 } | 1236 } |
1229 | 1237 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 } while (optional(',', token)); | 1280 } while (optional(',', token)); |
1273 mayParseFunctionExpressions = old; | 1281 mayParseFunctionExpressions = old; |
1274 listener.endInitializers(count, begin, token); | 1282 listener.endInitializers(count, begin, token); |
1275 return token; | 1283 return token; |
1276 } | 1284 } |
1277 | 1285 |
1278 Token parseLiteralStringOrRecoverExpression(Token token) { | 1286 Token parseLiteralStringOrRecoverExpression(Token token) { |
1279 if (identical(token.kind, STRING_TOKEN)) { | 1287 if (identical(token.kind, STRING_TOKEN)) { |
1280 return parseLiteralString(token); | 1288 return parseLiteralString(token); |
1281 } else { | 1289 } else { |
1282 listener.reportError(token, ErrorKind.ExpectedString); | 1290 reportRecoverableError(token, ErrorKind.ExpectedString); |
1283 return parseExpression(token); | 1291 return parseExpression(token); |
1284 } | 1292 } |
1285 } | 1293 } |
1286 | 1294 |
1287 Token expectSemicolon(Token token) { | 1295 Token expectSemicolon(Token token) { |
1288 return expect(';', token); | 1296 return expect(';', token); |
1289 } | 1297 } |
1290 | 1298 |
1291 bool isModifier(Token token) { | 1299 bool isModifier(Token token) { |
1292 final String value = token.stringValue; | 1300 final String value = token.stringValue; |
(...skipping 11 matching lines...) Expand all Loading... |
1304 return token.next; | 1312 return token.next; |
1305 } | 1313 } |
1306 | 1314 |
1307 void parseModifierList(Link<Token> tokens) { | 1315 void parseModifierList(Link<Token> tokens) { |
1308 int count = 0; | 1316 int count = 0; |
1309 for (; !tokens.isEmpty; tokens = tokens.tail) { | 1317 for (; !tokens.isEmpty; tokens = tokens.tail) { |
1310 Token token = tokens.head; | 1318 Token token = tokens.head; |
1311 if (isModifier(token)) { | 1319 if (isModifier(token)) { |
1312 parseModifier(token); | 1320 parseModifier(token); |
1313 } else { | 1321 } else { |
1314 listener.unexpected(token); | 1322 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
1315 // Skip the remaining modifiers. | 1323 // Skip the remaining modifiers. |
1316 break; | 1324 break; |
1317 } | 1325 } |
1318 count++; | 1326 count++; |
1319 } | 1327 } |
1320 listener.handleModifiers(count); | 1328 listener.handleModifiers(count); |
1321 } | 1329 } |
1322 | 1330 |
1323 Token parseModifiers(Token token) { | 1331 Token parseModifiers(Token token) { |
1324 int count = 0; | 1332 int count = 0; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 */ | 1373 */ |
1366 Token peekAfterIfType(Token token) { | 1374 Token peekAfterIfType(Token token) { |
1367 if (!optional('void', token) && !token.isIdentifier()) { | 1375 if (!optional('void', token) && !token.isIdentifier()) { |
1368 return null; | 1376 return null; |
1369 } | 1377 } |
1370 return peekAfterType(token); | 1378 return peekAfterType(token); |
1371 } | 1379 } |
1372 | 1380 |
1373 Token skipClassBody(Token token) { | 1381 Token skipClassBody(Token token) { |
1374 if (!optional('{', token)) { | 1382 if (!optional('{', token)) { |
1375 return listener.expectedClassBodyToSkip(token); | 1383 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip); |
1376 } | 1384 } |
1377 BeginGroupToken beginGroupToken = token; | 1385 BeginGroupToken beginGroupToken = token; |
1378 Token endGroup = beginGroupToken.endGroup; | 1386 Token endGroup = beginGroupToken.endGroup; |
1379 if (endGroup == null) { | 1387 if (endGroup == null) { |
1380 return listener.unmatched(beginGroupToken); | 1388 return reportUnrecoverableError( |
| 1389 beginGroupToken, ErrorKind.UnmatchedToken); |
1381 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | 1390 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
1382 return listener.unmatched(beginGroupToken); | 1391 return reportUnrecoverableError( |
| 1392 beginGroupToken, ErrorKind.UnmatchedToken); |
1383 } | 1393 } |
1384 return endGroup; | 1394 return endGroup; |
1385 } | 1395 } |
1386 | 1396 |
1387 Token parseClassBody(Token token) { | 1397 Token parseClassBody(Token token) { |
1388 Token begin = token; | 1398 Token begin = token; |
1389 listener.beginClassBody(token); | 1399 listener.beginClassBody(token); |
1390 if (!optional('{', token)) { | 1400 if (!optional('{', token)) { |
1391 token = listener.expectedClassBody(token); | 1401 token = reportUnrecoverableError(token, ErrorKind.ExpectedClassBody); |
1392 } | 1402 } |
1393 token = token.next; | 1403 token = token.next; |
1394 int count = 0; | 1404 int count = 0; |
1395 while (notEofOrValue('}', token)) { | 1405 while (notEofOrValue('}', token)) { |
1396 token = parseMember(token); | 1406 token = parseMember(token); |
1397 ++count; | 1407 ++count; |
1398 } | 1408 } |
1399 expect('}', token); | 1409 expect('}', token); |
1400 listener.endClassBody(count, begin, token); | 1410 listener.endClassBody(count, begin, token); |
1401 return token; | 1411 return token; |
(...skipping 16 matching lines...) Expand all Loading... |
1418 listener.beginMember(token); | 1428 listener.beginMember(token); |
1419 if (isFactoryDeclaration(token)) { | 1429 if (isFactoryDeclaration(token)) { |
1420 token = parseFactoryMethod(token); | 1430 token = parseFactoryMethod(token); |
1421 listener.endMember(); | 1431 listener.endMember(); |
1422 assert(token != null); | 1432 assert(token != null); |
1423 return token; | 1433 return token; |
1424 } | 1434 } |
1425 | 1435 |
1426 Link<Token> identifiers = findMemberName(token); | 1436 Link<Token> identifiers = findMemberName(token); |
1427 if (identifiers.isEmpty) { | 1437 if (identifiers.isEmpty) { |
1428 return listener.expectedDeclaration(start); | 1438 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); |
1429 } | 1439 } |
1430 Token afterName = identifiers.head; | 1440 Token afterName = identifiers.head; |
1431 identifiers = identifiers.tail; | 1441 identifiers = identifiers.tail; |
1432 | 1442 |
1433 if (identifiers.isEmpty) { | 1443 if (identifiers.isEmpty) { |
1434 return listener.expectedDeclaration(start); | 1444 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); |
1435 } | 1445 } |
1436 Token name = identifiers.head; | 1446 Token name = identifiers.head; |
1437 identifiers = identifiers.tail; | 1447 identifiers = identifiers.tail; |
1438 if (!identifiers.isEmpty) { | 1448 if (!identifiers.isEmpty) { |
1439 if (optional('operator', identifiers.head)) { | 1449 if (optional('operator', identifiers.head)) { |
1440 name = identifiers.head; | 1450 name = identifiers.head; |
1441 identifiers = identifiers.tail; | 1451 identifiers = identifiers.tail; |
1442 } | 1452 } |
1443 } | 1453 } |
1444 Token getOrSet; | 1454 Token getOrSet; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 isField = (!identical(getOrSet.stringValue, 'get')); | 1486 isField = (!identical(getOrSet.stringValue, 'get')); |
1477 // TODO(ahe): This feels like a hack. | 1487 // TODO(ahe): This feels like a hack. |
1478 } else { | 1488 } else { |
1479 isField = true; | 1489 isField = true; |
1480 } | 1490 } |
1481 break; | 1491 break; |
1482 } else if ((identical(value, '=')) || (identical(value, ','))) { | 1492 } else if ((identical(value, '=')) || (identical(value, ','))) { |
1483 isField = true; | 1493 isField = true; |
1484 break; | 1494 break; |
1485 } else { | 1495 } else { |
1486 token = listener.unexpected(token); | 1496 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
1487 if (identical(token.kind, EOF_TOKEN)) { | 1497 if (identical(token.kind, EOF_TOKEN)) { |
1488 // TODO(ahe): This is a hack, see parseTopLevelMember. | 1498 // TODO(ahe): This is a hack, see parseTopLevelMember. |
1489 listener.endFields(1, start, token); | 1499 listener.endFields(1, start, token); |
1490 listener.endMember(); | 1500 listener.endMember(); |
1491 return token; | 1501 return token; |
1492 } | 1502 } |
1493 } | 1503 } |
1494 } | 1504 } |
1495 | 1505 |
1496 var modifiers = identifiers.reverse(); | 1506 var modifiers = identifiers.reverse(); |
(...skipping 11 matching lines...) Expand all Loading... |
1508 Token constModifier; | 1518 Token constModifier; |
1509 int modifierCount = 0; | 1519 int modifierCount = 0; |
1510 int allowedModifierCount = 1; | 1520 int allowedModifierCount = 1; |
1511 // TODO(johnniwinther): Move error reporting to resolution to give more | 1521 // TODO(johnniwinther): Move error reporting to resolution to give more |
1512 // specific error messages. | 1522 // specific error messages. |
1513 for (Token modifier in modifiers) { | 1523 for (Token modifier in modifiers) { |
1514 if (externalModifier == null && optional('external', modifier)) { | 1524 if (externalModifier == null && optional('external', modifier)) { |
1515 modifierCount++; | 1525 modifierCount++; |
1516 externalModifier = modifier; | 1526 externalModifier = modifier; |
1517 if (modifierCount != allowedModifierCount) { | 1527 if (modifierCount != allowedModifierCount) { |
1518 listener.reportError(modifier, ErrorKind.ExtraneousModifier, | 1528 reportRecoverableError(modifier, ErrorKind.ExtraneousModifier, |
1519 {'modifier': modifier}); | 1529 {'modifier': modifier}); |
1520 } | 1530 } |
1521 allowedModifierCount++; | 1531 allowedModifierCount++; |
1522 } else if (staticModifier == null && optional('static', modifier)) { | 1532 } else if (staticModifier == null && optional('static', modifier)) { |
1523 modifierCount++; | 1533 modifierCount++; |
1524 staticModifier = modifier; | 1534 staticModifier = modifier; |
1525 if (modifierCount != allowedModifierCount) { | 1535 if (modifierCount != allowedModifierCount) { |
1526 listener.reportError(modifier, ErrorKind.ExtraneousModifier, | 1536 reportRecoverableError(modifier, ErrorKind.ExtraneousModifier, |
1527 {'modifier': modifier}); | 1537 {'modifier': modifier}); |
1528 } | 1538 } |
1529 } else if (constModifier == null && optional('const', modifier)) { | 1539 } else if (constModifier == null && optional('const', modifier)) { |
1530 modifierCount++; | 1540 modifierCount++; |
1531 constModifier = modifier; | 1541 constModifier = modifier; |
1532 if (modifierCount != allowedModifierCount) { | 1542 if (modifierCount != allowedModifierCount) { |
1533 listener.reportError(modifier, ErrorKind.ExtraneousModifier, | 1543 reportRecoverableError(modifier, ErrorKind.ExtraneousModifier, |
1534 {'modifier': modifier}); | 1544 {'modifier': modifier}); |
1535 } | 1545 } |
1536 } else { | 1546 } else { |
1537 listener.reportError( | 1547 reportRecoverableError( |
1538 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); | 1548 modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier}); |
1539 } | 1549 } |
1540 } | 1550 } |
1541 if (getOrSet != null && constModifier != null) { | 1551 if (getOrSet != null && constModifier != null) { |
1542 listener.reportError(constModifier, ErrorKind.ExtraneousModifier, | 1552 reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier, |
1543 {'modifier': constModifier}); | 1553 {'modifier': constModifier}); |
1544 } | 1554 } |
1545 parseModifierList(modifiers); | 1555 parseModifierList(modifiers); |
1546 | 1556 |
1547 if (type == null) { | 1557 if (type == null) { |
1548 listener.handleNoType(name); | 1558 listener.handleNoType(name); |
1549 } else { | 1559 } else { |
1550 parseReturnTypeOpt(type); | 1560 parseReturnTypeOpt(type); |
1551 } | 1561 } |
1552 Token token; | 1562 Token token; |
1553 if (optional('operator', name)) { | 1563 if (optional('operator', name)) { |
1554 token = parseOperatorName(name); | 1564 token = parseOperatorName(name); |
1555 if (staticModifier != null) { | 1565 if (staticModifier != null) { |
1556 listener.reportError(staticModifier, ErrorKind.ExtraneousModifier, | 1566 reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier, |
1557 {'modifier': staticModifier}); | 1567 {'modifier': staticModifier}); |
1558 } | 1568 } |
1559 } else { | 1569 } else { |
1560 token = parseIdentifier(name); | 1570 token = parseIdentifier(name); |
1561 } | 1571 } |
1562 | 1572 |
1563 token = parseQualifiedRestOpt(token); | 1573 token = parseQualifiedRestOpt(token); |
1564 if (getOrSet == null) { | 1574 if (getOrSet == null) { |
1565 token = parseTypeVariablesOpt(token); | 1575 token = parseTypeVariablesOpt(token); |
1566 } else { | 1576 } else { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1734 listener.endRedirectingFactoryBody(equals, semicolon); | 1744 listener.endRedirectingFactoryBody(equals, semicolon); |
1735 return token; | 1745 return token; |
1736 } | 1746 } |
1737 | 1747 |
1738 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 1748 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
1739 assert(!isExpression); | 1749 assert(!isExpression); |
1740 token = skipAsyncModifier(token); | 1750 token = skipAsyncModifier(token); |
1741 String value = token.stringValue; | 1751 String value = token.stringValue; |
1742 if (identical(value, ';')) { | 1752 if (identical(value, ';')) { |
1743 if (!allowAbstract) { | 1753 if (!allowAbstract) { |
1744 listener.reportError(token, ErrorKind.ExpectedBody); | 1754 reportRecoverableError(token, ErrorKind.ExpectedBody); |
1745 } | 1755 } |
1746 listener.handleNoFunctionBody(token); | 1756 listener.handleNoFunctionBody(token); |
1747 } else { | 1757 } else { |
1748 if (identical(value, '=>')) { | 1758 if (identical(value, '=>')) { |
1749 token = parseExpression(token.next); | 1759 token = parseExpression(token.next); |
1750 expectSemicolon(token); | 1760 expectSemicolon(token); |
1751 } else if (value == '=') { | 1761 } else if (value == '=') { |
1752 token = parseRedirectingFactoryBody(token); | 1762 token = parseRedirectingFactoryBody(token); |
1753 expectSemicolon(token); | 1763 expectSemicolon(token); |
1754 } else { | 1764 } else { |
1755 token = skipBlock(token); | 1765 token = skipBlock(token); |
1756 } | 1766 } |
1757 listener.handleFunctionBodySkipped(token); | 1767 listener.handleFunctionBodySkipped(token); |
1758 } | 1768 } |
1759 return token; | 1769 return token; |
1760 } | 1770 } |
1761 | 1771 |
1762 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 1772 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
1763 if (optional(';', token)) { | 1773 if (optional(';', token)) { |
1764 if (!allowAbstract) { | 1774 if (!allowAbstract) { |
1765 listener.reportError(token, ErrorKind.ExpectedBody); | 1775 reportRecoverableError(token, ErrorKind.ExpectedBody); |
1766 } | 1776 } |
1767 listener.endFunctionBody(0, null, token); | 1777 listener.endFunctionBody(0, null, token); |
1768 return token; | 1778 return token; |
1769 } else if (optional('=>', token)) { | 1779 } else if (optional('=>', token)) { |
1770 Token begin = token; | 1780 Token begin = token; |
1771 token = parseExpression(token.next); | 1781 token = parseExpression(token.next); |
1772 if (!isExpression) { | 1782 if (!isExpression) { |
1773 expectSemicolon(token); | 1783 expectSemicolon(token); |
1774 listener.endReturnStatement(true, begin, token); | 1784 listener.endReturnStatement(true, begin, token); |
1775 } else { | 1785 } else { |
1776 listener.endReturnStatement(true, begin, null); | 1786 listener.endReturnStatement(true, begin, null); |
1777 } | 1787 } |
1778 return token; | 1788 return token; |
1779 } | 1789 } |
1780 Token begin = token; | 1790 Token begin = token; |
1781 int statementCount = 0; | 1791 int statementCount = 0; |
1782 if (!optional('{', token)) { | 1792 if (!optional('{', token)) { |
1783 return listener.expectedFunctionBody(token); | 1793 return reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody); |
1784 } | 1794 } |
1785 | 1795 |
1786 listener.beginFunctionBody(begin); | 1796 listener.beginFunctionBody(begin); |
1787 token = token.next; | 1797 token = token.next; |
1788 while (notEofOrValue('}', token)) { | 1798 while (notEofOrValue('}', token)) { |
1789 token = parseStatement(token); | 1799 token = parseStatement(token); |
1790 ++statementCount; | 1800 ++statementCount; |
1791 } | 1801 } |
1792 listener.endFunctionBody(statementCount, begin, token); | 1802 listener.endFunctionBody(statementCount, begin, token); |
1793 expect('}', token); | 1803 expect('}', token); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1827 token = token.next; | 1837 token = token.next; |
1828 } | 1838 } |
1829 } else if (optional('sync', token)) { | 1839 } else if (optional('sync', token)) { |
1830 async = token; | 1840 async = token; |
1831 token = token.next; | 1841 token = token.next; |
1832 if (optional('*', token)) { | 1842 if (optional('*', token)) { |
1833 asyncAwaitKeywordsEnabled = true; | 1843 asyncAwaitKeywordsEnabled = true; |
1834 star = token; | 1844 star = token; |
1835 token = token.next; | 1845 token = token.next; |
1836 } else { | 1846 } else { |
1837 listener.reportError(async, ErrorKind.InvalidSyncModifier); | 1847 reportRecoverableError(async, ErrorKind.InvalidSyncModifier); |
1838 } | 1848 } |
1839 } | 1849 } |
1840 listener.handleAsyncModifier(async, star); | 1850 listener.handleAsyncModifier(async, star); |
1841 return token; | 1851 return token; |
1842 } | 1852 } |
1843 | 1853 |
1844 Token parseStatement(Token token) { | 1854 Token parseStatement(Token token) { |
1845 final value = token.stringValue; | 1855 final value = token.stringValue; |
1846 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 1856 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
1847 return parseExpressionStatementOrDeclaration(token); | 1857 return parseExpressionStatementOrDeclaration(token); |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2132 continue; | 2142 continue; |
2133 } | 2143 } |
2134 } | 2144 } |
2135 if (!mayParseFunctionExpressions && identical(value, '{')) { | 2145 if (!mayParseFunctionExpressions && identical(value, '{')) { |
2136 break; | 2146 break; |
2137 } | 2147 } |
2138 if (token is BeginGroupToken) { | 2148 if (token is BeginGroupToken) { |
2139 BeginGroupToken begin = token; | 2149 BeginGroupToken begin = token; |
2140 token = (begin.endGroup != null) ? begin.endGroup : token; | 2150 token = (begin.endGroup != null) ? begin.endGroup : token; |
2141 } else if (token is ErrorToken) { | 2151 } else if (token is ErrorToken) { |
2142 listener.reportErrorToken(token); | 2152 reportErrorToken(token, false); |
2143 } | 2153 } |
2144 token = token.next; | 2154 token = token.next; |
2145 } | 2155 } |
2146 return token; | 2156 return token; |
2147 } | 2157 } |
2148 | 2158 |
2149 Token parseExpression(Token token) { | 2159 Token parseExpression(Token token) { |
2150 listener.beginExpression(token); | 2160 listener.beginExpression(token); |
2151 return optional('throw', token) | 2161 return optional('throw', token) |
2152 ? parseThrowExpression(token, true) | 2162 ? parseThrowExpression(token, true) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2202 token = parseUnaryExpression(token.next, allowCascades); | 2212 token = parseUnaryExpression(token.next, allowCascades); |
2203 listener.handleBinaryExpression(operator); | 2213 listener.handleBinaryExpression(operator); |
2204 } else if ((identical(info, OPEN_PAREN_INFO)) || | 2214 } else if ((identical(info, OPEN_PAREN_INFO)) || |
2205 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { | 2215 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { |
2206 token = parseArgumentOrIndexStar(token); | 2216 token = parseArgumentOrIndexStar(token); |
2207 } else if ((identical(info, PLUS_PLUS_INFO)) || | 2217 } else if ((identical(info, PLUS_PLUS_INFO)) || |
2208 (identical(info, MINUS_MINUS_INFO))) { | 2218 (identical(info, MINUS_MINUS_INFO))) { |
2209 listener.handleUnaryPostfixAssignmentExpression(token); | 2219 listener.handleUnaryPostfixAssignmentExpression(token); |
2210 token = token.next; | 2220 token = token.next; |
2211 } else { | 2221 } else { |
2212 token = listener.unexpected(token); | 2222 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2213 } | 2223 } |
2214 } else if (identical(info, IS_INFO)) { | 2224 } else if (identical(info, IS_INFO)) { |
2215 token = parseIsOperatorRest(token); | 2225 token = parseIsOperatorRest(token); |
2216 } else if (identical(info, AS_INFO)) { | 2226 } else if (identical(info, AS_INFO)) { |
2217 token = parseAsOperatorRest(token); | 2227 token = parseAsOperatorRest(token); |
2218 } else if (identical(info, QUESTION_INFO)) { | 2228 } else if (identical(info, QUESTION_INFO)) { |
2219 token = parseConditionalExpressionRest(token); | 2229 token = parseConditionalExpressionRest(token); |
2220 } else { | 2230 } else { |
2221 // Left associative, so we recurse at the next higher | 2231 // Left associative, so we recurse at the next higher |
2222 // precedence level. | 2232 // precedence level. |
(...skipping 19 matching lines...) Expand all Loading... |
2242 listener.beginCascade(token); | 2252 listener.beginCascade(token); |
2243 assert(optional('..', token)); | 2253 assert(optional('..', token)); |
2244 Token cascadeOperator = token; | 2254 Token cascadeOperator = token; |
2245 token = token.next; | 2255 token = token.next; |
2246 if (optional('[', token)) { | 2256 if (optional('[', token)) { |
2247 token = parseArgumentOrIndexStar(token); | 2257 token = parseArgumentOrIndexStar(token); |
2248 } else if (token.isIdentifier()) { | 2258 } else if (token.isIdentifier()) { |
2249 token = parseSend(token); | 2259 token = parseSend(token); |
2250 listener.handleBinaryExpression(cascadeOperator); | 2260 listener.handleBinaryExpression(cascadeOperator); |
2251 } else { | 2261 } else { |
2252 return listener.unexpected(token); | 2262 return reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2253 } | 2263 } |
2254 Token mark; | 2264 Token mark; |
2255 do { | 2265 do { |
2256 mark = token; | 2266 mark = token; |
2257 if (optional('.', token)) { | 2267 if (optional('.', token)) { |
2258 Token period = token; | 2268 Token period = token; |
2259 token = parseSend(token.next); | 2269 token = parseSend(token.next); |
2260 listener.handleBinaryExpression(period); | 2270 listener.handleBinaryExpression(period); |
2261 } | 2271 } |
2262 token = parseArgumentOrIndexStar(token); | 2272 token = parseArgumentOrIndexStar(token); |
2263 } while (!identical(mark, token)); | 2273 } while (!identical(mark, token)); |
2264 | 2274 |
2265 if (identical(token.info.precedence, ASSIGNMENT_PRECEDENCE)) { | 2275 if (identical(token.info.precedence, ASSIGNMENT_PRECEDENCE)) { |
2266 Token assignment = token; | 2276 Token assignment = token; |
2267 token = parseExpressionWithoutCascade(token.next); | 2277 token = parseExpressionWithoutCascade(token.next); |
2268 listener.handleAssignmentExpression(assignment); | 2278 listener.handleAssignmentExpression(assignment); |
2269 } | 2279 } |
2270 listener.endCascade(); | 2280 listener.endCascade(); |
2271 return token; | 2281 return token; |
2272 } | 2282 } |
2273 | 2283 |
2274 Token parseUnaryExpression(Token token, bool allowCascades) { | 2284 Token parseUnaryExpression(Token token, bool allowCascades) { |
2275 String value = token.stringValue; | 2285 String value = token.stringValue; |
2276 // Prefix: | 2286 // Prefix: |
2277 if (asyncAwaitKeywordsEnabled && optional('await', token)) { | 2287 if (asyncAwaitKeywordsEnabled && optional('await', token)) { |
2278 return parseAwaitExpression(token, allowCascades); | 2288 return parseAwaitExpression(token, allowCascades); |
2279 } else if (identical(value, '+')) { | 2289 } else if (identical(value, '+')) { |
2280 // Dart no longer allows prefix-plus. | 2290 // Dart no longer allows prefix-plus. |
2281 listener.reportError(token, ErrorKind.UnsupportedPrefixPlus); | 2291 reportRecoverableError(token, ErrorKind.UnsupportedPrefixPlus); |
2282 return parseUnaryExpression(token.next, allowCascades); | 2292 return parseUnaryExpression(token.next, allowCascades); |
2283 } else if ((identical(value, '!')) || | 2293 } else if ((identical(value, '!')) || |
2284 (identical(value, '-')) || | 2294 (identical(value, '-')) || |
2285 (identical(value, '~'))) { | 2295 (identical(value, '~'))) { |
2286 Token operator = token; | 2296 Token operator = token; |
2287 // Right associative, so we recurse at the same precedence | 2297 // Right associative, so we recurse at the same precedence |
2288 // level. | 2298 // level. |
2289 token = parsePrecedenceExpression( | 2299 token = parsePrecedenceExpression( |
2290 token.next, POSTFIX_PRECEDENCE, allowCascades); | 2300 token.next, POSTFIX_PRECEDENCE, allowCascades); |
2291 listener.handleUnaryPrefixExpression(operator); | 2301 listener.handleUnaryPrefixExpression(operator); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2347 } else if (value == 'super') { | 2357 } else if (value == 'super') { |
2348 return parseSuperExpression(token); | 2358 return parseSuperExpression(token); |
2349 } else if (value == 'new') { | 2359 } else if (value == 'new') { |
2350 return parseNewExpression(token); | 2360 return parseNewExpression(token); |
2351 } else if (value == 'const') { | 2361 } else if (value == 'const') { |
2352 return parseConstExpression(token); | 2362 return parseConstExpression(token); |
2353 } else if (value == 'void') { | 2363 } else if (value == 'void') { |
2354 return parseFunctionExpression(token); | 2364 return parseFunctionExpression(token); |
2355 } else if (asyncAwaitKeywordsEnabled && | 2365 } else if (asyncAwaitKeywordsEnabled && |
2356 (value == 'yield' || value == 'async')) { | 2366 (value == 'yield' || value == 'async')) { |
2357 return listener.expectedExpression(token); | 2367 return reportUnrecoverableError(token, ErrorKind.ExpectedExpression); |
2358 } else if (token.isIdentifier()) { | 2368 } else if (token.isIdentifier()) { |
2359 return parseSendOrFunctionLiteral(token); | 2369 return parseSendOrFunctionLiteral(token); |
2360 } else { | 2370 } else { |
2361 return listener.expectedExpression(token); | 2371 return reportUnrecoverableError(token, ErrorKind.ExpectedExpression); |
2362 } | 2372 } |
2363 } else if (kind == OPEN_PAREN_TOKEN) { | 2373 } else if (kind == OPEN_PAREN_TOKEN) { |
2364 return parseParenthesizedExpressionOrFunctionLiteral(token); | 2374 return parseParenthesizedExpressionOrFunctionLiteral(token); |
2365 } else if (kind == OPEN_SQUARE_BRACKET_TOKEN || token.stringValue == '[]') { | 2375 } else if (kind == OPEN_SQUARE_BRACKET_TOKEN || token.stringValue == '[]') { |
2366 listener.handleNoTypeArguments(token); | 2376 listener.handleNoTypeArguments(token); |
2367 return parseLiteralListSuffix(token, null); | 2377 return parseLiteralListSuffix(token, null); |
2368 } else if (kind == OPEN_CURLY_BRACKET_TOKEN) { | 2378 } else if (kind == OPEN_CURLY_BRACKET_TOKEN) { |
2369 listener.handleNoTypeArguments(token); | 2379 listener.handleNoTypeArguments(token); |
2370 return parseLiteralMapSuffix(token, null); | 2380 return parseLiteralMapSuffix(token, null); |
2371 } else if (kind == LT_TOKEN) { | 2381 } else if (kind == LT_TOKEN) { |
2372 return parseLiteralListOrMapOrFunction(token, null); | 2382 return parseLiteralListOrMapOrFunction(token, null); |
2373 } else { | 2383 } else { |
2374 return listener.expectedExpression(token); | 2384 return reportUnrecoverableError(token, ErrorKind.ExpectedExpression); |
2375 } | 2385 } |
2376 } | 2386 } |
2377 | 2387 |
2378 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 2388 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
2379 BeginGroupToken beginGroup = token; | 2389 BeginGroupToken beginGroup = token; |
2380 // TODO(eernst): Check for NPE as described in issue 26252. | 2390 // TODO(eernst): Check for NPE as described in issue 26252. |
2381 Token nextToken = beginGroup.endGroup.next; | 2391 Token nextToken = beginGroup.endGroup.next; |
2382 int kind = nextToken.kind; | 2392 int kind = nextToken.kind; |
2383 if (mayParseFunctionExpressions && | 2393 if (mayParseFunctionExpressions && |
2384 (identical(kind, FUNCTION_TOKEN) || | 2394 (identical(kind, FUNCTION_TOKEN) || |
(...skipping 12 matching lines...) Expand all Loading... |
2397 } | 2407 } |
2398 | 2408 |
2399 Token parseParenthesizedExpression(Token token) { | 2409 Token parseParenthesizedExpression(Token token) { |
2400 // We expect [begin] to be of type [BeginGroupToken], but we don't know for | 2410 // We expect [begin] to be of type [BeginGroupToken], but we don't know for |
2401 // sure until after calling expect. | 2411 // sure until after calling expect. |
2402 var begin = token; | 2412 var begin = token; |
2403 token = expect('(', token); | 2413 token = expect('(', token); |
2404 // [begin] is now known to have type [BeginGroupToken]. | 2414 // [begin] is now known to have type [BeginGroupToken]. |
2405 token = parseExpression(token); | 2415 token = parseExpression(token); |
2406 if (!identical(begin.endGroup, token)) { | 2416 if (!identical(begin.endGroup, token)) { |
2407 listener.unexpected(token); | 2417 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2408 token = begin.endGroup; | 2418 token = begin.endGroup; |
2409 } | 2419 } |
2410 listener.handleParenthesizedExpression(begin); | 2420 listener.handleParenthesizedExpression(begin); |
2411 return expect(')', token); | 2421 return expect(')', token); |
2412 } | 2422 } |
2413 | 2423 |
2414 Token parseThisExpression(Token token) { | 2424 Token parseThisExpression(Token token) { |
2415 listener.handleThisExpression(token); | 2425 listener.handleThisExpression(token); |
2416 token = token.next; | 2426 token = token.next; |
2417 if (optional('(', token)) { | 2427 if (optional('(', token)) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2499 Token nextToken = beginGroup.endGroup.next; | 2509 Token nextToken = beginGroup.endGroup.next; |
2500 int kind = nextToken.kind; | 2510 int kind = nextToken.kind; |
2501 if (identical(kind, FUNCTION_TOKEN) || | 2511 if (identical(kind, FUNCTION_TOKEN) || |
2502 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || | 2512 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || |
2503 (identical(kind, KEYWORD_TOKEN) && | 2513 (identical(kind, KEYWORD_TOKEN) && |
2504 (nextToken.value == 'async' || nextToken.value == 'sync'))) { | 2514 (nextToken.value == 'async' || nextToken.value == 'sync'))) { |
2505 return parseUnnamedFunction(token); | 2515 return parseUnnamedFunction(token); |
2506 } | 2516 } |
2507 // Fall through. | 2517 // Fall through. |
2508 } | 2518 } |
2509 listener.unexpected(token); | 2519 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2510 return null; | 2520 return null; |
2511 } | 2521 } |
2512 | 2522 |
2513 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral. | 2523 /// genericListLiteral | genericMapLiteral | genericFunctionLiteral. |
2514 /// | 2524 /// |
2515 /// Where | 2525 /// Where |
2516 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' | 2526 /// genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']' |
2517 /// genericMapLiteral ::= | 2527 /// genericMapLiteral ::= |
2518 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' | 2528 /// typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' |
2519 /// genericFunctionLiteral ::= | 2529 /// genericFunctionLiteral ::= |
2520 /// typeParameters formalParameterList functionBody | 2530 /// typeParameters formalParameterList functionBody |
2521 /// Provide token for [constKeyword] if preceded by 'const', null if not. | 2531 /// Provide token for [constKeyword] if preceded by 'const', null if not. |
2522 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) { | 2532 Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) { |
2523 assert(optional('<', token)); | 2533 assert(optional('<', token)); |
2524 BeginGroupToken begin = token; | 2534 BeginGroupToken begin = token; |
2525 if (constKeyword == null && | 2535 if (constKeyword == null && |
2526 begin.endGroup != null && | 2536 begin.endGroup != null && |
2527 identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) { | 2537 identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) { |
2528 token = parseTypeVariablesOpt(token); | 2538 token = parseTypeVariablesOpt(token); |
2529 return parseLiteralFunctionSuffix(token); | 2539 return parseLiteralFunctionSuffix(token); |
2530 } else { | 2540 } else { |
2531 token = parseTypeArgumentsOpt(token); | 2541 token = parseTypeArgumentsOpt(token); |
2532 if (optional('{', token)) { | 2542 if (optional('{', token)) { |
2533 return parseLiteralMapSuffix(token, constKeyword); | 2543 return parseLiteralMapSuffix(token, constKeyword); |
2534 } else if ((optional('[', token)) || (optional('[]', token))) { | 2544 } else if ((optional('[', token)) || (optional('[]', token))) { |
2535 return parseLiteralListSuffix(token, constKeyword); | 2545 return parseLiteralListSuffix(token, constKeyword); |
2536 } | 2546 } |
2537 listener.unexpected(token); | 2547 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2538 return null; | 2548 return null; |
2539 } | 2549 } |
2540 } | 2550 } |
2541 | 2551 |
2542 Token parseMapLiteralEntry(Token token) { | 2552 Token parseMapLiteralEntry(Token token) { |
2543 listener.beginLiteralMapEntry(token); | 2553 listener.beginLiteralMapEntry(token); |
2544 // Assume the listener rejects non-string keys. | 2554 // Assume the listener rejects non-string keys. |
2545 token = parseExpression(token); | 2555 token = parseExpression(token); |
2546 Token colon = token; | 2556 Token colon = token; |
2547 token = expect(':', token); | 2557 token = expect(':', token); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2582 } | 2592 } |
2583 } | 2593 } |
2584 return false; | 2594 return false; |
2585 } | 2595 } |
2586 | 2596 |
2587 Token parseRequiredArguments(Token token) { | 2597 Token parseRequiredArguments(Token token) { |
2588 if (optional('(', token)) { | 2598 if (optional('(', token)) { |
2589 token = parseArguments(token); | 2599 token = parseArguments(token); |
2590 } else { | 2600 } else { |
2591 listener.handleNoArguments(token); | 2601 listener.handleNoArguments(token); |
2592 token = listener.unexpected(token); | 2602 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2593 } | 2603 } |
2594 return token; | 2604 return token; |
2595 } | 2605 } |
2596 | 2606 |
2597 Token parseNewExpression(Token token) { | 2607 Token parseNewExpression(Token token) { |
2598 Token newKeyword = token; | 2608 Token newKeyword = token; |
2599 token = expect('new', token); | 2609 token = expect('new', token); |
2600 token = parseConstructorReference(token); | 2610 token = parseConstructorReference(token); |
2601 token = parseRequiredArguments(token); | 2611 token = parseRequiredArguments(token); |
2602 listener.handleNewExpression(newKeyword); | 2612 listener.handleNewExpression(newKeyword); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2780 if (optional('!', token.next)) { | 2790 if (optional('!', token.next)) { |
2781 token = token.next; | 2791 token = token.next; |
2782 not = token; | 2792 not = token; |
2783 } | 2793 } |
2784 token = parseType(token.next); | 2794 token = parseType(token.next); |
2785 listener.handleIsOperator(operator, not, token); | 2795 listener.handleIsOperator(operator, not, token); |
2786 String value = token.stringValue; | 2796 String value = token.stringValue; |
2787 if (identical(value, 'is') || identical(value, 'as')) { | 2797 if (identical(value, 'is') || identical(value, 'as')) { |
2788 // The is- and as-operators cannot be chained, but they can take part of | 2798 // The is- and as-operators cannot be chained, but they can take part of |
2789 // expressions like: foo is Foo || foo is Bar. | 2799 // expressions like: foo is Foo || foo is Bar. |
2790 listener.unexpected(token); | 2800 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2791 } | 2801 } |
2792 return token; | 2802 return token; |
2793 } | 2803 } |
2794 | 2804 |
2795 Token parseAsOperatorRest(Token token) { | 2805 Token parseAsOperatorRest(Token token) { |
2796 assert(optional('as', token)); | 2806 assert(optional('as', token)); |
2797 Token operator = token; | 2807 Token operator = token; |
2798 token = parseType(token.next); | 2808 token = parseType(token.next); |
2799 listener.handleAsOperator(operator, token); | 2809 listener.handleAsOperator(operator, token); |
2800 String value = token.stringValue; | 2810 String value = token.stringValue; |
2801 if (identical(value, 'is') || identical(value, 'as')) { | 2811 if (identical(value, 'is') || identical(value, 'as')) { |
2802 // The is- and as-operators cannot be chained. | 2812 // The is- and as-operators cannot be chained. |
2803 listener.unexpected(token); | 2813 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); |
2804 } | 2814 } |
2805 return token; | 2815 return token; |
2806 } | 2816 } |
2807 | 2817 |
2808 Token parseVariablesDeclaration(Token token) { | 2818 Token parseVariablesDeclaration(Token token) { |
2809 return parseVariablesDeclarationMaybeSemicolon(token, true); | 2819 return parseVariablesDeclarationMaybeSemicolon(token, true); |
2810 } | 2820 } |
2811 | 2821 |
2812 Token parseVariablesDeclarationNoSemicolon(Token token) { | 2822 Token parseVariablesDeclarationNoSemicolon(Token token) { |
2813 // Only called when parsing a for loop, so this is for parsing locals. | 2823 // Only called when parsing a for loop, so this is for parsing locals. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2866 Token parseForStatement(Token awaitToken, Token token) { | 2876 Token parseForStatement(Token awaitToken, Token token) { |
2867 Token forToken = token; | 2877 Token forToken = token; |
2868 listener.beginForStatement(forToken); | 2878 listener.beginForStatement(forToken); |
2869 token = expect('for', token); | 2879 token = expect('for', token); |
2870 token = expect('(', token); | 2880 token = expect('(', token); |
2871 token = parseVariablesDeclarationOrExpressionOpt(token); | 2881 token = parseVariablesDeclarationOrExpressionOpt(token); |
2872 if (optional('in', token)) { | 2882 if (optional('in', token)) { |
2873 return parseForInRest(awaitToken, forToken, token); | 2883 return parseForInRest(awaitToken, forToken, token); |
2874 } else { | 2884 } else { |
2875 if (awaitToken != null) { | 2885 if (awaitToken != null) { |
2876 listener.reportError(awaitToken, ErrorKind.InvalidAwaitFor); | 2886 reportRecoverableError(awaitToken, ErrorKind.InvalidAwaitFor); |
2877 } | 2887 } |
2878 return parseForRest(forToken, token); | 2888 return parseForRest(forToken, token); |
2879 } | 2889 } |
2880 } | 2890 } |
2881 | 2891 |
2882 Token parseVariablesDeclarationOrExpressionOpt(Token token) { | 2892 Token parseVariablesDeclarationOrExpressionOpt(Token token) { |
2883 final String value = token.stringValue; | 2893 final String value = token.stringValue; |
2884 if (identical(value, ';')) { | 2894 if (identical(value, ';')) { |
2885 listener.handleNoExpression(token); | 2895 listener.handleNoExpression(token); |
2886 return token; | 2896 return token; |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3118 } | 3128 } |
3119 Token caseKeyword = token; | 3129 Token caseKeyword = token; |
3120 token = parseExpression(token.next); | 3130 token = parseExpression(token.next); |
3121 Token colonToken = token; | 3131 Token colonToken = token; |
3122 token = expect(':', token); | 3132 token = expect(':', token); |
3123 listener.handleCaseMatch(caseKeyword, colonToken); | 3133 listener.handleCaseMatch(caseKeyword, colonToken); |
3124 expressionCount++; | 3134 expressionCount++; |
3125 peek = peekPastLabels(token); | 3135 peek = peekPastLabels(token); |
3126 } else { | 3136 } else { |
3127 if (expressionCount == 0) { | 3137 if (expressionCount == 0) { |
3128 listener.expected("case", token); | 3138 // TODO(ahe): This is probably easy to recover from. |
| 3139 reportUnrecoverableError( |
| 3140 token, ErrorKind.ExpectedButGot, {"expected": "case"}); |
3129 } | 3141 } |
3130 break; | 3142 break; |
3131 } | 3143 } |
3132 } | 3144 } |
3133 listener.beginSwitchCase(labelCount, expressionCount, begin); | 3145 listener.beginSwitchCase(labelCount, expressionCount, begin); |
3134 // Finally zero or more statements. | 3146 // Finally zero or more statements. |
3135 int statementCount = 0; | 3147 int statementCount = 0; |
3136 while (!identical(token.kind, EOF_TOKEN)) { | 3148 while (!identical(token.kind, EOF_TOKEN)) { |
3137 String value = peek.stringValue; | 3149 String value = peek.stringValue; |
3138 if ((identical(value, 'case')) || | 3150 if ((identical(value, 'case')) || |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3193 hasTarget = true; | 3205 hasTarget = true; |
3194 } | 3206 } |
3195 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 3207 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
3196 return expectSemicolon(token); | 3208 return expectSemicolon(token); |
3197 } | 3209 } |
3198 | 3210 |
3199 Token parseEmptyStatement(Token token) { | 3211 Token parseEmptyStatement(Token token) { |
3200 listener.handleEmptyStatement(token); | 3212 listener.handleEmptyStatement(token); |
3201 return expectSemicolon(token); | 3213 return expectSemicolon(token); |
3202 } | 3214 } |
| 3215 |
| 3216 /// Don't call this method. Should only be used as a last resort when there |
| 3217 /// is no feasible way to recover from a parser error. |
| 3218 Token reportUnrecoverableError(Token token, ErrorKind kind, [Map arguments]) { |
| 3219 Token next; |
| 3220 if (token is ErrorToken) { |
| 3221 next = reportErrorToken(token, false); |
| 3222 } else { |
| 3223 arguments ??= {}; |
| 3224 arguments.putIfAbsent("actual", () => token.value); |
| 3225 next = listener.handleUnrecoverableError(token, kind, arguments); |
| 3226 } |
| 3227 return next ?? skipToEof(token); |
| 3228 } |
| 3229 |
| 3230 void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) { |
| 3231 if (token is ErrorToken) { |
| 3232 reportErrorToken(token, true); |
| 3233 } else { |
| 3234 arguments ??= {}; |
| 3235 listener.handleRecoverableError(token, kind, arguments); |
| 3236 } |
| 3237 } |
| 3238 |
| 3239 Token reportErrorToken(ErrorToken token, bool isRecoverable) { |
| 3240 ErrorKind kind; |
| 3241 Map arguments = const {}; |
| 3242 if (token is BadInputToken) { |
| 3243 String hex = token.character.toRadixString(16); |
| 3244 if (hex.length < 4) { |
| 3245 String padding = "0000".substring(hex.length); |
| 3246 hex = "$padding$hex"; |
| 3247 } |
| 3248 kind = ErrorKind.InvalidInputCharacter; |
| 3249 arguments = {'characterHex': hex}; |
| 3250 } else if (token is UnterminatedToken) { |
| 3251 switch (token.start) { |
| 3252 case '1e': |
| 3253 kind = ErrorKind.MissingExponent; |
| 3254 break; |
| 3255 case '"': |
| 3256 case "'": |
| 3257 case '"""': |
| 3258 case "'''": |
| 3259 case 'r"': |
| 3260 case "r'": |
| 3261 case 'r"""': |
| 3262 case "r'''": |
| 3263 kind = ErrorKind.UnterminatedString; |
| 3264 arguments = {'quote': token.start}; |
| 3265 break; |
| 3266 case '0x': |
| 3267 kind = ErrorKind.ExpectedHexDigit; |
| 3268 break; |
| 3269 case r'$': |
| 3270 kind = ErrorKind.MalformedStringLiteral; |
| 3271 break; |
| 3272 case '/*': |
| 3273 kind = ErrorKind.UnterminatedComment; |
| 3274 break; |
| 3275 default: |
| 3276 kind = ErrorKind.UnterminatedToken; |
| 3277 break; |
| 3278 } |
| 3279 } else if (token is UnmatchedToken) { |
| 3280 String begin = token.begin.value; |
| 3281 String end = closeBraceFor(begin); |
| 3282 kind = ErrorKind.UnmatchedToken; |
| 3283 arguments = {'begin': begin, 'end': end}; |
| 3284 } else { |
| 3285 return listener.handleUnrecoverableError( |
| 3286 token, ErrorKind.Unspecified, {"text": token.assertionMessage}); |
| 3287 } |
| 3288 if (isRecoverable) { |
| 3289 listener.handleRecoverableError(token, kind, arguments); |
| 3290 return null; |
| 3291 } else { |
| 3292 return listener.handleUnrecoverableError(token, kind, arguments); |
| 3293 } |
| 3294 } |
3203 } | 3295 } |
| 3296 |
| 3297 String closeBraceFor(String openBrace) { |
| 3298 return const { |
| 3299 '(': ')', |
| 3300 '[': ']', |
| 3301 '{': '}', |
| 3302 '<': '>', |
| 3303 r'${': '}', |
| 3304 }[openBrace]; |
| 3305 } |
| 3306 |
| 3307 Token skipToEof(Token token) { |
| 3308 while (!identical(token.info, EOF_INFO)) { |
| 3309 token = token.next; |
| 3310 } |
| 3311 return token; |
| 3312 } |
OLD | NEW |