| 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 |