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