OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library fasta.parser.parser; | 5 library fasta.parser.parser; |
6 | 6 |
7 import '../fasta_codes.dart' show FastaCode, FastaMessage; | 7 import '../fasta_codes.dart' show Code, Message, Template; |
8 | 8 |
9 import '../fasta_codes.dart' as fasta; | 9 import '../fasta_codes.dart' as fasta; |
10 | 10 |
11 import '../scanner.dart' show ErrorToken, Token; | 11 import '../scanner.dart' show ErrorToken, Token; |
12 | 12 |
13 import '../scanner/recover.dart' show closeBraceFor, skipToEof; | 13 import '../scanner/recover.dart' show closeBraceFor, skipToEof; |
14 | 14 |
15 import '../../scanner/token.dart' | 15 import '../../scanner/token.dart' |
16 show | 16 show |
17 ASSIGNMENT_PRECEDENCE, | 17 ASSIGNMENT_PRECEDENCE, |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 /// | 271 /// |
272 /// Both dart2js and the Dart VM have used the `native` keyword to mark methods | 272 /// Both dart2js and the Dart VM have used the `native` keyword to mark methods |
273 /// that couldn't be implemented in the Dart language and needed to be | 273 /// that couldn't be implemented in the Dart language and needed to be |
274 /// implemented in JavaScript or C++, respectively. An example of the syntax | 274 /// implemented in JavaScript or C++, respectively. An example of the syntax |
275 /// extension used by the Dart VM is: | 275 /// extension used by the Dart VM is: |
276 /// | 276 /// |
277 /// nativeFunction() native "NativeFunction"; | 277 /// nativeFunction() native "NativeFunction"; |
278 /// | 278 /// |
279 /// When attempting to parse this function, the parser eventually calls | 279 /// When attempting to parse this function, the parser eventually calls |
280 /// [parseFunctionBody]. This method will report an unrecoverable error to the | 280 /// [parseFunctionBody]. This method will report an unrecoverable error to the |
281 /// listener with the code [fasta.codeExpectedFunctionBody]. The listener can | 281 /// listener with the code [fasta.messageExpectedFunctionBody]. The listener can |
282 /// then look at the error code and the token and use the methods in | 282 /// then look at the error code and the token and use the methods in |
283 /// [dart_vm_native.dart](dart_vm_native.dart) to parse the native syntax. | 283 /// [dart_vm_native.dart](dart_vm_native.dart) to parse the native syntax. |
284 /// | 284 /// |
285 /// #### Implementation of Diet Parsing | 285 /// #### Implementation of Diet Parsing |
286 /// | 286 /// |
287 /// We call it _diet_ _parsing_ when the parser skips parts of a file. Both | 287 /// We call it _diet_ _parsing_ when the parser skips parts of a file. Both |
288 /// dart2js and the Dart VM have been relying on this from early on as it allows | 288 /// dart2js and the Dart VM have been relying on this from early on as it allows |
289 /// them to more quickly compile small programs that use small parts of big | 289 /// them to more quickly compile small programs that use small parts of big |
290 /// libraries. It's also become an integrated part of how Fasta builds up | 290 /// libraries. It's also become an integrated part of how Fasta builds up |
291 /// outlines before starting to parse method bodies. | 291 /// outlines before starting to parse method bodies. |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 | 606 |
607 /// Parse `'@' qualified (‘.’ identifier)? (arguments)?` | 607 /// Parse `'@' qualified (‘.’ identifier)? (arguments)?` |
608 Token parseMetadata(Token token) { | 608 Token parseMetadata(Token token) { |
609 listener.beginMetadata(token); | 609 listener.beginMetadata(token); |
610 Token atToken = token; | 610 Token atToken = token; |
611 assert(optional('@', token)); | 611 assert(optional('@', token)); |
612 token = parseIdentifier(token.next, IdentifierContext.metadataReference); | 612 token = parseIdentifier(token.next, IdentifierContext.metadataReference); |
613 token = | 613 token = |
614 parseQualifiedRestOpt(token, IdentifierContext.metadataContinuation); | 614 parseQualifiedRestOpt(token, IdentifierContext.metadataContinuation); |
615 if (optional("<", token)) { | 615 if (optional("<", token)) { |
616 reportRecoverableErrorCode(token, fasta.codeMetadataTypeArguments); | 616 reportRecoverableError(token, fasta.messageMetadataTypeArguments); |
617 } | 617 } |
618 token = parseTypeArgumentsOpt(token); | 618 token = parseTypeArgumentsOpt(token); |
619 Token period = null; | 619 Token period = null; |
620 if (optional('.', token)) { | 620 if (optional('.', token)) { |
621 period = token; | 621 period = token; |
622 token = parseIdentifier( | 622 token = parseIdentifier( |
623 token.next, IdentifierContext.metadataContinuationAfterTypeArguments); | 623 token.next, IdentifierContext.metadataContinuationAfterTypeArguments); |
624 } | 624 } |
625 token = parseArgumentsOpt(token); | 625 token = parseArgumentsOpt(token); |
626 listener.endMetadata(atToken, period, token); | 626 listener.endMetadata(atToken, period, token); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 listener.handleNoFormalParameters(token, kind); | 671 listener.handleNoFormalParameters(token, kind); |
672 return token; | 672 return token; |
673 } | 673 } |
674 } | 674 } |
675 | 675 |
676 Token skipFormalParameters(Token token, MemberKind kind) { | 676 Token skipFormalParameters(Token token, MemberKind kind) { |
677 // TODO(ahe): Shouldn't this be `beginFormalParameters`? | 677 // TODO(ahe): Shouldn't this be `beginFormalParameters`? |
678 listener.beginOptionalFormalParameters(token); | 678 listener.beginOptionalFormalParameters(token); |
679 if (!optional('(', token)) { | 679 if (!optional('(', token)) { |
680 if (optional(';', token)) { | 680 if (optional(';', token)) { |
681 reportRecoverableErrorCode(token, fasta.codeExpectedOpenParens); | 681 reportRecoverableError(token, fasta.messageExpectedOpenParens); |
682 return token; | 682 return token; |
683 } | 683 } |
684 return reportUnrecoverableErrorCodeWithString( | 684 return reportUnrecoverableError( |
685 token, fasta.codeExpectedButGot, "(") | 685 token, fasta.templateExpectedButGot.withArguments("(")) |
686 .next; | 686 .next; |
687 } | 687 } |
688 BeginToken beginGroupToken = token; | 688 BeginToken beginGroupToken = token; |
689 Token endToken = beginGroupToken.endGroup; | 689 Token endToken = beginGroupToken.endGroup; |
690 listener.endFormalParameters(0, token, endToken, kind); | 690 listener.endFormalParameters(0, token, endToken, kind); |
691 return endToken.next; | 691 return endToken.next; |
692 } | 692 } |
693 | 693 |
694 /// Parses the formal parameter list of a function. | 694 /// Parses the formal parameter list of a function. |
695 /// | 695 /// |
(...skipping 12 matching lines...) Expand all Loading... |
708 ++parameterCount; | 708 ++parameterCount; |
709 String value = token.stringValue; | 709 String value = token.stringValue; |
710 if (identical(value, '[')) { | 710 if (identical(value, '[')) { |
711 token = parseOptionalFormalParameters(token, false, kind); | 711 token = parseOptionalFormalParameters(token, false, kind); |
712 break; | 712 break; |
713 } else if (identical(value, '{')) { | 713 } else if (identical(value, '{')) { |
714 token = parseOptionalFormalParameters(token, true, kind); | 714 token = parseOptionalFormalParameters(token, true, kind); |
715 break; | 715 break; |
716 } else if (identical(value, '[]')) { | 716 } else if (identical(value, '[]')) { |
717 --parameterCount; | 717 --parameterCount; |
718 reportRecoverableErrorCode(token, fasta.codeEmptyOptionalParameterList); | 718 reportRecoverableError(token, fasta.messageEmptyOptionalParameterList); |
719 token = token.next; | 719 token = token.next; |
720 break; | 720 break; |
721 } | 721 } |
722 token = parseFormalParameter(token, FormalParameterType.REQUIRED, kind); | 722 token = parseFormalParameter(token, FormalParameterType.REQUIRED, kind); |
723 } while (optional(',', token)); | 723 } while (optional(',', token)); |
724 listener.endFormalParameters(parameterCount, begin, token, kind); | 724 listener.endFormalParameters(parameterCount, begin, token, kind); |
725 return expect(')', token); | 725 return expect(')', token); |
726 } | 726 } |
727 | 727 |
728 Token parseFormalParameter( | 728 Token parseFormalParameter( |
(...skipping 16 matching lines...) Expand all Loading... |
745 break; | 745 break; |
746 } else if (!isNamed && optional(']', token)) { | 746 } else if (!isNamed && optional(']', token)) { |
747 break; | 747 break; |
748 } | 748 } |
749 var type = | 749 var type = |
750 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 750 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
751 token = parseFormalParameter(token, type, kind); | 751 token = parseFormalParameter(token, type, kind); |
752 ++parameterCount; | 752 ++parameterCount; |
753 } while (optional(',', token)); | 753 } while (optional(',', token)); |
754 if (parameterCount == 0) { | 754 if (parameterCount == 0) { |
755 reportRecoverableErrorCode( | 755 reportRecoverableError( |
756 token, | 756 token, |
757 isNamed | 757 isNamed |
758 ? fasta.codeEmptyNamedParameterList | 758 ? fasta.messageEmptyNamedParameterList |
759 : fasta.codeEmptyOptionalParameterList); | 759 : fasta.messageEmptyOptionalParameterList); |
760 } | 760 } |
761 listener.endOptionalFormalParameters(parameterCount, begin, token); | 761 listener.endOptionalFormalParameters(parameterCount, begin, token); |
762 if (isNamed) { | 762 if (isNamed) { |
763 return expect('}', token); | 763 return expect('}', token); |
764 } else { | 764 } else { |
765 return expect(']', token); | 765 return expect(']', token); |
766 } | 766 } |
767 } | 767 } |
768 | 768 |
769 bool isValidTypeReference(Token token) { | 769 bool isValidTypeReference(Token token) { |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 Token parseQualifiedRest(Token token, IdentifierContext context) { | 878 Token parseQualifiedRest(Token token, IdentifierContext context) { |
879 assert(optional('.', token)); | 879 assert(optional('.', token)); |
880 Token period = token; | 880 Token period = token; |
881 token = parseIdentifier(token.next, context); | 881 token = parseIdentifier(token.next, context); |
882 listener.handleQualified(period); | 882 listener.handleQualified(period); |
883 return token; | 883 return token; |
884 } | 884 } |
885 | 885 |
886 Token skipBlock(Token token) { | 886 Token skipBlock(Token token) { |
887 if (!optional('{', token)) { | 887 if (!optional('{', token)) { |
888 return reportUnrecoverableErrorCode(token, fasta.codeExpectedBlockToSkip) | 888 return reportUnrecoverableError(token, fasta.messageExpectedBlockToSkip) |
889 .next; | 889 .next; |
890 } | 890 } |
891 BeginToken beginGroupToken = token; | 891 BeginToken beginGroupToken = token; |
892 Token endGroup = beginGroupToken.endGroup; | 892 Token endGroup = beginGroupToken.endGroup; |
893 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | 893 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
894 return reportUnmatchedToken(beginGroupToken).next; | 894 return reportUnmatchedToken(beginGroupToken).next; |
895 } | 895 } |
896 return beginGroupToken.endGroup; | 896 return beginGroupToken.endGroup; |
897 } | 897 } |
898 | 898 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 } | 982 } |
983 token = parseClassBody(token); | 983 token = parseClassBody(token); |
984 listener.endClassDeclaration(interfacesCount, begin, classKeyword, | 984 listener.endClassDeclaration(interfacesCount, begin, classKeyword, |
985 extendsKeyword, implementsKeyword, token); | 985 extendsKeyword, implementsKeyword, token); |
986 return token.next; | 986 return token.next; |
987 } | 987 } |
988 | 988 |
989 Token parseStringPart(Token token) { | 989 Token parseStringPart(Token token) { |
990 if (token.kind != STRING_TOKEN) { | 990 if (token.kind != STRING_TOKEN) { |
991 token = | 991 token = |
992 reportUnrecoverableErrorCodeWithToken(token, fasta.codeExpectedString) | 992 reportUnrecoverableErrorWithToken(token, fasta.templateExpectedString) |
993 .next; | 993 .next; |
994 } | 994 } |
995 listener.handleStringPart(token); | 995 listener.handleStringPart(token); |
996 return token.next; | 996 return token.next; |
997 } | 997 } |
998 | 998 |
999 Token parseIdentifier(Token token, IdentifierContext context) { | 999 Token parseIdentifier(Token token, IdentifierContext context) { |
1000 if (!token.isIdentifier) { | 1000 if (!token.isIdentifier) { |
1001 if (optional("void", token)) { | 1001 if (optional("void", token)) { |
1002 reportRecoverableErrorCode(token, fasta.codeInvalidVoid); | 1002 reportRecoverableError(token, fasta.messageInvalidVoid); |
1003 } else { | 1003 } else { |
1004 token = reportUnrecoverableErrorCodeWithToken( | 1004 token = reportUnrecoverableErrorWithToken( |
1005 token, fasta.codeExpectedIdentifier) | 1005 token, fasta.templateExpectedIdentifier) |
1006 .next; | 1006 .next; |
1007 } | 1007 } |
1008 } else if (token.type.isBuiltIn && !context.isBuiltInIdentifierAllowed) { | 1008 } else if (token.type.isBuiltIn && !context.isBuiltInIdentifierAllowed) { |
1009 if (context.inDeclaration) { | 1009 if (context.inDeclaration) { |
1010 reportRecoverableErrorCodeWithToken( | 1010 reportRecoverableErrorWithToken( |
1011 token, fasta.codeBuiltInIdentifierInDeclaration); | 1011 token, fasta.templateBuiltInIdentifierInDeclaration); |
1012 } else if (!optional("dynamic", token)) { | 1012 } else if (!optional("dynamic", token)) { |
1013 reportRecoverableErrorCodeWithToken( | 1013 reportRecoverableErrorWithToken( |
1014 token, fasta.codeBuiltInIdentifierAsType); | 1014 token, fasta.templateBuiltInIdentifierAsType); |
1015 } | 1015 } |
1016 } else if (!inPlainSync && token.type.isPseudo) { | 1016 } else if (!inPlainSync && token.type.isPseudo) { |
1017 if (optional('await', token)) { | 1017 if (optional('await', token)) { |
1018 reportRecoverableErrorCode(token, fasta.codeAwaitAsIdentifier); | 1018 reportRecoverableError(token, fasta.messageAwaitAsIdentifier); |
1019 } else if (optional('yield', token)) { | 1019 } else if (optional('yield', token)) { |
1020 reportRecoverableErrorCode(token, fasta.codeYieldAsIdentifier); | 1020 reportRecoverableError(token, fasta.messageYieldAsIdentifier); |
1021 } else if (optional('async', token)) { | 1021 } else if (optional('async', token)) { |
1022 reportRecoverableErrorCode(token, fasta.codeAsyncAsIdentifier); | 1022 reportRecoverableError(token, fasta.messageAsyncAsIdentifier); |
1023 } | 1023 } |
1024 } | 1024 } |
1025 listener.handleIdentifier(token, context); | 1025 listener.handleIdentifier(token, context); |
1026 return token.next; | 1026 return token.next; |
1027 } | 1027 } |
1028 | 1028 |
1029 Token expect(String string, Token token) { | 1029 Token expect(String string, Token token) { |
1030 if (!identical(string, token.stringValue)) { | 1030 if (!identical(string, token.stringValue)) { |
1031 return reportUnrecoverableErrorCodeWithString( | 1031 return reportUnrecoverableError( |
1032 token, fasta.codeExpectedButGot, string) | 1032 token, fasta.templateExpectedButGot.withArguments(string)) |
1033 .next; | 1033 .next; |
1034 } | 1034 } |
1035 return token.next; | 1035 return token.next; |
1036 } | 1036 } |
1037 | 1037 |
1038 Token parseTypeVariable(Token token) { | 1038 Token parseTypeVariable(Token token) { |
1039 listener.beginTypeVariable(token); | 1039 listener.beginTypeVariable(token); |
1040 token = parseMetadataStar(token); | 1040 token = parseMetadataStar(token); |
1041 token = parseIdentifier(token, IdentifierContext.typeVariableDeclaration); | 1041 token = parseIdentifier(token, IdentifierContext.typeVariableDeclaration); |
1042 Token extendsOrSuper = null; | 1042 Token extendsOrSuper = null; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 if (optional("<", token)) { | 1241 if (optional("<", token)) { |
1242 // Skip type parameters, they were parsed above. | 1242 // Skip type parameters, they were parsed above. |
1243 token = getClose(token).next; | 1243 token = getClose(token).next; |
1244 } | 1244 } |
1245 token = | 1245 token = |
1246 parseFormalParameters(token, MemberKind.GeneralizedFunctionType); | 1246 parseFormalParameters(token, MemberKind.GeneralizedFunctionType); |
1247 listener.endFunctionType(functionToken, token); | 1247 listener.endFunctionType(functionToken, token); |
1248 } | 1248 } |
1249 | 1249 |
1250 if (hasVar) { | 1250 if (hasVar) { |
1251 reportRecoverableErrorCode(begin, fasta.codeTypeAfterVar); | 1251 reportRecoverableError(begin, fasta.messageTypeAfterVar); |
1252 } | 1252 } |
1253 | 1253 |
1254 return token; | 1254 return token; |
1255 } | 1255 } |
1256 | 1256 |
1257 /// Returns true if [kind] is '=', ';', or ',', that is, if [kind] could be | 1257 /// Returns true if [kind] is '=', ';', or ',', that is, if [kind] could be |
1258 /// the end of a variable declaration. | 1258 /// the end of a variable declaration. |
1259 bool looksLikeVariableDeclarationEnd(int kind) { | 1259 bool looksLikeVariableDeclarationEnd(int kind) { |
1260 return EQ_TOKEN == kind || SEMICOLON_TOKEN == kind || COMMA_TOKEN == kind; | 1260 return EQ_TOKEN == kind || SEMICOLON_TOKEN == kind || COMMA_TOKEN == kind; |
1261 } | 1261 } |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 nameToken = token; | 1453 nameToken = token; |
1454 nameContext = IdentifierContext.fieldInitializer; | 1454 nameContext = IdentifierContext.fieldInitializer; |
1455 token = token.next; | 1455 token = token.next; |
1456 } else if (!nameToken.isIdentifier) { | 1456 } else if (!nameToken.isIdentifier) { |
1457 untyped = true; | 1457 untyped = true; |
1458 nameToken = begin; | 1458 nameToken = begin; |
1459 token = nameToken.next; | 1459 token = nameToken.next; |
1460 } | 1460 } |
1461 if (isNamedParameter && nameToken.lexeme.startsWith("_")) { | 1461 if (isNamedParameter && nameToken.lexeme.startsWith("_")) { |
1462 // TODO(ahe): Move this to after commiting the type. | 1462 // TODO(ahe): Move this to after commiting the type. |
1463 reportRecoverableErrorCode( | 1463 reportRecoverableError(nameToken, fasta.messagePrivateNamedParameter); |
1464 nameToken, fasta.codePrivateNamedParameter); | |
1465 } | 1464 } |
1466 | 1465 |
1467 token = listener.injectGenericCommentTypeList(token); | 1466 token = listener.injectGenericCommentTypeList(token); |
1468 | 1467 |
1469 Token inlineFunctionTypeStart; | 1468 Token inlineFunctionTypeStart; |
1470 if (optional("<", token)) { | 1469 if (optional("<", token)) { |
1471 Token closer = getClose(token); | 1470 Token closer = getClose(token); |
1472 if (closer != null) { | 1471 if (closer != null) { |
1473 if (optional("(", closer.next)) { | 1472 if (optional("(", closer.next)) { |
1474 inlineFunctionTypeStart = token; | 1473 inlineFunctionTypeStart = token; |
(...skipping 20 matching lines...) Expand all Loading... |
1495 listener.handleNoType(begin); | 1494 listener.handleNoType(begin); |
1496 } | 1495 } |
1497 token = | 1496 token = |
1498 parseFormalParameters(token, MemberKind.FunctionTypedParameter); | 1497 parseFormalParameters(token, MemberKind.FunctionTypedParameter); |
1499 listener.endFunctionTypedFormalParameter(); | 1498 listener.endFunctionTypedFormalParameter(); |
1500 | 1499 |
1501 // Generalized function types don't allow inline function types. | 1500 // Generalized function types don't allow inline function types. |
1502 // The following isn't allowed: | 1501 // The following isn't allowed: |
1503 // int Function(int bar(String x)). | 1502 // int Function(int bar(String x)). |
1504 if (memberKind == MemberKind.GeneralizedFunctionType) { | 1503 if (memberKind == MemberKind.GeneralizedFunctionType) { |
1505 reportRecoverableErrorCode( | 1504 reportRecoverableError(inlineFunctionTypeStart, |
1506 inlineFunctionTypeStart, fasta.codeInvalidInlineFunctionType); | 1505 fasta.messageInvalidInlineFunctionType); |
1507 } | 1506 } |
1508 } else if (untyped) { | 1507 } else if (untyped) { |
1509 listener.handleNoType(begin); | 1508 listener.handleNoType(begin); |
1510 } else { | 1509 } else { |
1511 Token saved = token; | 1510 Token saved = token; |
1512 commitType(); | 1511 commitType(); |
1513 token = saved; | 1512 token = saved; |
1514 } | 1513 } |
1515 | 1514 |
1516 if (nameContext != null) { | 1515 if (nameContext != null) { |
1517 parseIdentifier(nameToken, nameContext); | 1516 parseIdentifier(nameToken, nameContext); |
1518 } else { | 1517 } else { |
1519 listener.handleNoName(nameToken); | 1518 listener.handleNoName(nameToken); |
1520 } | 1519 } |
1521 | 1520 |
1522 String value = token.stringValue; | 1521 String value = token.stringValue; |
1523 if ((identical('=', value)) || (identical(':', value))) { | 1522 if ((identical('=', value)) || (identical(':', value))) { |
1524 Token equal = token; | 1523 Token equal = token; |
1525 token = parseExpression(token.next); | 1524 token = parseExpression(token.next); |
1526 listener.handleValuedFormalParameter(equal, token); | 1525 listener.handleValuedFormalParameter(equal, token); |
1527 if (parameterKind.isRequired) { | 1526 if (parameterKind.isRequired) { |
1528 reportRecoverableErrorCode( | 1527 reportRecoverableError( |
1529 equal, fasta.codeRequiredParameterWithDefault); | 1528 equal, fasta.messageRequiredParameterWithDefault); |
1530 } else if (parameterKind.isPositional && identical(':', value)) { | 1529 } else if (parameterKind.isPositional && identical(':', value)) { |
1531 reportRecoverableErrorCode( | 1530 reportRecoverableError( |
1532 equal, fasta.codePositionalParameterWithEquals); | 1531 equal, fasta.messagePositionalParameterWithEquals); |
1533 } else if (inFunctionType || | 1532 } else if (inFunctionType || |
1534 memberKind == MemberKind.FunctionTypeAlias || | 1533 memberKind == MemberKind.FunctionTypeAlias || |
1535 memberKind == MemberKind.FunctionTypedParameter) { | 1534 memberKind == MemberKind.FunctionTypedParameter) { |
1536 reportRecoverableErrorCode( | 1535 reportRecoverableError( |
1537 equal.next, fasta.codeFunctionTypeDefaultValue); | 1536 equal.next, fasta.messageFunctionTypeDefaultValue); |
1538 } | 1537 } |
1539 } else { | 1538 } else { |
1540 listener.handleFormalParameterWithoutValue(token); | 1539 listener.handleFormalParameterWithoutValue(token); |
1541 } | 1540 } |
1542 listener.endFormalParameter( | 1541 listener.endFormalParameter( |
1543 thisKeyword, nameToken, parameterKind, memberKind); | 1542 thisKeyword, nameToken, parameterKind, memberKind); |
1544 | 1543 |
1545 return token; | 1544 return token; |
1546 } | 1545 } |
1547 | 1546 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1590 handleNoStuff(token); | 1589 handleNoStuff(token); |
1591 return token; | 1590 return token; |
1592 } | 1591 } |
1593 | 1592 |
1594 Token parseTopLevelMember(Token token) { | 1593 Token parseTopLevelMember(Token token) { |
1595 Token start = token; | 1594 Token start = token; |
1596 listener.beginTopLevelMember(token); | 1595 listener.beginTopLevelMember(token); |
1597 | 1596 |
1598 Link<Token> identifiers = findMemberName(token); | 1597 Link<Token> identifiers = findMemberName(token); |
1599 if (identifiers.isEmpty) { | 1598 if (identifiers.isEmpty) { |
1600 return reportUnrecoverableErrorCodeWithToken( | 1599 return reportUnrecoverableErrorWithToken( |
1601 start, fasta.codeExpectedDeclaration) | 1600 start, fasta.templateExpectedDeclaration) |
1602 .next; | 1601 .next; |
1603 } | 1602 } |
1604 Token afterName = identifiers.head; | 1603 Token afterName = identifiers.head; |
1605 identifiers = identifiers.tail; | 1604 identifiers = identifiers.tail; |
1606 | 1605 |
1607 if (identifiers.isEmpty) { | 1606 if (identifiers.isEmpty) { |
1608 return reportUnrecoverableErrorCodeWithToken( | 1607 return reportUnrecoverableErrorWithToken( |
1609 start, fasta.codeExpectedDeclaration) | 1608 start, fasta.templateExpectedDeclaration) |
1610 .next; | 1609 .next; |
1611 } | 1610 } |
1612 Token name = identifiers.head; | 1611 Token name = identifiers.head; |
1613 identifiers = identifiers.tail; | 1612 identifiers = identifiers.tail; |
1614 Token getOrSet; | 1613 Token getOrSet; |
1615 if (!identifiers.isEmpty) { | 1614 if (!identifiers.isEmpty) { |
1616 String value = identifiers.head.stringValue; | 1615 String value = identifiers.head.stringValue; |
1617 if ((identical(value, 'get')) || (identical(value, 'set'))) { | 1616 if ((identical(value, 'get')) || (identical(value, 'set'))) { |
1618 getOrSet = identifiers.head; | 1617 getOrSet = identifiers.head; |
1619 identifiers = identifiers.tail; | 1618 identifiers = identifiers.tail; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1671 optional("const", modifier)) { | 1670 optional("const", modifier)) { |
1672 varFinalOrConst = modifier; | 1671 varFinalOrConst = modifier; |
1673 break; | 1672 break; |
1674 } | 1673 } |
1675 } | 1674 } |
1676 Token token = parseModifiers(start, | 1675 Token token = parseModifiers(start, |
1677 isTopLevel ? MemberKind.TopLevelField : MemberKind.NonStaticField, | 1676 isTopLevel ? MemberKind.TopLevelField : MemberKind.NonStaticField, |
1678 isVarAllowed: true); | 1677 isVarAllowed: true); |
1679 | 1678 |
1680 if (token != name) { | 1679 if (token != name) { |
1681 reportRecoverableErrorCodeWithToken(token, fasta.codeExtraneousModifier); | 1680 reportRecoverableErrorWithToken(token, fasta.templateExtraneousModifier); |
1682 token = name; | 1681 token = name; |
1683 } | 1682 } |
1684 | 1683 |
1685 IdentifierContext context = isTopLevel | 1684 IdentifierContext context = isTopLevel |
1686 ? IdentifierContext.topLevelVariableDeclaration | 1685 ? IdentifierContext.topLevelVariableDeclaration |
1687 : IdentifierContext.fieldDeclaration; | 1686 : IdentifierContext.fieldDeclaration; |
1688 token = parseIdentifier(token, context); | 1687 token = parseIdentifier(token, context); |
1689 | 1688 |
1690 int fieldCount = 1; | 1689 int fieldCount = 1; |
1691 token = parseFieldInitializerOpt(token, name, varFinalOrConst, isTopLevel); | 1690 token = parseFieldInitializerOpt(token, name, varFinalOrConst, isTopLevel); |
(...skipping 17 matching lines...) Expand all Loading... |
1709 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, | 1708 Token parseTopLevelMethod(Token start, Link<Token> modifiers, Token type, |
1710 Token getOrSet, Token name) { | 1709 Token getOrSet, Token name) { |
1711 listener.beginTopLevelMethod(start, name); | 1710 listener.beginTopLevelMethod(start, name); |
1712 Token externalModifier; | 1711 Token externalModifier; |
1713 // TODO(johnniwinther): Move error reporting to resolution to give more | 1712 // TODO(johnniwinther): Move error reporting to resolution to give more |
1714 // specific error messages. | 1713 // specific error messages. |
1715 for (Token modifier in modifiers) { | 1714 for (Token modifier in modifiers) { |
1716 if (externalModifier == null && optional('external', modifier)) { | 1715 if (externalModifier == null && optional('external', modifier)) { |
1717 externalModifier = modifier; | 1716 externalModifier = modifier; |
1718 } else { | 1717 } else { |
1719 reportRecoverableErrorCodeWithToken( | 1718 reportRecoverableErrorWithToken( |
1720 modifier, fasta.codeExtraneousModifier); | 1719 modifier, fasta.templateExtraneousModifier); |
1721 } | 1720 } |
1722 } | 1721 } |
1723 if (externalModifier != null) { | 1722 if (externalModifier != null) { |
1724 parseModifier(externalModifier); | 1723 parseModifier(externalModifier); |
1725 listener.handleModifiers(1); | 1724 listener.handleModifiers(1); |
1726 } else { | 1725 } else { |
1727 listener.handleModifiers(0); | 1726 listener.handleModifiers(0); |
1728 } | 1727 } |
1729 | 1728 |
1730 if (type == null) { | 1729 if (type == null) { |
(...skipping 10 matching lines...) Expand all Loading... |
1741 } else { | 1740 } else { |
1742 isGetter = optional("get", getOrSet); | 1741 isGetter = optional("get", getOrSet); |
1743 listener.handleNoTypeVariables(token); | 1742 listener.handleNoTypeVariables(token); |
1744 } | 1743 } |
1745 checkFormals(isGetter, name, token); | 1744 checkFormals(isGetter, name, token); |
1746 token = parseFormalParametersOpt(token, MemberKind.TopLevelMethod); | 1745 token = parseFormalParametersOpt(token, MemberKind.TopLevelMethod); |
1747 AsyncModifier savedAsyncModifier = asyncState; | 1746 AsyncModifier savedAsyncModifier = asyncState; |
1748 Token asyncToken = token; | 1747 Token asyncToken = token; |
1749 token = parseAsyncModifier(token); | 1748 token = parseAsyncModifier(token); |
1750 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { | 1749 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { |
1751 reportRecoverableErrorCode(asyncToken, fasta.codeSetterNotSync); | 1750 reportRecoverableError(asyncToken, fasta.messageSetterNotSync); |
1752 } | 1751 } |
1753 token = parseFunctionBody(token, false, externalModifier != null); | 1752 token = parseFunctionBody(token, false, externalModifier != null); |
1754 asyncState = savedAsyncModifier; | 1753 asyncState = savedAsyncModifier; |
1755 Token endToken = token; | 1754 Token endToken = token; |
1756 token = token.next; | 1755 token = token.next; |
1757 listener.endTopLevelMethod(start, getOrSet, endToken); | 1756 listener.endTopLevelMethod(start, getOrSet, endToken); |
1758 return token; | 1757 return token; |
1759 } | 1758 } |
1760 | 1759 |
1761 void checkFormals(bool isGetter, Token name, Token token) { | 1760 void checkFormals(bool isGetter, Token name, Token token) { |
1762 if (optional("(", token)) { | 1761 if (optional("(", token)) { |
1763 if (isGetter) { | 1762 if (isGetter) { |
1764 reportRecoverableErrorCode(token, fasta.codeGetterWithFormals); | 1763 reportRecoverableError(token, fasta.messageGetterWithFormals); |
1765 } | 1764 } |
1766 } else if (!isGetter) { | 1765 } else if (!isGetter) { |
1767 reportRecoverableErrorCodeWithToken(name, fasta.codeNoFormals); | 1766 reportRecoverableErrorWithToken(name, fasta.templateNoFormals); |
1768 } | 1767 } |
1769 } | 1768 } |
1770 | 1769 |
1771 /// Looks ahead to find the name of a member. Returns a link of the modifiers, | 1770 /// Looks ahead to find the name of a member. Returns a link of the modifiers, |
1772 /// set/get, (operator) name, and either the start of the method body or the | 1771 /// set/get, (operator) name, and either the start of the method body or the |
1773 /// end of the declaration. | 1772 /// end of the declaration. |
1774 /// | 1773 /// |
1775 /// Examples: | 1774 /// Examples: |
1776 /// | 1775 /// |
1777 /// int get foo; | 1776 /// int get foo; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1882 BeginToken beginGroup = token; | 1881 BeginToken beginGroup = token; |
1883 if (beginGroup.endGroup == null) { | 1882 if (beginGroup.endGroup == null) { |
1884 token = reportUnmatchedToken(beginGroup).next; | 1883 token = reportUnmatchedToken(beginGroup).next; |
1885 } else { | 1884 } else { |
1886 token = beginGroup.endGroup.next; | 1885 token = beginGroup.endGroup.next; |
1887 } | 1886 } |
1888 } | 1887 } |
1889 } | 1888 } |
1890 if (!optional('(', token)) { | 1889 if (!optional('(', token)) { |
1891 if (optional(';', token)) { | 1890 if (optional(';', token)) { |
1892 reportRecoverableErrorCode(token, fasta.codeExpectedOpenParens); | 1891 reportRecoverableError(token, fasta.messageExpectedOpenParens); |
1893 } | 1892 } |
1894 token = expect("(", token); | 1893 token = expect("(", token); |
1895 } | 1894 } |
1896 if (token is BeginToken) { | 1895 if (token is BeginToken) { |
1897 BeginToken beginGroup = token; | 1896 BeginToken beginGroup = token; |
1898 if (beginGroup.endGroup == null) { | 1897 if (beginGroup.endGroup == null) { |
1899 token = reportUnmatchedToken(beginGroup).next; | 1898 token = reportUnmatchedToken(beginGroup).next; |
1900 } else { | 1899 } else { |
1901 token = beginGroup.endGroup.next; | 1900 token = beginGroup.endGroup.next; |
1902 } | 1901 } |
1903 } | 1902 } |
1904 } | 1903 } |
1905 } | 1904 } |
1906 return listener.handleMemberName(const Link<Token>()); | 1905 return listener.handleMemberName(const Link<Token>()); |
1907 } | 1906 } |
1908 | 1907 |
1909 Token parseFieldInitializerOpt( | 1908 Token parseFieldInitializerOpt( |
1910 Token token, Token name, Token varFinalOrConst, bool isTopLevel) { | 1909 Token token, Token name, Token varFinalOrConst, bool isTopLevel) { |
1911 if (optional('=', token)) { | 1910 if (optional('=', token)) { |
1912 Token assignment = token; | 1911 Token assignment = token; |
1913 listener.beginFieldInitializer(token); | 1912 listener.beginFieldInitializer(token); |
1914 token = parseExpression(token.next); | 1913 token = parseExpression(token.next); |
1915 listener.endFieldInitializer(assignment, token); | 1914 listener.endFieldInitializer(assignment, token); |
1916 } else { | 1915 } else { |
1917 if (varFinalOrConst != null) { | 1916 if (varFinalOrConst != null) { |
1918 if (optional("const", varFinalOrConst)) { | 1917 if (optional("const", varFinalOrConst)) { |
1919 reportRecoverableErrorCode( | 1918 reportRecoverableError( |
1920 name, fasta.codeConstFieldWithoutInitializer); | 1919 name, fasta.messageConstFieldWithoutInitializer); |
1921 } else if (isTopLevel && optional("final", varFinalOrConst)) { | 1920 } else if (isTopLevel && optional("final", varFinalOrConst)) { |
1922 reportRecoverableErrorCode( | 1921 reportRecoverableError( |
1923 name, fasta.codeFinalFieldWithoutInitializer); | 1922 name, fasta.messageFinalFieldWithoutInitializer); |
1924 } | 1923 } |
1925 } | 1924 } |
1926 listener.handleNoFieldInitializer(token); | 1925 listener.handleNoFieldInitializer(token); |
1927 } | 1926 } |
1928 return token; | 1927 return token; |
1929 } | 1928 } |
1930 | 1929 |
1931 Token parseVariableInitializerOpt(Token token) { | 1930 Token parseVariableInitializerOpt(Token token) { |
1932 if (optional('=', token)) { | 1931 if (optional('=', token)) { |
1933 Token assignment = token; | 1932 Token assignment = token; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1972 } else { | 1971 } else { |
1973 token = parseExpression(token); | 1972 token = parseExpression(token); |
1974 } | 1973 } |
1975 listener.endInitializer(token); | 1974 listener.endInitializer(token); |
1976 return token; | 1975 return token; |
1977 } | 1976 } |
1978 | 1977 |
1979 Token parseLiteralStringOrRecoverExpression(Token token) { | 1978 Token parseLiteralStringOrRecoverExpression(Token token) { |
1980 if (identical(token.kind, STRING_TOKEN)) { | 1979 if (identical(token.kind, STRING_TOKEN)) { |
1981 return parseLiteralString(token); | 1980 return parseLiteralString(token); |
| 1981 } else if (token is ErrorToken) { |
| 1982 return reportErrorToken(token, false); |
1982 } else { | 1983 } else { |
1983 reportRecoverableErrorCodeWithToken(token, fasta.codeExpectedString); | 1984 reportRecoverableErrorWithToken(token, fasta.templateExpectedString); |
1984 return parseRecoverExpression( | 1985 return parseRecoverExpression( |
1985 token, fasta.codeExpectedString.format(uri, token.charOffset, token)); | 1986 token, fasta.templateExpectedString.withArguments(token)); |
1986 } | 1987 } |
1987 } | 1988 } |
1988 | 1989 |
1989 Token expectSemicolon(Token token) { | 1990 Token expectSemicolon(Token token) { |
1990 return expect(';', token); | 1991 return expect(';', token); |
1991 } | 1992 } |
1992 | 1993 |
1993 bool isModifier(Token token) => modifierOrder(token) < 127; | 1994 bool isModifier(Token token) => modifierOrder(token) < 127; |
1994 | 1995 |
1995 /// Provides a partial order on modifiers. | 1996 /// Provides a partial order on modifiers. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2049 break; | 2050 break; |
2050 } | 2051 } |
2051 } | 2052 } |
2052 int order = modifierOrder(token); | 2053 int order = modifierOrder(token); |
2053 if (order < 3) { | 2054 if (order < 3) { |
2054 // `abstract` isn't parsed with this method. | 2055 // `abstract` isn't parsed with this method. |
2055 if (order > currentOrder) { | 2056 if (order > currentOrder) { |
2056 currentOrder = order; | 2057 currentOrder = order; |
2057 if (optional("var", token)) { | 2058 if (optional("var", token)) { |
2058 if (!isVarAllowed && parameterKind == null) { | 2059 if (!isVarAllowed && parameterKind == null) { |
2059 reportRecoverableErrorCodeWithToken( | 2060 reportRecoverableErrorWithToken( |
2060 token, fasta.codeExtraneousModifier); | 2061 token, fasta.templateExtraneousModifier); |
2061 } | 2062 } |
2062 switch (typeContinuation ?? TypeContinuation.Required) { | 2063 switch (typeContinuation ?? TypeContinuation.Required) { |
2063 case TypeContinuation.NormalFormalParameter: | 2064 case TypeContinuation.NormalFormalParameter: |
2064 typeContinuation = | 2065 typeContinuation = |
2065 TypeContinuation.NormalFormalParameterAfterVar; | 2066 TypeContinuation.NormalFormalParameterAfterVar; |
2066 break; | 2067 break; |
2067 | 2068 |
2068 case TypeContinuation.OptionalPositionalFormalParameter: | 2069 case TypeContinuation.OptionalPositionalFormalParameter: |
2069 typeContinuation = | 2070 typeContinuation = |
2070 TypeContinuation.OptionalPositionalFormalParameterAfterVar; | 2071 TypeContinuation.OptionalPositionalFormalParameterAfterVar; |
2071 break; | 2072 break; |
2072 | 2073 |
2073 case TypeContinuation.NamedFormalParameter: | 2074 case TypeContinuation.NamedFormalParameter: |
2074 typeContinuation = | 2075 typeContinuation = |
2075 TypeContinuation.NamedFormalParameterAfterVar; | 2076 TypeContinuation.NamedFormalParameterAfterVar; |
2076 break; | 2077 break; |
2077 | 2078 |
2078 default: | 2079 default: |
2079 typeContinuation = TypeContinuation.OptionalAfterVar; | 2080 typeContinuation = TypeContinuation.OptionalAfterVar; |
2080 break; | 2081 break; |
2081 } | 2082 } |
2082 } else if (optional("final", token)) { | 2083 } else if (optional("final", token)) { |
2083 if (!isVarAllowed && parameterKind == null) { | 2084 if (!isVarAllowed && parameterKind == null) { |
2084 reportRecoverableErrorCodeWithToken( | 2085 reportRecoverableErrorWithToken( |
2085 token, fasta.codeExtraneousModifier); | 2086 token, fasta.templateExtraneousModifier); |
2086 } | 2087 } |
2087 typeContinuation ??= TypeContinuation.Optional; | 2088 typeContinuation ??= TypeContinuation.Optional; |
2088 } else if (optional("const", token)) { | 2089 } else if (optional("const", token)) { |
2089 if (!isVarAllowed) { | 2090 if (!isVarAllowed) { |
2090 reportRecoverableErrorCodeWithToken( | 2091 reportRecoverableErrorWithToken( |
2091 token, fasta.codeExtraneousModifier); | 2092 token, fasta.templateExtraneousModifier); |
2092 } | 2093 } |
2093 typeContinuation ??= TypeContinuation.Optional; | 2094 typeContinuation ??= TypeContinuation.Optional; |
2094 } else if (optional("static", token)) { | 2095 } else if (optional("static", token)) { |
2095 if (parameterKind != null) { | 2096 if (parameterKind != null) { |
2096 reportRecoverableErrorCodeWithToken( | 2097 reportRecoverableErrorWithToken( |
2097 token, fasta.codeExtraneousModifier); | 2098 token, fasta.templateExtraneousModifier); |
2098 } else if (memberKind == MemberKind.NonStaticMethod) { | 2099 } else if (memberKind == MemberKind.NonStaticMethod) { |
2099 memberKind = MemberKind.StaticMethod; | 2100 memberKind = MemberKind.StaticMethod; |
2100 } else if (memberKind == MemberKind.NonStaticField) { | 2101 } else if (memberKind == MemberKind.NonStaticField) { |
2101 memberKind = MemberKind.StaticField; | 2102 memberKind = MemberKind.StaticField; |
2102 } else { | 2103 } else { |
2103 reportRecoverableErrorCodeWithToken( | 2104 reportRecoverableErrorWithToken( |
2104 token, fasta.codeExtraneousModifier); | 2105 token, fasta.templateExtraneousModifier); |
2105 token = token.next; | 2106 token = token.next; |
2106 continue; | 2107 continue; |
2107 } | 2108 } |
2108 } else if (optional("covariant", token)) { | 2109 } else if (optional("covariant", token)) { |
2109 switch (memberKind) { | 2110 switch (memberKind) { |
2110 case MemberKind.StaticField: | 2111 case MemberKind.StaticField: |
2111 case MemberKind.StaticMethod: | 2112 case MemberKind.StaticMethod: |
2112 case MemberKind.TopLevelField: | 2113 case MemberKind.TopLevelField: |
2113 case MemberKind.TopLevelMethod: | 2114 case MemberKind.TopLevelMethod: |
2114 reportRecoverableErrorCodeWithToken( | 2115 reportRecoverableErrorWithToken( |
2115 token, fasta.codeExtraneousModifier); | 2116 token, fasta.templateExtraneousModifier); |
2116 token = token.next; | 2117 token = token.next; |
2117 continue; | 2118 continue; |
2118 | 2119 |
2119 default: | 2120 default: |
2120 break; | 2121 break; |
2121 } | 2122 } |
2122 } else if (optional("external", token)) { | 2123 } else if (optional("external", token)) { |
2123 switch (memberKind) { | 2124 switch (memberKind) { |
2124 case MemberKind.Factory: | 2125 case MemberKind.Factory: |
2125 case MemberKind.NonStaticMethod: | 2126 case MemberKind.NonStaticMethod: |
2126 case MemberKind.StaticMethod: | 2127 case MemberKind.StaticMethod: |
2127 case MemberKind.TopLevelMethod: | 2128 case MemberKind.TopLevelMethod: |
2128 break; | 2129 break; |
2129 | 2130 |
2130 default: | 2131 default: |
2131 reportRecoverableErrorCodeWithToken( | 2132 reportRecoverableErrorWithToken( |
2132 token, fasta.codeExtraneousModifier); | 2133 token, fasta.templateExtraneousModifier); |
2133 token = token.next; | 2134 token = token.next; |
2134 continue; | 2135 continue; |
2135 } | 2136 } |
2136 } | 2137 } |
2137 token = parseModifier(token); | 2138 token = parseModifier(token); |
2138 count++; | 2139 count++; |
2139 } else { | 2140 } else { |
2140 reportRecoverableErrorCodeWithToken( | 2141 reportRecoverableErrorWithToken( |
2141 token, fasta.codeExtraneousModifier); | 2142 token, fasta.templateExtraneousModifier); |
2142 token = token.next; | 2143 token = token.next; |
2143 } | 2144 } |
2144 } else { | 2145 } else { |
2145 break; | 2146 break; |
2146 } | 2147 } |
2147 } | 2148 } |
2148 listener.handleModifiers(count); | 2149 listener.handleModifiers(count); |
2149 | 2150 |
2150 typeContinuation ??= | 2151 typeContinuation ??= |
2151 (isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType) | 2152 (isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType) |
2152 ? TypeContinuation.Required | 2153 ? TypeContinuation.Required |
2153 : TypeContinuation.Optional; | 2154 : TypeContinuation.Optional; |
2154 | 2155 |
2155 token = parseType(token, typeContinuation, null, memberKind); | 2156 token = parseType(token, typeContinuation, null, memberKind); |
2156 return token; | 2157 return token; |
2157 } | 2158 } |
2158 | 2159 |
2159 Token skipClassBody(Token token) { | 2160 Token skipClassBody(Token token) { |
2160 if (!optional('{', token)) { | 2161 if (!optional('{', token)) { |
2161 return reportUnrecoverableErrorCodeWithToken( | 2162 return reportUnrecoverableErrorWithToken( |
2162 token, fasta.codeExpectedClassBodyToSkip) | 2163 token, fasta.templateExpectedClassBodyToSkip) |
2163 .next; | 2164 .next; |
2164 } | 2165 } |
2165 BeginToken beginGroupToken = token; | 2166 BeginToken beginGroupToken = token; |
2166 Token endGroup = beginGroupToken.endGroup; | 2167 Token endGroup = beginGroupToken.endGroup; |
2167 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | 2168 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
2168 return reportUnmatchedToken(beginGroupToken).next; | 2169 return reportUnmatchedToken(beginGroupToken).next; |
2169 } | 2170 } |
2170 return endGroup; | 2171 return endGroup; |
2171 } | 2172 } |
2172 | 2173 |
2173 Token parseClassBody(Token token) { | 2174 Token parseClassBody(Token token) { |
2174 Token begin = token; | 2175 Token begin = token; |
2175 listener.beginClassBody(token); | 2176 listener.beginClassBody(token); |
2176 if (!optional('{', token)) { | 2177 if (!optional('{', token)) { |
2177 token = reportUnrecoverableErrorCodeWithToken( | 2178 token = reportUnrecoverableErrorWithToken( |
2178 token, fasta.codeExpectedClassBody) | 2179 token, fasta.templateExpectedClassBody) |
2179 .next; | 2180 .next; |
2180 } | 2181 } |
2181 token = token.next; | 2182 token = token.next; |
2182 int count = 0; | 2183 int count = 0; |
2183 while (notEofOrValue('}', token)) { | 2184 while (notEofOrValue('}', token)) { |
2184 token = parseMember(token); | 2185 token = parseMember(token); |
2185 ++count; | 2186 ++count; |
2186 } | 2187 } |
2187 expect('}', token); | 2188 expect('}', token); |
2188 listener.endClassBody(count, begin, token); | 2189 listener.endClassBody(count, begin, token); |
(...skipping 17 matching lines...) Expand all Loading... |
2206 listener.beginMember(token); | 2207 listener.beginMember(token); |
2207 if (isFactoryDeclaration(token)) { | 2208 if (isFactoryDeclaration(token)) { |
2208 token = parseFactoryMethod(token); | 2209 token = parseFactoryMethod(token); |
2209 listener.endMember(); | 2210 listener.endMember(); |
2210 assert(token != null); | 2211 assert(token != null); |
2211 return token; | 2212 return token; |
2212 } | 2213 } |
2213 | 2214 |
2214 Link<Token> identifiers = findMemberName(token); | 2215 Link<Token> identifiers = findMemberName(token); |
2215 if (identifiers.isEmpty) { | 2216 if (identifiers.isEmpty) { |
2216 return reportUnrecoverableErrorCodeWithToken( | 2217 return reportUnrecoverableErrorWithToken( |
2217 start, fasta.codeExpectedDeclaration) | 2218 start, fasta.templateExpectedDeclaration) |
2218 .next; | 2219 .next; |
2219 } | 2220 } |
2220 Token afterName = identifiers.head; | 2221 Token afterName = identifiers.head; |
2221 identifiers = identifiers.tail; | 2222 identifiers = identifiers.tail; |
2222 | 2223 |
2223 if (identifiers.isEmpty) { | 2224 if (identifiers.isEmpty) { |
2224 return reportUnrecoverableErrorCodeWithToken( | 2225 return reportUnrecoverableErrorWithToken( |
2225 start, fasta.codeExpectedDeclaration) | 2226 start, fasta.templateExpectedDeclaration) |
2226 .next; | 2227 .next; |
2227 } | 2228 } |
2228 Token name = identifiers.head; | 2229 Token name = identifiers.head; |
2229 identifiers = identifiers.tail; | 2230 identifiers = identifiers.tail; |
2230 if (!identifiers.isEmpty) { | 2231 if (!identifiers.isEmpty) { |
2231 if (optional('operator', identifiers.head)) { | 2232 if (optional('operator', identifiers.head)) { |
2232 name = identifiers.head; | 2233 name = identifiers.head; |
2233 identifiers = identifiers.tail; | 2234 identifiers = identifiers.tail; |
2234 } | 2235 } |
2235 } | 2236 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2299 | 2300 |
2300 Token externalModifier; | 2301 Token externalModifier; |
2301 Token staticModifier; | 2302 Token staticModifier; |
2302 // TODO(ahe): Consider using [parseModifiers] instead. | 2303 // TODO(ahe): Consider using [parseModifiers] instead. |
2303 void parseModifierList(Link<Token> tokens) { | 2304 void parseModifierList(Link<Token> tokens) { |
2304 int count = 0; | 2305 int count = 0; |
2305 int currentOrder = -1; | 2306 int currentOrder = -1; |
2306 for (; !tokens.isEmpty; tokens = tokens.tail) { | 2307 for (; !tokens.isEmpty; tokens = tokens.tail) { |
2307 Token token = tokens.head; | 2308 Token token = tokens.head; |
2308 if (optional("abstract", token)) { | 2309 if (optional("abstract", token)) { |
2309 reportRecoverableErrorCodeWithToken( | 2310 reportRecoverableErrorWithToken( |
2310 token, fasta.codeExtraneousModifier); | 2311 token, fasta.templateExtraneousModifier); |
2311 continue; | 2312 continue; |
2312 } | 2313 } |
2313 int order = modifierOrder(token); | 2314 int order = modifierOrder(token); |
2314 if (order < 127) { | 2315 if (order < 127) { |
2315 if (order > currentOrder) { | 2316 if (order > currentOrder) { |
2316 currentOrder = order; | 2317 currentOrder = order; |
2317 if (optional("var", token)) { | 2318 if (optional("var", token)) { |
2318 reportRecoverableErrorCodeWithToken( | 2319 reportRecoverableErrorWithToken( |
2319 token, fasta.codeExtraneousModifier); | 2320 token, fasta.templateExtraneousModifier); |
2320 } else if (optional("const", token)) { | 2321 } else if (optional("const", token)) { |
2321 if (getOrSet != null) { | 2322 if (getOrSet != null) { |
2322 reportRecoverableErrorCodeWithToken( | 2323 reportRecoverableErrorWithToken( |
2323 token, fasta.codeExtraneousModifier); | 2324 token, fasta.templateExtraneousModifier); |
2324 continue; | 2325 continue; |
2325 } | 2326 } |
2326 } else if (optional("external", token)) { | 2327 } else if (optional("external", token)) { |
2327 externalModifier = token; | 2328 externalModifier = token; |
2328 } else if (optional("static", token)) { | 2329 } else if (optional("static", token)) { |
2329 staticModifier = token; | 2330 staticModifier = token; |
2330 } else if (optional("covariant", token)) { | 2331 } else if (optional("covariant", token)) { |
2331 if (staticModifier != null || | 2332 if (staticModifier != null || |
2332 getOrSet == null || | 2333 getOrSet == null || |
2333 optional("get", getOrSet)) { | 2334 optional("get", getOrSet)) { |
2334 reportRecoverableErrorCodeWithToken( | 2335 reportRecoverableErrorWithToken( |
2335 token, fasta.codeExtraneousModifier); | 2336 token, fasta.templateExtraneousModifier); |
2336 continue; | 2337 continue; |
2337 } | 2338 } |
2338 } | 2339 } |
2339 } else { | 2340 } else { |
2340 reportRecoverableErrorCodeWithToken( | 2341 reportRecoverableErrorWithToken( |
2341 token, fasta.codeExtraneousModifier); | 2342 token, fasta.templateExtraneousModifier); |
2342 continue; | 2343 continue; |
2343 } | 2344 } |
2344 } else { | 2345 } else { |
2345 reportUnexpectedToken(token); | 2346 reportUnexpectedToken(token); |
2346 break; // Skip the remaining modifiers. | 2347 break; // Skip the remaining modifiers. |
2347 } | 2348 } |
2348 parseModifier(token); | 2349 parseModifier(token); |
2349 count++; | 2350 count++; |
2350 } | 2351 } |
2351 listener.handleModifiers(count); | 2352 listener.handleModifiers(count); |
2352 } | 2353 } |
2353 | 2354 |
2354 parseModifierList(modifiers); | 2355 parseModifierList(modifiers); |
2355 | 2356 |
2356 if (type == null) { | 2357 if (type == null) { |
2357 listener.handleNoType(name); | 2358 listener.handleNoType(name); |
2358 } else { | 2359 } else { |
2359 parseType(type, TypeContinuation.Optional); | 2360 parseType(type, TypeContinuation.Optional); |
2360 } | 2361 } |
2361 Token token; | 2362 Token token; |
2362 if (optional('operator', name)) { | 2363 if (optional('operator', name)) { |
2363 token = parseOperatorName(name); | 2364 token = parseOperatorName(name); |
2364 if (staticModifier != null) { | 2365 if (staticModifier != null) { |
2365 reportRecoverableErrorCodeWithToken( | 2366 reportRecoverableErrorWithToken( |
2366 staticModifier, fasta.codeExtraneousModifier); | 2367 staticModifier, fasta.templateExtraneousModifier); |
2367 } | 2368 } |
2368 } else { | 2369 } else { |
2369 token = parseIdentifier(name, IdentifierContext.methodDeclaration); | 2370 token = parseIdentifier(name, IdentifierContext.methodDeclaration); |
2370 } | 2371 } |
2371 | 2372 |
2372 token = parseQualifiedRestOpt( | 2373 token = parseQualifiedRestOpt( |
2373 token, IdentifierContext.methodDeclarationContinuation); | 2374 token, IdentifierContext.methodDeclarationContinuation); |
2374 bool isGetter = false; | 2375 bool isGetter = false; |
2375 if (getOrSet == null) { | 2376 if (getOrSet == null) { |
2376 token = parseTypeVariablesOpt(token); | 2377 token = parseTypeVariablesOpt(token); |
2377 } else { | 2378 } else { |
2378 isGetter = optional("get", getOrSet); | 2379 isGetter = optional("get", getOrSet); |
2379 listener.handleNoTypeVariables(token); | 2380 listener.handleNoTypeVariables(token); |
2380 } | 2381 } |
2381 checkFormals(isGetter, name, token); | 2382 checkFormals(isGetter, name, token); |
2382 token = parseFormalParametersOpt( | 2383 token = parseFormalParametersOpt( |
2383 token, | 2384 token, |
2384 staticModifier != null | 2385 staticModifier != null |
2385 ? MemberKind.StaticMethod | 2386 ? MemberKind.StaticMethod |
2386 : MemberKind.NonStaticMethod); | 2387 : MemberKind.NonStaticMethod); |
2387 token = parseInitializersOpt(token); | 2388 token = parseInitializersOpt(token); |
2388 AsyncModifier savedAsyncModifier = asyncState; | 2389 AsyncModifier savedAsyncModifier = asyncState; |
2389 Token asyncToken = token; | 2390 Token asyncToken = token; |
2390 token = parseAsyncModifier(token); | 2391 token = parseAsyncModifier(token); |
2391 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { | 2392 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { |
2392 reportRecoverableErrorCode(asyncToken, fasta.codeSetterNotSync); | 2393 reportRecoverableError(asyncToken, fasta.messageSetterNotSync); |
2393 } | 2394 } |
2394 if (optional('=', token)) { | 2395 if (optional('=', token)) { |
2395 token = parseRedirectingFactoryBody(token); | 2396 token = parseRedirectingFactoryBody(token); |
2396 } else { | 2397 } else { |
2397 token = parseFunctionBody( | 2398 token = parseFunctionBody( |
2398 token, false, staticModifier == null || externalModifier != null); | 2399 token, false, staticModifier == null || externalModifier != null); |
2399 } | 2400 } |
2400 asyncState = savedAsyncModifier; | 2401 asyncState = savedAsyncModifier; |
2401 listener.endMethod(getOrSet, start, token); | 2402 listener.endMethod(getOrSet, start, token); |
2402 return token.next; | 2403 return token.next; |
(...skipping 13 matching lines...) Expand all Loading... |
2416 } | 2417 } |
2417 listener.handleModifiers(modifierCount); | 2418 listener.handleModifiers(modifierCount); |
2418 Token factoryKeyword = token; | 2419 Token factoryKeyword = token; |
2419 listener.beginFactoryMethod(factoryKeyword); | 2420 listener.beginFactoryMethod(factoryKeyword); |
2420 token = expect('factory', token); | 2421 token = expect('factory', token); |
2421 token = parseConstructorReference(token); | 2422 token = parseConstructorReference(token); |
2422 token = parseFormalParameters(token, MemberKind.Factory); | 2423 token = parseFormalParameters(token, MemberKind.Factory); |
2423 Token asyncToken = token; | 2424 Token asyncToken = token; |
2424 token = parseAsyncModifier(token); | 2425 token = parseAsyncModifier(token); |
2425 if (!inPlainSync) { | 2426 if (!inPlainSync) { |
2426 reportRecoverableErrorCode(asyncToken, fasta.codeFactoryNotSync); | 2427 reportRecoverableError(asyncToken, fasta.messageFactoryNotSync); |
2427 } | 2428 } |
2428 if (optional('=', token)) { | 2429 if (optional('=', token)) { |
2429 token = parseRedirectingFactoryBody(token); | 2430 token = parseRedirectingFactoryBody(token); |
2430 } else { | 2431 } else { |
2431 token = parseFunctionBody(token, false, isExternal); | 2432 token = parseFunctionBody(token, false, isExternal); |
2432 } | 2433 } |
2433 listener.endFactoryMethod(start, factoryKeyword, token); | 2434 listener.endFactoryMethod(start, factoryKeyword, token); |
2434 return token.next; | 2435 return token.next; |
2435 } | 2436 } |
2436 | 2437 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2536 listener.endRedirectingFactoryBody(equals, semicolon); | 2537 listener.endRedirectingFactoryBody(equals, semicolon); |
2537 return token; | 2538 return token; |
2538 } | 2539 } |
2539 | 2540 |
2540 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 2541 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
2541 assert(!isExpression); | 2542 assert(!isExpression); |
2542 token = skipAsyncModifier(token); | 2543 token = skipAsyncModifier(token); |
2543 String value = token.stringValue; | 2544 String value = token.stringValue; |
2544 if (identical(value, ';')) { | 2545 if (identical(value, ';')) { |
2545 if (!allowAbstract) { | 2546 if (!allowAbstract) { |
2546 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2547 reportRecoverableError(token, fasta.messageExpectedBody); |
2547 } | 2548 } |
2548 listener.handleNoFunctionBody(token); | 2549 listener.handleNoFunctionBody(token); |
2549 } else { | 2550 } else { |
2550 if (identical(value, '=>')) { | 2551 if (identical(value, '=>')) { |
2551 token = parseExpression(token.next); | 2552 token = parseExpression(token.next); |
2552 expectSemicolon(token); | 2553 expectSemicolon(token); |
2553 listener.handleFunctionBodySkipped(token, true); | 2554 listener.handleFunctionBodySkipped(token, true); |
2554 } else if (identical(value, '=')) { | 2555 } else if (identical(value, '=')) { |
2555 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2556 reportRecoverableError(token, fasta.messageExpectedBody); |
2556 token = parseExpression(token.next); | 2557 token = parseExpression(token.next); |
2557 expectSemicolon(token); | 2558 expectSemicolon(token); |
2558 listener.handleFunctionBodySkipped(token, true); | 2559 listener.handleFunctionBodySkipped(token, true); |
2559 } else { | 2560 } else { |
2560 token = skipBlock(token); | 2561 token = skipBlock(token); |
2561 listener.handleFunctionBodySkipped(token, false); | 2562 listener.handleFunctionBodySkipped(token, false); |
2562 } | 2563 } |
2563 } | 2564 } |
2564 return token; | 2565 return token; |
2565 } | 2566 } |
2566 | 2567 |
2567 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 2568 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
2568 if (optional(';', token)) { | 2569 if (optional(';', token)) { |
2569 if (!allowAbstract) { | 2570 if (!allowAbstract) { |
2570 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2571 reportRecoverableError(token, fasta.messageExpectedBody); |
2571 } | 2572 } |
2572 listener.handleEmptyFunctionBody(token); | 2573 listener.handleEmptyFunctionBody(token); |
2573 return token; | 2574 return token; |
2574 } else if (optional('=>', token)) { | 2575 } else if (optional('=>', token)) { |
2575 Token begin = token; | 2576 Token begin = token; |
2576 token = parseExpression(token.next); | 2577 token = parseExpression(token.next); |
2577 if (!isExpression) { | 2578 if (!isExpression) { |
2578 expectSemicolon(token); | 2579 expectSemicolon(token); |
2579 listener.handleExpressionFunctionBody(begin, token); | 2580 listener.handleExpressionFunctionBody(begin, token); |
2580 } else { | 2581 } else { |
2581 listener.handleExpressionFunctionBody(begin, null); | 2582 listener.handleExpressionFunctionBody(begin, null); |
2582 } | 2583 } |
2583 return token; | 2584 return token; |
2584 } else if (optional('=', token)) { | 2585 } else if (optional('=', token)) { |
2585 Token begin = token; | 2586 Token begin = token; |
2586 // Recover from a bad factory method. | 2587 // Recover from a bad factory method. |
2587 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2588 reportRecoverableError(token, fasta.messageExpectedBody); |
2588 token = parseExpression(token.next); | 2589 token = parseExpression(token.next); |
2589 if (!isExpression) { | 2590 if (!isExpression) { |
2590 expectSemicolon(token); | 2591 expectSemicolon(token); |
2591 listener.handleExpressionFunctionBody(begin, token); | 2592 listener.handleExpressionFunctionBody(begin, token); |
2592 } else { | 2593 } else { |
2593 listener.handleExpressionFunctionBody(begin, null); | 2594 listener.handleExpressionFunctionBody(begin, null); |
2594 } | 2595 } |
2595 return token; | 2596 return token; |
2596 } | 2597 } |
2597 Token begin = token; | 2598 Token begin = token; |
2598 int statementCount = 0; | 2599 int statementCount = 0; |
2599 if (!optional('{', token)) { | 2600 if (!optional('{', token)) { |
2600 token = reportUnrecoverableErrorCodeWithToken( | 2601 token = reportUnrecoverableErrorWithToken( |
2601 token, fasta.codeExpectedFunctionBody) | 2602 token, fasta.templateExpectedFunctionBody) |
2602 .next; | 2603 .next; |
2603 listener.handleInvalidFunctionBody(token); | 2604 listener.handleInvalidFunctionBody(token); |
2604 return token; | 2605 return token; |
2605 } | 2606 } |
2606 | 2607 |
2607 listener.beginBlockFunctionBody(begin); | 2608 listener.beginBlockFunctionBody(begin); |
2608 token = token.next; | 2609 token = token.next; |
2609 while (notEofOrValue('}', token)) { | 2610 while (notEofOrValue('}', token)) { |
2610 token = parseStatement(token); | 2611 token = parseStatement(token); |
2611 ++statementCount; | 2612 ++statementCount; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2650 asyncState = AsyncModifier.Async; | 2651 asyncState = AsyncModifier.Async; |
2651 } | 2652 } |
2652 } else if (optional('sync', token)) { | 2653 } else if (optional('sync', token)) { |
2653 async = token; | 2654 async = token; |
2654 token = token.next; | 2655 token = token.next; |
2655 if (optional('*', token)) { | 2656 if (optional('*', token)) { |
2656 asyncState = AsyncModifier.SyncStar; | 2657 asyncState = AsyncModifier.SyncStar; |
2657 star = token; | 2658 star = token; |
2658 token = token.next; | 2659 token = token.next; |
2659 } else { | 2660 } else { |
2660 reportRecoverableErrorCode(async, fasta.codeInvalidSyncModifier); | 2661 reportRecoverableError(async, fasta.messageInvalidSyncModifier); |
2661 } | 2662 } |
2662 } | 2663 } |
2663 listener.handleAsyncModifier(async, star); | 2664 listener.handleAsyncModifier(async, star); |
2664 if (inGenerator && optional('=>', token)) { | 2665 if (inGenerator && optional('=>', token)) { |
2665 reportRecoverableErrorCode(token, fasta.codeGeneratorReturnsValue); | 2666 reportRecoverableError(token, fasta.messageGeneratorReturnsValue); |
2666 } else if (!inPlainSync && optional(';', token)) { | 2667 } else if (!inPlainSync && optional(';', token)) { |
2667 reportRecoverableErrorCode(token, fasta.codeAbstractNotSync); | 2668 reportRecoverableError(token, fasta.messageAbstractNotSync); |
2668 } | 2669 } |
2669 return token; | 2670 return token; |
2670 } | 2671 } |
2671 | 2672 |
2672 int statementDepth = 0; | 2673 int statementDepth = 0; |
2673 Token parseStatement(Token token) { | 2674 Token parseStatement(Token token) { |
2674 if (statementDepth++ > 500) { | 2675 if (statementDepth++ > 500) { |
2675 // This happens for degenerate programs, for example, a lot of nested | 2676 // This happens for degenerate programs, for example, a lot of nested |
2676 // if-statements. The language test deep_nesting2_negative_test, for | 2677 // if-statements. The language test deep_nesting2_negative_test, for |
2677 // example, provokes this. | 2678 // example, provokes this. |
2678 return reportUnrecoverableErrorCode(token, fasta.codeStackOverflow).next; | 2679 return reportUnrecoverableError(token, fasta.messageStackOverflow).next; |
2679 } | 2680 } |
2680 Token result = parseStatementX(token); | 2681 Token result = parseStatementX(token); |
2681 statementDepth--; | 2682 statementDepth--; |
2682 return result; | 2683 return result; |
2683 } | 2684 } |
2684 | 2685 |
2685 Token parseStatementX(Token token) { | 2686 Token parseStatementX(Token token) { |
2686 final value = token.stringValue; | 2687 final value = token.stringValue; |
2687 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 2688 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
2688 return parseExpressionStatementOrDeclaration(token); | 2689 return parseExpressionStatementOrDeclaration(token); |
2689 } else if (identical(value, '{')) { | 2690 } else if (identical(value, '{')) { |
2690 return parseBlock(token); | 2691 return parseBlock(token); |
2691 } else if (identical(value, 'return')) { | 2692 } else if (identical(value, 'return')) { |
2692 return parseReturnStatement(token); | 2693 return parseReturnStatement(token); |
2693 } else if (identical(value, 'var') || identical(value, 'final')) { | 2694 } else if (identical(value, 'var') || identical(value, 'final')) { |
2694 return parseVariablesDeclaration(token); | 2695 return parseVariablesDeclaration(token); |
2695 } else if (identical(value, 'if')) { | 2696 } else if (identical(value, 'if')) { |
2696 return parseIfStatement(token); | 2697 return parseIfStatement(token); |
2697 } else if (identical(value, 'await') && optional('for', token.next)) { | 2698 } else if (identical(value, 'await') && optional('for', token.next)) { |
2698 if (!inAsync) { | 2699 if (!inAsync) { |
2699 reportRecoverableErrorCode(token, fasta.codeAwaitForNotAsync); | 2700 reportRecoverableError(token, fasta.messageAwaitForNotAsync); |
2700 } | 2701 } |
2701 return parseForStatement(token, token.next); | 2702 return parseForStatement(token, token.next); |
2702 } else if (identical(value, 'for')) { | 2703 } else if (identical(value, 'for')) { |
2703 return parseForStatement(null, token); | 2704 return parseForStatement(null, token); |
2704 } else if (identical(value, 'rethrow')) { | 2705 } else if (identical(value, 'rethrow')) { |
2705 return parseRethrowStatement(token); | 2706 return parseRethrowStatement(token); |
2706 } else if (identical(value, 'throw') && optional(';', token.next)) { | 2707 } else if (identical(value, 'throw') && optional(';', token.next)) { |
2707 // TODO(kasperl): Stop dealing with throw here. | 2708 // TODO(kasperl): Stop dealing with throw here. |
2708 return parseRethrowStatement(token); | 2709 return parseRethrowStatement(token); |
2709 } else if (identical(value, 'void')) { | 2710 } else if (identical(value, 'void')) { |
(...skipping 17 matching lines...) Expand all Loading... |
2727 } else if (identical(value, 'yield')) { | 2728 } else if (identical(value, 'yield')) { |
2728 switch (asyncState) { | 2729 switch (asyncState) { |
2729 case AsyncModifier.Sync: | 2730 case AsyncModifier.Sync: |
2730 return parseExpressionStatementOrDeclaration(token); | 2731 return parseExpressionStatementOrDeclaration(token); |
2731 | 2732 |
2732 case AsyncModifier.SyncStar: | 2733 case AsyncModifier.SyncStar: |
2733 case AsyncModifier.AsyncStar: | 2734 case AsyncModifier.AsyncStar: |
2734 return parseYieldStatement(token); | 2735 return parseYieldStatement(token); |
2735 | 2736 |
2736 case AsyncModifier.Async: | 2737 case AsyncModifier.Async: |
2737 reportRecoverableErrorCode(token, fasta.codeYieldNotGenerator); | 2738 reportRecoverableError(token, fasta.messageYieldNotGenerator); |
2738 return parseYieldStatement(token); | 2739 return parseYieldStatement(token); |
2739 } | 2740 } |
2740 throw "Internal error: Unknown asyncState: '$asyncState'."; | 2741 throw "Internal error: Unknown asyncState: '$asyncState'."; |
2741 } else if (identical(value, 'const')) { | 2742 } else if (identical(value, 'const')) { |
2742 return parseExpressionStatementOrConstDeclaration(token); | 2743 return parseExpressionStatementOrConstDeclaration(token); |
2743 } else if (token.isIdentifier) { | 2744 } else if (token.isIdentifier) { |
2744 return parseExpressionStatementOrDeclaration(token); | 2745 return parseExpressionStatementOrDeclaration(token); |
2745 } else if (identical(value, '@')) { | 2746 } else if (identical(value, '@')) { |
2746 return parseVariablesDeclaration(token); | 2747 return parseVariablesDeclaration(token); |
2747 } else { | 2748 } else { |
(...skipping 19 matching lines...) Expand all Loading... |
2767 Token parseReturnStatement(Token token) { | 2768 Token parseReturnStatement(Token token) { |
2768 Token begin = token; | 2769 Token begin = token; |
2769 listener.beginReturnStatement(begin); | 2770 listener.beginReturnStatement(begin); |
2770 assert(identical('return', token.stringValue)); | 2771 assert(identical('return', token.stringValue)); |
2771 token = token.next; | 2772 token = token.next; |
2772 if (optional(';', token)) { | 2773 if (optional(';', token)) { |
2773 listener.endReturnStatement(false, begin, token); | 2774 listener.endReturnStatement(false, begin, token); |
2774 } else { | 2775 } else { |
2775 token = parseExpression(token); | 2776 token = parseExpression(token); |
2776 if (inGenerator) { | 2777 if (inGenerator) { |
2777 reportRecoverableErrorCode(begin.next, fasta.codeGeneratorReturnsValue); | 2778 reportRecoverableError(begin.next, fasta.messageGeneratorReturnsValue); |
2778 } | 2779 } |
2779 listener.endReturnStatement(true, begin, token); | 2780 listener.endReturnStatement(true, begin, token); |
2780 } | 2781 } |
2781 return expectSemicolon(token); | 2782 return expectSemicolon(token); |
2782 } | 2783 } |
2783 | 2784 |
2784 Token parseExpressionStatementOrDeclaration(Token token) { | 2785 Token parseExpressionStatementOrDeclaration(Token token) { |
2785 return parseType(token, TypeContinuation.ExpressionStatementOrDeclaration); | 2786 return parseType(token, TypeContinuation.ExpressionStatementOrDeclaration); |
2786 } | 2787 } |
2787 | 2788 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2880 BeginToken begin = token; | 2881 BeginToken begin = token; |
2881 token = (begin.endGroup != null) ? begin.endGroup : token; | 2882 token = (begin.endGroup != null) ? begin.endGroup : token; |
2882 } else if (token is ErrorToken) { | 2883 } else if (token is ErrorToken) { |
2883 reportErrorToken(token, false).next; | 2884 reportErrorToken(token, false).next; |
2884 } | 2885 } |
2885 token = token.next; | 2886 token = token.next; |
2886 } | 2887 } |
2887 return token; | 2888 return token; |
2888 } | 2889 } |
2889 | 2890 |
2890 Token parseRecoverExpression(Token token, FastaMessage message) => | 2891 Token parseRecoverExpression(Token token, Message message) { |
2891 parseExpression(token); | 2892 return parseExpression(token); |
| 2893 } |
2892 | 2894 |
2893 int expressionDepth = 0; | 2895 int expressionDepth = 0; |
2894 Token parseExpression(Token token) { | 2896 Token parseExpression(Token token) { |
2895 if (expressionDepth++ > 500) { | 2897 if (expressionDepth++ > 500) { |
2896 // This happens in degenerate programs, for example, with a lot of nested | 2898 // This happens in degenerate programs, for example, with a lot of nested |
2897 // list literals. This is provoked by, for examaple, the language test | 2899 // list literals. This is provoked by, for examaple, the language test |
2898 // deep_nesting1_negative_test. | 2900 // deep_nesting1_negative_test. |
2899 return reportUnrecoverableErrorCode(token, fasta.codeStackOverflow).next; | 2901 return reportUnrecoverableError(token, fasta.messageStackOverflow).next; |
2900 } | 2902 } |
2901 listener.beginExpression(token); | 2903 listener.beginExpression(token); |
2902 Token result = optional('throw', token) | 2904 Token result = optional('throw', token) |
2903 ? parseThrowExpression(token, true) | 2905 ? parseThrowExpression(token, true) |
2904 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); | 2906 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); |
2905 expressionDepth--; | 2907 expressionDepth--; |
2906 return result; | 2908 return result; |
2907 } | 2909 } |
2908 | 2910 |
2909 Token parseExpressionWithoutCascade(Token token) { | 2911 Token parseExpressionWithoutCascade(Token token) { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3030 String value = token.stringValue; | 3032 String value = token.stringValue; |
3031 // Prefix: | 3033 // Prefix: |
3032 if (optional('await', token)) { | 3034 if (optional('await', token)) { |
3033 if (inPlainSync) { | 3035 if (inPlainSync) { |
3034 return parsePrimary(token, IdentifierContext.expression); | 3036 return parsePrimary(token, IdentifierContext.expression); |
3035 } else { | 3037 } else { |
3036 return parseAwaitExpression(token, allowCascades); | 3038 return parseAwaitExpression(token, allowCascades); |
3037 } | 3039 } |
3038 } else if (identical(value, '+')) { | 3040 } else if (identical(value, '+')) { |
3039 // Dart no longer allows prefix-plus. | 3041 // Dart no longer allows prefix-plus. |
3040 reportRecoverableErrorCode(token, fasta.codeUnsupportedPrefixPlus); | 3042 reportRecoverableError(token, fasta.messageUnsupportedPrefixPlus); |
3041 return parseUnaryExpression(token.next, allowCascades); | 3043 return parseUnaryExpression(token.next, allowCascades); |
3042 } else if ((identical(value, '!')) || | 3044 } else if ((identical(value, '!')) || |
3043 (identical(value, '-')) || | 3045 (identical(value, '-')) || |
3044 (identical(value, '~'))) { | 3046 (identical(value, '~'))) { |
3045 Token operator = token; | 3047 Token operator = token; |
3046 // Right associative, so we recurse at the same precedence | 3048 // Right associative, so we recurse at the same precedence |
3047 // level. | 3049 // level. |
3048 token = parsePrecedenceExpression( | 3050 token = parsePrecedenceExpression( |
3049 token.next, POSTFIX_PRECEDENCE, allowCascades); | 3051 token.next, POSTFIX_PRECEDENCE, allowCascades); |
3050 listener.handleUnaryPrefixExpression(operator); | 3052 listener.handleUnaryPrefixExpression(operator); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3133 listener.handleNoTypeArguments(token); | 3135 listener.handleNoTypeArguments(token); |
3134 return parseLiteralMapSuffix(token, null); | 3136 return parseLiteralMapSuffix(token, null); |
3135 } else if (kind == LT_TOKEN) { | 3137 } else if (kind == LT_TOKEN) { |
3136 return parseLiteralListOrMapOrFunction(token, null); | 3138 return parseLiteralListOrMapOrFunction(token, null); |
3137 } else { | 3139 } else { |
3138 return expressionExpected(token); | 3140 return expressionExpected(token); |
3139 } | 3141 } |
3140 } | 3142 } |
3141 | 3143 |
3142 Token expressionExpected(Token token) { | 3144 Token expressionExpected(Token token) { |
3143 token = reportUnrecoverableErrorCodeWithToken( | 3145 token = reportUnrecoverableErrorWithToken( |
3144 token, fasta.codeExpectedExpression) | 3146 token, fasta.templateExpectedExpression) |
3145 .next; | 3147 .next; |
3146 listener.handleInvalidExpression(token); | 3148 listener.handleInvalidExpression(token); |
3147 return token; | 3149 return token; |
3148 } | 3150 } |
3149 | 3151 |
3150 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 3152 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
3151 BeginToken beginGroup = token; | 3153 BeginToken beginGroup = token; |
3152 Token nextToken = beginGroup.endGroup.next; | 3154 Token nextToken = beginGroup.endGroup.next; |
3153 int kind = nextToken.kind; | 3155 int kind = nextToken.kind; |
3154 if (mayParseFunctionExpressions && | 3156 if (mayParseFunctionExpressions && |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3199 Token parseSuperExpression(Token token, IdentifierContext context) { | 3201 Token parseSuperExpression(Token token, IdentifierContext context) { |
3200 Token beginToken = token; | 3202 Token beginToken = token; |
3201 listener.handleSuperExpression(token, context); | 3203 listener.handleSuperExpression(token, context); |
3202 token = token.next; | 3204 token = token.next; |
3203 if (optional('(', token)) { | 3205 if (optional('(', token)) { |
3204 // Super constructor. | 3206 // Super constructor. |
3205 listener.handleNoTypeArguments(token); | 3207 listener.handleNoTypeArguments(token); |
3206 token = parseArguments(token); | 3208 token = parseArguments(token); |
3207 listener.endSend(beginToken, token); | 3209 listener.endSend(beginToken, token); |
3208 } else if (optional("?.", token)) { | 3210 } else if (optional("?.", token)) { |
3209 reportRecoverableErrorCode(token, fasta.codeSuperNullAware); | 3211 reportRecoverableError(token, fasta.messageSuperNullAware); |
3210 } | 3212 } |
3211 return token; | 3213 return token; |
3212 } | 3214 } |
3213 | 3215 |
3214 /// '[' (expressionList ','?)? ']'. | 3216 /// '[' (expressionList ','?)? ']'. |
3215 /// | 3217 /// |
3216 /// Provide [constKeyword] if preceded by 'const', null if not. | 3218 /// Provide [constKeyword] if preceded by 'const', null if not. |
3217 /// This is a suffix parser because it is assumed that type arguments have | 3219 /// This is a suffix parser because it is assumed that type arguments have |
3218 /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed. | 3220 /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed. |
3219 Token parseLiteralListSuffix(Token token, Token constKeyword) { | 3221 Token parseLiteralListSuffix(Token token, Token constKeyword) { |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3675 Token forKeyword = token; | 3677 Token forKeyword = token; |
3676 listener.beginForStatement(forKeyword); | 3678 listener.beginForStatement(forKeyword); |
3677 token = expect('for', token); | 3679 token = expect('for', token); |
3678 Token leftParenthesis = token; | 3680 Token leftParenthesis = token; |
3679 token = expect('(', token); | 3681 token = expect('(', token); |
3680 token = parseVariablesDeclarationOrExpressionOpt(token); | 3682 token = parseVariablesDeclarationOrExpressionOpt(token); |
3681 if (optional('in', token)) { | 3683 if (optional('in', token)) { |
3682 return parseForInRest(awaitToken, forKeyword, leftParenthesis, token); | 3684 return parseForInRest(awaitToken, forKeyword, leftParenthesis, token); |
3683 } else { | 3685 } else { |
3684 if (awaitToken != null) { | 3686 if (awaitToken != null) { |
3685 reportRecoverableErrorCode(awaitToken, fasta.codeInvalidAwaitFor); | 3687 reportRecoverableError(awaitToken, fasta.messageInvalidAwaitFor); |
3686 } | 3688 } |
3687 return parseForRest(forKeyword, leftParenthesis, token); | 3689 return parseForRest(forKeyword, leftParenthesis, token); |
3688 } | 3690 } |
3689 } | 3691 } |
3690 | 3692 |
3691 Token parseVariablesDeclarationOrExpressionOpt(Token token) { | 3693 Token parseVariablesDeclarationOrExpressionOpt(Token token) { |
3692 final String value = token.stringValue; | 3694 final String value = token.stringValue; |
3693 if (identical(value, ';')) { | 3695 if (identical(value, ';')) { |
3694 listener.handleNoExpression(token); | 3696 listener.handleNoExpression(token); |
3695 return token; | 3697 return token; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3781 } | 3783 } |
3782 listener.endBlock(statementCount, begin, token); | 3784 listener.endBlock(statementCount, begin, token); |
3783 return expect('}', token); | 3785 return expect('}', token); |
3784 } | 3786 } |
3785 | 3787 |
3786 Token parseAwaitExpression(Token token, bool allowCascades) { | 3788 Token parseAwaitExpression(Token token, bool allowCascades) { |
3787 Token awaitToken = token; | 3789 Token awaitToken = token; |
3788 listener.beginAwaitExpression(awaitToken); | 3790 listener.beginAwaitExpression(awaitToken); |
3789 token = expect('await', token); | 3791 token = expect('await', token); |
3790 if (!inAsync) { | 3792 if (!inAsync) { |
3791 reportRecoverableErrorCode(awaitToken, fasta.codeAwaitNotAsync); | 3793 reportRecoverableError(awaitToken, fasta.messageAwaitNotAsync); |
3792 } | 3794 } |
3793 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades); | 3795 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades); |
3794 listener.endAwaitExpression(awaitToken, token); | 3796 listener.endAwaitExpression(awaitToken, token); |
3795 return token; | 3797 return token; |
3796 } | 3798 } |
3797 | 3799 |
3798 Token parseThrowExpression(Token token, bool allowCascades) { | 3800 Token parseThrowExpression(Token token, bool allowCascades) { |
3799 Token throwToken = token; | 3801 Token throwToken = token; |
3800 listener.beginThrowExpression(throwToken); | 3802 listener.beginThrowExpression(throwToken); |
3801 token = expect('throw', token); | 3803 token = expect('throw', token); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3840 if (identical(value, 'catch')) { | 3842 if (identical(value, 'catch')) { |
3841 catchKeyword = token; | 3843 catchKeyword = token; |
3842 Token openParens = catchKeyword.next; | 3844 Token openParens = catchKeyword.next; |
3843 Token exceptionName = openParens.next; | 3845 Token exceptionName = openParens.next; |
3844 Token commaOrCloseParens = exceptionName.next; | 3846 Token commaOrCloseParens = exceptionName.next; |
3845 Token traceName = commaOrCloseParens.next; | 3847 Token traceName = commaOrCloseParens.next; |
3846 Token closeParens = traceName.next; | 3848 Token closeParens = traceName.next; |
3847 if (!optional("(", openParens)) { | 3849 if (!optional("(", openParens)) { |
3848 // Handled below by parseFormalParameters. | 3850 // Handled below by parseFormalParameters. |
3849 } else if (!exceptionName.isIdentifier) { | 3851 } else if (!exceptionName.isIdentifier) { |
3850 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3852 reportRecoverableError(exceptionName, fasta.messageCatchSyntax); |
3851 } else if (optional(")", commaOrCloseParens)) { | 3853 } else if (optional(")", commaOrCloseParens)) { |
3852 // OK: `catch (identifier)`. | 3854 // OK: `catch (identifier)`. |
3853 } else if (!optional(",", commaOrCloseParens)) { | 3855 } else if (!optional(",", commaOrCloseParens)) { |
3854 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3856 reportRecoverableError(exceptionName, fasta.messageCatchSyntax); |
3855 } else if (!traceName.isIdentifier) { | 3857 } else if (!traceName.isIdentifier) { |
3856 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3858 reportRecoverableError(exceptionName, fasta.messageCatchSyntax); |
3857 } else if (!optional(")", closeParens)) { | 3859 } else if (!optional(")", closeParens)) { |
3858 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3860 reportRecoverableError(exceptionName, fasta.messageCatchSyntax); |
3859 } | 3861 } |
3860 token = parseFormalParameters(token.next, MemberKind.Catch); | 3862 token = parseFormalParameters(token.next, MemberKind.Catch); |
3861 } | 3863 } |
3862 listener.endCatchClause(token); | 3864 listener.endCatchClause(token); |
3863 token = parseBlock(token); | 3865 token = parseBlock(token); |
3864 ++catchCount; | 3866 ++catchCount; |
3865 listener.handleCatchBlock(onKeyword, catchKeyword); | 3867 listener.handleCatchBlock(onKeyword, catchKeyword); |
3866 value = token.stringValue; // while condition | 3868 value = token.stringValue; // while condition |
3867 } | 3869 } |
3868 | 3870 |
3869 Token finallyKeyword = null; | 3871 Token finallyKeyword = null; |
3870 if (optional('finally', token)) { | 3872 if (optional('finally', token)) { |
3871 finallyKeyword = token; | 3873 finallyKeyword = token; |
3872 token = parseBlock(token.next); | 3874 token = parseBlock(token.next); |
3873 listener.handleFinallyBlock(finallyKeyword); | 3875 listener.handleFinallyBlock(finallyKeyword); |
3874 } else { | 3876 } else { |
3875 if (catchCount == 0) { | 3877 if (catchCount == 0) { |
3876 reportRecoverableErrorCode(tryKeyword, fasta.codeOnlyTry); | 3878 reportRecoverableError(tryKeyword, fasta.messageOnlyTry); |
3877 } | 3879 } |
3878 } | 3880 } |
3879 listener.endTryStatement(catchCount, tryKeyword, finallyKeyword); | 3881 listener.endTryStatement(catchCount, tryKeyword, finallyKeyword); |
3880 return token; | 3882 return token; |
3881 } | 3883 } |
3882 | 3884 |
3883 Token parseSwitchStatement(Token token) { | 3885 Token parseSwitchStatement(Token token) { |
3884 assert(optional('switch', token)); | 3886 assert(optional('switch', token)); |
3885 Token switchKeyword = token; | 3887 Token switchKeyword = token; |
3886 listener.beginSwitchStatement(switchKeyword); | 3888 listener.beginSwitchStatement(switchKeyword); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3947 token = parseExpression(token.next); | 3949 token = parseExpression(token.next); |
3948 listener.endCaseExpression(token); | 3950 listener.endCaseExpression(token); |
3949 Token colonToken = token; | 3951 Token colonToken = token; |
3950 token = expect(':', token); | 3952 token = expect(':', token); |
3951 listener.handleCaseMatch(caseKeyword, colonToken); | 3953 listener.handleCaseMatch(caseKeyword, colonToken); |
3952 expressionCount++; | 3954 expressionCount++; |
3953 peek = peekPastLabels(token); | 3955 peek = peekPastLabels(token); |
3954 } else { | 3956 } else { |
3955 if (expressionCount == 0) { | 3957 if (expressionCount == 0) { |
3956 // TODO(ahe): This is probably easy to recover from. | 3958 // TODO(ahe): This is probably easy to recover from. |
3957 reportUnrecoverableErrorCodeWithString( | 3959 reportUnrecoverableError( |
3958 token, fasta.codeExpectedButGot, "case"); | 3960 token, fasta.templateExpectedButGot.withArguments("case")); |
3959 } | 3961 } |
3960 break; | 3962 break; |
3961 } | 3963 } |
3962 } | 3964 } |
3963 listener.beginSwitchCase(labelCount, expressionCount, begin); | 3965 listener.beginSwitchCase(labelCount, expressionCount, begin); |
3964 // Finally zero or more statements. | 3966 // Finally zero or more statements. |
3965 int statementCount = 0; | 3967 int statementCount = 0; |
3966 while (!identical(token.kind, EOF_TOKEN)) { | 3968 while (!identical(token.kind, EOF_TOKEN)) { |
3967 String value = peek.stringValue; | 3969 String value = peek.stringValue; |
3968 if ((identical(value, 'case')) || | 3970 if ((identical(value, 'case')) || |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4008 commaToken = token; | 4010 commaToken = token; |
4009 token = token.next; | 4011 token = token.next; |
4010 token = parseExpression(token); | 4012 token = parseExpression(token); |
4011 } | 4013 } |
4012 if (optional(',', token)) { | 4014 if (optional(',', token)) { |
4013 Token firstExtra = token.next; | 4015 Token firstExtra = token.next; |
4014 while (optional(',', token)) { | 4016 while (optional(',', token)) { |
4015 token = token.next; | 4017 token = token.next; |
4016 Token begin = token; | 4018 Token begin = token; |
4017 token = parseExpression(token); | 4019 token = parseExpression(token); |
4018 listener.handleExtraneousExpression(begin, | 4020 listener.handleExtraneousExpression( |
4019 fasta.codeAssertExtraneousArgument.format(uri, token.charOffset)); | 4021 begin, fasta.messageAssertExtraneousArgument); |
4020 } | 4022 } |
4021 reportRecoverableErrorCode( | 4023 reportRecoverableError(firstExtra, fasta.messageAssertExtraneousArgument); |
4022 firstExtra, fasta.codeAssertExtraneousArgument); | |
4023 } | 4024 } |
4024 Token rightParenthesis = token; | 4025 Token rightParenthesis = token; |
4025 token = expect(')', token); | 4026 token = expect(')', token); |
4026 mayParseFunctionExpressions = old; | 4027 mayParseFunctionExpressions = old; |
4027 listener.endAssert(assertKeyword, kind, leftParenthesis, commaToken, | 4028 listener.endAssert(assertKeyword, kind, leftParenthesis, commaToken, |
4028 rightParenthesis, token); | 4029 rightParenthesis, token); |
4029 if (kind == Assert.Expression) { | 4030 if (kind == Assert.Expression) { |
4030 reportRecoverableErrorCode(assertKeyword, fasta.codeAssertAsExpression); | 4031 reportRecoverableError(assertKeyword, fasta.messageAssertAsExpression); |
4031 } | 4032 } |
4032 return token; | 4033 return token; |
4033 } | 4034 } |
4034 | 4035 |
4035 Token parseAssertStatement(Token token) { | 4036 Token parseAssertStatement(Token token) { |
4036 token = parseAssert(token, Assert.Statement); | 4037 token = parseAssert(token, Assert.Statement); |
4037 return expectSemicolon(token); | 4038 return expectSemicolon(token); |
4038 } | 4039 } |
4039 | 4040 |
4040 Token parseContinueStatement(Token token) { | 4041 Token parseContinueStatement(Token token) { |
4041 assert(optional('continue', token)); | 4042 assert(optional('continue', token)); |
4042 Token continueKeyword = token; | 4043 Token continueKeyword = token; |
4043 token = token.next; | 4044 token = token.next; |
4044 bool hasTarget = false; | 4045 bool hasTarget = false; |
4045 if (token.isIdentifier) { | 4046 if (token.isIdentifier) { |
4046 token = parseIdentifier(token, IdentifierContext.labelReference); | 4047 token = parseIdentifier(token, IdentifierContext.labelReference); |
4047 hasTarget = true; | 4048 hasTarget = true; |
4048 } | 4049 } |
4049 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 4050 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
4050 return expectSemicolon(token); | 4051 return expectSemicolon(token); |
4051 } | 4052 } |
4052 | 4053 |
4053 Token parseEmptyStatement(Token token) { | 4054 Token parseEmptyStatement(Token token) { |
4054 listener.handleEmptyStatement(token); | 4055 listener.handleEmptyStatement(token); |
4055 return expectSemicolon(token); | 4056 return expectSemicolon(token); |
4056 } | 4057 } |
4057 | 4058 |
4058 /// Don't call this method. Should only be used as a last resort when there | 4059 /// Don't call this method. Should only be used as a last resort when there |
4059 /// is no feasible way to recover from a parser error. | 4060 /// is no feasible way to recover from a parser error. |
4060 Token reportUnrecoverableError(Token token, FastaMessage format()) { | 4061 Token reportUnrecoverableError(Token token, Message message) { |
4061 Token next; | 4062 Token next; |
4062 if (token is ErrorToken) { | 4063 if (token is ErrorToken) { |
4063 next = reportErrorToken(token, false); | 4064 next = reportErrorToken(token, false); |
4064 } else { | 4065 } else { |
4065 next = listener.handleUnrecoverableError(token, format()); | 4066 next = listener.handleUnrecoverableError(token, message); |
4066 } | 4067 } |
4067 return next ?? skipToEof(token); | 4068 return next ?? skipToEof(token); |
4068 } | 4069 } |
4069 | 4070 |
4070 void reportRecoverableError(Token token, FastaMessage format()) { | 4071 void reportRecoverableError(Token token, Message message) { |
4071 if (token is ErrorToken) { | 4072 if (token is ErrorToken) { |
4072 reportErrorToken(token, true); | 4073 reportErrorToken(token, true); |
4073 } else { | 4074 } else { |
4074 listener.handleRecoverableError(token, format()); | 4075 listener.handleRecoverableError(token, message); |
| 4076 } |
| 4077 } |
| 4078 |
| 4079 Token reportUnrecoverableErrorWithToken( |
| 4080 Token token, Template<_MessageWithArgument<Token>> template) { |
| 4081 Token next; |
| 4082 if (token is ErrorToken) { |
| 4083 next = reportErrorToken(token, false); |
| 4084 } else { |
| 4085 next = listener.handleUnrecoverableError( |
| 4086 token, template.withArguments(token)); |
| 4087 } |
| 4088 return next ?? skipToEof(token); |
| 4089 } |
| 4090 |
| 4091 void reportRecoverableErrorWithToken( |
| 4092 Token token, Template<_MessageWithArgument<Token>> template) { |
| 4093 if (token is ErrorToken) { |
| 4094 reportErrorToken(token, true); |
| 4095 } else { |
| 4096 listener.handleRecoverableError(token, template.withArguments(token)); |
4075 } | 4097 } |
4076 } | 4098 } |
4077 | 4099 |
4078 Token reportErrorToken(ErrorToken token, bool isRecoverable) { | 4100 Token reportErrorToken(ErrorToken token, bool isRecoverable) { |
4079 FastaCode code = token.errorCode; | 4101 Code code = token.errorCode; |
4080 FastaMessage message; | 4102 Message message; |
4081 if (code == fasta.codeAsciiControlCharacter) { | 4103 if (code == fasta.codeAsciiControlCharacter) { |
4082 message = fasta.codeAsciiControlCharacter | 4104 message = |
4083 .format(uri, token.charOffset, token.character); | 4105 fasta.templateAsciiControlCharacter.withArguments(token.character); |
4084 } else if (code == fasta.codeNonAsciiWhitespace) { | 4106 } else if (code == fasta.codeNonAsciiWhitespace) { |
4085 message = fasta.codeNonAsciiWhitespace | 4107 message = fasta.templateNonAsciiWhitespace.withArguments(token.character); |
4086 .format(uri, token.charOffset, token.character); | |
4087 } else if (code == fasta.codeEncoding) { | 4108 } else if (code == fasta.codeEncoding) { |
4088 message = fasta.codeEncoding.format(uri, token.charOffset); | 4109 message = fasta.messageEncoding; |
4089 } else if (code == fasta.codeNonAsciiIdentifier) { | 4110 } else if (code == fasta.codeNonAsciiIdentifier) { |
4090 message = fasta.codeNonAsciiIdentifier.format(uri, token.charOffset, | 4111 message = fasta.templateNonAsciiIdentifier.withArguments( |
4091 new String.fromCharCodes([token.character]), token.character); | 4112 new String.fromCharCodes([token.character]), token.character); |
4092 } else if (code == fasta.codeUnterminatedString) { | 4113 } else if (code == fasta.codeUnterminatedString) { |
4093 message = fasta.codeUnterminatedString | 4114 message = fasta.templateUnterminatedString.withArguments(token.start); |
4094 .format(uri, token.charOffset, token.start); | |
4095 } else if (code == fasta.codeUnmatchedToken) { | 4115 } else if (code == fasta.codeUnmatchedToken) { |
4096 Token begin = token.begin; | 4116 Token begin = token.begin; |
4097 message = fasta.codeUnmatchedToken | 4117 message = fasta.templateUnmatchedToken |
4098 .format(uri, token.charOffset, closeBraceFor(begin.lexeme), begin); | 4118 .withArguments(closeBraceFor(begin.lexeme), begin); |
4099 } else if (code == fasta.codeUnspecified) { | 4119 } else if (code == fasta.codeUnspecified) { |
4100 message = fasta.codeUnspecified | 4120 message = fasta.templateUnspecified.withArguments(token.assertionMessage); |
4101 .format(uri, token.charOffset, token.assertionMessage); | |
4102 } else { | 4121 } else { |
4103 message = code.format(uri, token.charOffset); | 4122 message = code as Message; |
4104 } | 4123 } |
4105 if (isRecoverable) { | 4124 if (isRecoverable) { |
4106 listener.handleRecoverableError(token, message); | 4125 listener.handleRecoverableError(token, message); |
4107 return null; | 4126 return null; |
4108 } else { | 4127 } else { |
4109 Token next = listener.handleUnrecoverableError(token, message); | 4128 Token next = listener.handleUnrecoverableError(token, message); |
4110 return next ?? skipToEof(token); | 4129 return next ?? skipToEof(token); |
4111 } | 4130 } |
4112 } | 4131 } |
4113 | 4132 |
4114 Token reportUnmatchedToken(BeginToken token) { | 4133 Token reportUnmatchedToken(BeginToken token) { |
4115 return reportUnrecoverableError( | 4134 return reportUnrecoverableError( |
4116 token, | 4135 token, |
4117 () => fasta.codeUnmatchedToken | 4136 fasta.templateUnmatchedToken |
4118 .format(uri, token.charOffset, closeBraceFor(token.lexeme), token)); | 4137 .withArguments(closeBraceFor(token.lexeme), token)); |
4119 } | 4138 } |
4120 | 4139 |
4121 Token reportUnexpectedToken(Token token) { | 4140 Token reportUnexpectedToken(Token token) { |
4122 return reportUnrecoverableError(token, | 4141 return reportUnrecoverableErrorWithToken( |
4123 () => fasta.codeUnexpectedToken.format(uri, token.charOffset, token)); | 4142 token, fasta.templateUnexpectedToken); |
4124 } | |
4125 | |
4126 void reportRecoverableErrorCode(Token token, FastaCode<NoArgument> code) { | |
4127 reportRecoverableError(token, () => code.format(uri, token.charOffset)); | |
4128 } | |
4129 | |
4130 Token reportUnrecoverableErrorCode(Token token, FastaCode<NoArgument> code) { | |
4131 return reportUnrecoverableError( | |
4132 token, () => code.format(uri, token.charOffset)); | |
4133 } | |
4134 | |
4135 void reportRecoverableErrorCodeWithToken( | |
4136 Token token, FastaCode<TokenArgument> code) { | |
4137 reportRecoverableError( | |
4138 token, () => code.format(uri, token.charOffset, token)); | |
4139 } | |
4140 | |
4141 Token reportUnrecoverableErrorCodeWithToken( | |
4142 Token token, FastaCode<TokenArgument> code) { | |
4143 return reportUnrecoverableError( | |
4144 token, () => code.format(uri, token.charOffset, token)); | |
4145 } | |
4146 | |
4147 Token reportUnrecoverableErrorCodeWithString( | |
4148 Token token, FastaCode<StringArgument> code, String string) { | |
4149 return reportUnrecoverableError( | |
4150 token, () => code.format(uri, token.charOffset, string)); | |
4151 } | 4143 } |
4152 } | 4144 } |
4153 | 4145 |
4154 typedef FastaMessage NoArgument(Uri uri, int charOffset); | 4146 // TODO(ahe): Remove when analyzer supports generalized function syntax. |
4155 | 4147 typedef _MessageWithArgument<T> = Message Function(T); |
4156 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); | |
4157 | |
4158 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); | |
OLD | NEW |