| 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' |
| 8 show BoundFastaCode, BoundFastaMessage, FastaCode, FastaMessage; |
| 8 | 9 |
| 9 import '../fasta_codes.dart' as fasta; | 10 import '../fasta_codes.dart' as fasta; |
| 10 | 11 |
| 11 import '../scanner.dart' show ErrorToken, Token; | 12 import '../scanner.dart' show ErrorToken, Token; |
| 12 | 13 |
| 13 import '../scanner/recover.dart' show closeBraceFor, skipToEof; | 14 import '../scanner/recover.dart' show closeBraceFor, skipToEof; |
| 14 | 15 |
| 15 import '../../scanner/token.dart' | 16 import '../../scanner/token.dart' |
| 16 show | 17 show |
| 17 ASSIGNMENT_PRECEDENCE, | 18 ASSIGNMENT_PRECEDENCE, |
| (...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 | 607 |
| 607 /// Parse `'@' qualified (‘.’ identifier)? (arguments)?` | 608 /// Parse `'@' qualified (‘.’ identifier)? (arguments)?` |
| 608 Token parseMetadata(Token token) { | 609 Token parseMetadata(Token token) { |
| 609 listener.beginMetadata(token); | 610 listener.beginMetadata(token); |
| 610 Token atToken = token; | 611 Token atToken = token; |
| 611 assert(optional('@', token)); | 612 assert(optional('@', token)); |
| 612 token = parseIdentifier(token.next, IdentifierContext.metadataReference); | 613 token = parseIdentifier(token.next, IdentifierContext.metadataReference); |
| 613 token = | 614 token = |
| 614 parseQualifiedRestOpt(token, IdentifierContext.metadataContinuation); | 615 parseQualifiedRestOpt(token, IdentifierContext.metadataContinuation); |
| 615 if (optional("<", token)) { | 616 if (optional("<", token)) { |
| 616 reportRecoverableErrorCode(token, fasta.codeMetadataTypeArguments); | 617 reportRecoverableError(token, fasta.codeMetadataTypeArguments); |
| 617 } | 618 } |
| 618 token = parseTypeArgumentsOpt(token); | 619 token = parseTypeArgumentsOpt(token); |
| 619 Token period = null; | 620 Token period = null; |
| 620 if (optional('.', token)) { | 621 if (optional('.', token)) { |
| 621 period = token; | 622 period = token; |
| 622 token = parseIdentifier( | 623 token = parseIdentifier( |
| 623 token.next, IdentifierContext.metadataContinuationAfterTypeArguments); | 624 token.next, IdentifierContext.metadataContinuationAfterTypeArguments); |
| 624 } | 625 } |
| 625 token = parseArgumentsOpt(token); | 626 token = parseArgumentsOpt(token); |
| 626 listener.endMetadata(atToken, period, token); | 627 listener.endMetadata(atToken, period, token); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 listener.handleNoFormalParameters(token, kind); | 672 listener.handleNoFormalParameters(token, kind); |
| 672 return token; | 673 return token; |
| 673 } | 674 } |
| 674 } | 675 } |
| 675 | 676 |
| 676 Token skipFormalParameters(Token token, MemberKind kind) { | 677 Token skipFormalParameters(Token token, MemberKind kind) { |
| 677 // TODO(ahe): Shouldn't this be `beginFormalParameters`? | 678 // TODO(ahe): Shouldn't this be `beginFormalParameters`? |
| 678 listener.beginOptionalFormalParameters(token); | 679 listener.beginOptionalFormalParameters(token); |
| 679 if (!optional('(', token)) { | 680 if (!optional('(', token)) { |
| 680 if (optional(';', token)) { | 681 if (optional(';', token)) { |
| 681 reportRecoverableErrorCode(token, fasta.codeExpectedOpenParens); | 682 reportRecoverableError(token, fasta.codeExpectedOpenParens); |
| 682 return token; | 683 return token; |
| 683 } | 684 } |
| 684 return reportUnrecoverableErrorCodeWithString( | 685 return reportUnrecoverableError(token, fasta.codeExpectedButGot.bind("(")) |
| 685 token, fasta.codeExpectedButGot, "(") | |
| 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.codeEmptyOptionalParameterList); |
| 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.codeEmptyNamedParameterList |
| 759 : fasta.codeEmptyOptionalParameterList); | 759 : fasta.codeEmptyOptionalParameterList); |
| 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); |
| (...skipping 112 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.codeExpectedBlockToSkip) |
| 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 reportUnrecoverableError(token, fasta.codeExpectedString.bind(token)) |
| 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.codeInvalidVoid); |
| 1003 } else { | 1003 } else { |
| 1004 token = reportUnrecoverableErrorCodeWithToken( | 1004 token = reportUnrecoverableError( |
| 1005 token, fasta.codeExpectedIdentifier) | 1005 token, fasta.codeExpectedIdentifier.bind(token)) |
| 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 reportRecoverableError( |
| 1011 token, fasta.codeBuiltInIdentifierInDeclaration); | 1011 token, fasta.codeBuiltInIdentifierInDeclaration.bind(token)); |
| 1012 } else if (!optional("dynamic", token)) { | 1012 } else if (!optional("dynamic", token)) { |
| 1013 reportRecoverableErrorCodeWithToken( | 1013 reportRecoverableError( |
| 1014 token, fasta.codeBuiltInIdentifierAsType); | 1014 token, fasta.codeBuiltInIdentifierAsType.bind(token)); |
| 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.codeAwaitAsIdentifier); |
| 1019 } else if (optional('yield', token)) { | 1019 } else if (optional('yield', token)) { |
| 1020 reportRecoverableErrorCode(token, fasta.codeYieldAsIdentifier); | 1020 reportRecoverableError(token, fasta.codeYieldAsIdentifier); |
| 1021 } else if (optional('async', token)) { | 1021 } else if (optional('async', token)) { |
| 1022 reportRecoverableErrorCode(token, fasta.codeAsyncAsIdentifier); | 1022 reportRecoverableError(token, fasta.codeAsyncAsIdentifier); |
| 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.codeExpectedButGot.bind(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.codeTypeAfterVar); |
| 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.codePrivateNamedParameter); |
| 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( |
| 1506 inlineFunctionTypeStart, fasta.codeInvalidInlineFunctionType); | 1505 inlineFunctionTypeStart, fasta.codeInvalidInlineFunctionType); |
| 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.codeRequiredParameterWithDefault); |
| 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.codePositionalParameterWithEquals); |
| 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.codeFunctionTypeDefaultValue); |
| 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 } |
| (...skipping 43 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 reportUnrecoverableError( |
| 1601 start, fasta.codeExpectedDeclaration) | 1600 start, fasta.codeExpectedDeclaration.bind(start)) |
| 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 reportUnrecoverableError( |
| 1609 start, fasta.codeExpectedDeclaration) | 1608 start, fasta.codeExpectedDeclaration.bind(start)) |
| 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 reportRecoverableError(token, fasta.codeExtraneousModifier.bind(token)); |
| 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 reportRecoverableError( |
| 1720 modifier, fasta.codeExtraneousModifier); | 1719 modifier, fasta.codeExtraneousModifier.bind(modifier)); |
| 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.codeSetterNotSync); |
| 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.codeGetterWithFormals); |
| 1765 } | 1764 } |
| 1766 } else if (!isGetter) { | 1765 } else if (!isGetter) { |
| 1767 reportRecoverableErrorCodeWithToken(name, fasta.codeNoFormals); | 1766 reportRecoverableError(name, fasta.codeNoFormals.bind(name)); |
| 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.codeExpectedOpenParens); |
| 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(name, fasta.codeConstFieldWithoutInitializer); |
| 1920 name, fasta.codeConstFieldWithoutInitializer); | |
| 1921 } else if (isTopLevel && optional("final", varFinalOrConst)) { | 1919 } else if (isTopLevel && optional("final", varFinalOrConst)) { |
| 1922 reportRecoverableErrorCode( | 1920 reportRecoverableError(name, fasta.codeFinalFieldWithoutInitializer); |
| 1923 name, fasta.codeFinalFieldWithoutInitializer); | |
| 1924 } | 1921 } |
| 1925 } | 1922 } |
| 1926 listener.handleNoFieldInitializer(token); | 1923 listener.handleNoFieldInitializer(token); |
| 1927 } | 1924 } |
| 1928 return token; | 1925 return token; |
| 1929 } | 1926 } |
| 1930 | 1927 |
| 1931 Token parseVariableInitializerOpt(Token token) { | 1928 Token parseVariableInitializerOpt(Token token) { |
| 1932 if (optional('=', token)) { | 1929 if (optional('=', token)) { |
| 1933 Token assignment = token; | 1930 Token assignment = token; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 token = parseExpression(token); | 1970 token = parseExpression(token); |
| 1974 } | 1971 } |
| 1975 listener.endInitializer(token); | 1972 listener.endInitializer(token); |
| 1976 return token; | 1973 return token; |
| 1977 } | 1974 } |
| 1978 | 1975 |
| 1979 Token parseLiteralStringOrRecoverExpression(Token token) { | 1976 Token parseLiteralStringOrRecoverExpression(Token token) { |
| 1980 if (identical(token.kind, STRING_TOKEN)) { | 1977 if (identical(token.kind, STRING_TOKEN)) { |
| 1981 return parseLiteralString(token); | 1978 return parseLiteralString(token); |
| 1982 } else { | 1979 } else { |
| 1983 reportRecoverableErrorCodeWithToken(token, fasta.codeExpectedString); | 1980 reportRecoverableError(token, fasta.codeExpectedString.bind(token)); |
| 1984 return parseRecoverExpression( | 1981 return parseRecoverExpression( |
| 1985 token, fasta.codeExpectedString.format(uri, token.charOffset, token)); | 1982 token, fasta.codeExpectedString.bind(token)(uri, token.charOffset)); |
| 1986 } | 1983 } |
| 1987 } | 1984 } |
| 1988 | 1985 |
| 1989 Token expectSemicolon(Token token) { | 1986 Token expectSemicolon(Token token) { |
| 1990 return expect(';', token); | 1987 return expect(';', token); |
| 1991 } | 1988 } |
| 1992 | 1989 |
| 1993 bool isModifier(Token token) => modifierOrder(token) < 127; | 1990 bool isModifier(Token token) => modifierOrder(token) < 127; |
| 1994 | 1991 |
| 1995 /// Provides a partial order on modifiers. | 1992 /// Provides a partial order on modifiers. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2049 break; | 2046 break; |
| 2050 } | 2047 } |
| 2051 } | 2048 } |
| 2052 int order = modifierOrder(token); | 2049 int order = modifierOrder(token); |
| 2053 if (order < 3) { | 2050 if (order < 3) { |
| 2054 // `abstract` isn't parsed with this method. | 2051 // `abstract` isn't parsed with this method. |
| 2055 if (order > currentOrder) { | 2052 if (order > currentOrder) { |
| 2056 currentOrder = order; | 2053 currentOrder = order; |
| 2057 if (optional("var", token)) { | 2054 if (optional("var", token)) { |
| 2058 if (!isVarAllowed && parameterKind == null) { | 2055 if (!isVarAllowed && parameterKind == null) { |
| 2059 reportRecoverableErrorCodeWithToken( | 2056 reportRecoverableError( |
| 2060 token, fasta.codeExtraneousModifier); | 2057 token, fasta.codeExtraneousModifier.bind(token)); |
| 2061 } | 2058 } |
| 2062 switch (typeContinuation ?? TypeContinuation.Required) { | 2059 switch (typeContinuation ?? TypeContinuation.Required) { |
| 2063 case TypeContinuation.NormalFormalParameter: | 2060 case TypeContinuation.NormalFormalParameter: |
| 2064 typeContinuation = | 2061 typeContinuation = |
| 2065 TypeContinuation.NormalFormalParameterAfterVar; | 2062 TypeContinuation.NormalFormalParameterAfterVar; |
| 2066 break; | 2063 break; |
| 2067 | 2064 |
| 2068 case TypeContinuation.OptionalPositionalFormalParameter: | 2065 case TypeContinuation.OptionalPositionalFormalParameter: |
| 2069 typeContinuation = | 2066 typeContinuation = |
| 2070 TypeContinuation.OptionalPositionalFormalParameterAfterVar; | 2067 TypeContinuation.OptionalPositionalFormalParameterAfterVar; |
| 2071 break; | 2068 break; |
| 2072 | 2069 |
| 2073 case TypeContinuation.NamedFormalParameter: | 2070 case TypeContinuation.NamedFormalParameter: |
| 2074 typeContinuation = | 2071 typeContinuation = |
| 2075 TypeContinuation.NamedFormalParameterAfterVar; | 2072 TypeContinuation.NamedFormalParameterAfterVar; |
| 2076 break; | 2073 break; |
| 2077 | 2074 |
| 2078 default: | 2075 default: |
| 2079 typeContinuation = TypeContinuation.OptionalAfterVar; | 2076 typeContinuation = TypeContinuation.OptionalAfterVar; |
| 2080 break; | 2077 break; |
| 2081 } | 2078 } |
| 2082 } else if (optional("final", token)) { | 2079 } else if (optional("final", token)) { |
| 2083 if (!isVarAllowed && parameterKind == null) { | 2080 if (!isVarAllowed && parameterKind == null) { |
| 2084 reportRecoverableErrorCodeWithToken( | 2081 reportRecoverableError( |
| 2085 token, fasta.codeExtraneousModifier); | 2082 token, fasta.codeExtraneousModifier.bind(token)); |
| 2086 } | 2083 } |
| 2087 typeContinuation ??= TypeContinuation.Optional; | 2084 typeContinuation ??= TypeContinuation.Optional; |
| 2088 } else if (optional("const", token)) { | 2085 } else if (optional("const", token)) { |
| 2089 if (!isVarAllowed) { | 2086 if (!isVarAllowed) { |
| 2090 reportRecoverableErrorCodeWithToken( | 2087 reportRecoverableError( |
| 2091 token, fasta.codeExtraneousModifier); | 2088 token, fasta.codeExtraneousModifier.bind(token)); |
| 2092 } | 2089 } |
| 2093 typeContinuation ??= TypeContinuation.Optional; | 2090 typeContinuation ??= TypeContinuation.Optional; |
| 2094 } else if (optional("static", token)) { | 2091 } else if (optional("static", token)) { |
| 2095 if (parameterKind != null) { | 2092 if (parameterKind != null) { |
| 2096 reportRecoverableErrorCodeWithToken( | 2093 reportRecoverableError( |
| 2097 token, fasta.codeExtraneousModifier); | 2094 token, fasta.codeExtraneousModifier.bind(token)); |
| 2098 } else if (memberKind == MemberKind.NonStaticMethod) { | 2095 } else if (memberKind == MemberKind.NonStaticMethod) { |
| 2099 memberKind = MemberKind.StaticMethod; | 2096 memberKind = MemberKind.StaticMethod; |
| 2100 } else if (memberKind == MemberKind.NonStaticField) { | 2097 } else if (memberKind == MemberKind.NonStaticField) { |
| 2101 memberKind = MemberKind.StaticField; | 2098 memberKind = MemberKind.StaticField; |
| 2102 } else { | 2099 } else { |
| 2103 reportRecoverableErrorCodeWithToken( | 2100 reportRecoverableError( |
| 2104 token, fasta.codeExtraneousModifier); | 2101 token, fasta.codeExtraneousModifier.bind(token)); |
| 2105 token = token.next; | 2102 token = token.next; |
| 2106 continue; | 2103 continue; |
| 2107 } | 2104 } |
| 2108 } else if (optional("covariant", token)) { | 2105 } else if (optional("covariant", token)) { |
| 2109 switch (memberKind) { | 2106 switch (memberKind) { |
| 2110 case MemberKind.StaticField: | 2107 case MemberKind.StaticField: |
| 2111 case MemberKind.StaticMethod: | 2108 case MemberKind.StaticMethod: |
| 2112 case MemberKind.TopLevelField: | 2109 case MemberKind.TopLevelField: |
| 2113 case MemberKind.TopLevelMethod: | 2110 case MemberKind.TopLevelMethod: |
| 2114 reportRecoverableErrorCodeWithToken( | 2111 reportRecoverableError( |
| 2115 token, fasta.codeExtraneousModifier); | 2112 token, fasta.codeExtraneousModifier.bind(token)); |
| 2116 token = token.next; | 2113 token = token.next; |
| 2117 continue; | 2114 continue; |
| 2118 | 2115 |
| 2119 default: | 2116 default: |
| 2120 break; | 2117 break; |
| 2121 } | 2118 } |
| 2122 } else if (optional("external", token)) { | 2119 } else if (optional("external", token)) { |
| 2123 switch (memberKind) { | 2120 switch (memberKind) { |
| 2124 case MemberKind.Factory: | 2121 case MemberKind.Factory: |
| 2125 case MemberKind.NonStaticMethod: | 2122 case MemberKind.NonStaticMethod: |
| 2126 case MemberKind.StaticMethod: | 2123 case MemberKind.StaticMethod: |
| 2127 case MemberKind.TopLevelMethod: | 2124 case MemberKind.TopLevelMethod: |
| 2128 break; | 2125 break; |
| 2129 | 2126 |
| 2130 default: | 2127 default: |
| 2131 reportRecoverableErrorCodeWithToken( | 2128 reportRecoverableError( |
| 2132 token, fasta.codeExtraneousModifier); | 2129 token, fasta.codeExtraneousModifier.bind(token)); |
| 2133 token = token.next; | 2130 token = token.next; |
| 2134 continue; | 2131 continue; |
| 2135 } | 2132 } |
| 2136 } | 2133 } |
| 2137 token = parseModifier(token); | 2134 token = parseModifier(token); |
| 2138 count++; | 2135 count++; |
| 2139 } else { | 2136 } else { |
| 2140 reportRecoverableErrorCodeWithToken( | 2137 reportRecoverableError( |
| 2141 token, fasta.codeExtraneousModifier); | 2138 token, fasta.codeExtraneousModifier.bind(token)); |
| 2142 token = token.next; | 2139 token = token.next; |
| 2143 } | 2140 } |
| 2144 } else { | 2141 } else { |
| 2145 break; | 2142 break; |
| 2146 } | 2143 } |
| 2147 } | 2144 } |
| 2148 listener.handleModifiers(count); | 2145 listener.handleModifiers(count); |
| 2149 | 2146 |
| 2150 typeContinuation ??= | 2147 typeContinuation ??= |
| 2151 (isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType) | 2148 (isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType) |
| 2152 ? TypeContinuation.Required | 2149 ? TypeContinuation.Required |
| 2153 : TypeContinuation.Optional; | 2150 : TypeContinuation.Optional; |
| 2154 | 2151 |
| 2155 token = parseType(token, typeContinuation, null, memberKind); | 2152 token = parseType(token, typeContinuation, null, memberKind); |
| 2156 return token; | 2153 return token; |
| 2157 } | 2154 } |
| 2158 | 2155 |
| 2159 Token skipClassBody(Token token) { | 2156 Token skipClassBody(Token token) { |
| 2160 if (!optional('{', token)) { | 2157 if (!optional('{', token)) { |
| 2161 return reportUnrecoverableErrorCodeWithToken( | 2158 return reportUnrecoverableError( |
| 2162 token, fasta.codeExpectedClassBodyToSkip) | 2159 token, fasta.codeExpectedClassBodyToSkip.bind(token)) |
| 2163 .next; | 2160 .next; |
| 2164 } | 2161 } |
| 2165 BeginToken beginGroupToken = token; | 2162 BeginToken beginGroupToken = token; |
| 2166 Token endGroup = beginGroupToken.endGroup; | 2163 Token endGroup = beginGroupToken.endGroup; |
| 2167 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | 2164 if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
| 2168 return reportUnmatchedToken(beginGroupToken).next; | 2165 return reportUnmatchedToken(beginGroupToken).next; |
| 2169 } | 2166 } |
| 2170 return endGroup; | 2167 return endGroup; |
| 2171 } | 2168 } |
| 2172 | 2169 |
| 2173 Token parseClassBody(Token token) { | 2170 Token parseClassBody(Token token) { |
| 2174 Token begin = token; | 2171 Token begin = token; |
| 2175 listener.beginClassBody(token); | 2172 listener.beginClassBody(token); |
| 2176 if (!optional('{', token)) { | 2173 if (!optional('{', token)) { |
| 2177 token = reportUnrecoverableErrorCodeWithToken( | 2174 token = reportUnrecoverableError( |
| 2178 token, fasta.codeExpectedClassBody) | 2175 token, fasta.codeExpectedClassBody.bind(token)) |
| 2179 .next; | 2176 .next; |
| 2180 } | 2177 } |
| 2181 token = token.next; | 2178 token = token.next; |
| 2182 int count = 0; | 2179 int count = 0; |
| 2183 while (notEofOrValue('}', token)) { | 2180 while (notEofOrValue('}', token)) { |
| 2184 token = parseMember(token); | 2181 token = parseMember(token); |
| 2185 ++count; | 2182 ++count; |
| 2186 } | 2183 } |
| 2187 expect('}', token); | 2184 expect('}', token); |
| 2188 listener.endClassBody(count, begin, token); | 2185 listener.endClassBody(count, begin, token); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2206 listener.beginMember(token); | 2203 listener.beginMember(token); |
| 2207 if (isFactoryDeclaration(token)) { | 2204 if (isFactoryDeclaration(token)) { |
| 2208 token = parseFactoryMethod(token); | 2205 token = parseFactoryMethod(token); |
| 2209 listener.endMember(); | 2206 listener.endMember(); |
| 2210 assert(token != null); | 2207 assert(token != null); |
| 2211 return token; | 2208 return token; |
| 2212 } | 2209 } |
| 2213 | 2210 |
| 2214 Link<Token> identifiers = findMemberName(token); | 2211 Link<Token> identifiers = findMemberName(token); |
| 2215 if (identifiers.isEmpty) { | 2212 if (identifiers.isEmpty) { |
| 2216 return reportUnrecoverableErrorCodeWithToken( | 2213 return reportUnrecoverableError( |
| 2217 start, fasta.codeExpectedDeclaration) | 2214 start, fasta.codeExpectedDeclaration.bind(token)) |
| 2218 .next; | 2215 .next; |
| 2219 } | 2216 } |
| 2220 Token afterName = identifiers.head; | 2217 Token afterName = identifiers.head; |
| 2221 identifiers = identifiers.tail; | 2218 identifiers = identifiers.tail; |
| 2222 | 2219 |
| 2223 if (identifiers.isEmpty) { | 2220 if (identifiers.isEmpty) { |
| 2224 return reportUnrecoverableErrorCodeWithToken( | 2221 return reportUnrecoverableError( |
| 2225 start, fasta.codeExpectedDeclaration) | 2222 start, fasta.codeExpectedDeclaration.bind(start)) |
| 2226 .next; | 2223 .next; |
| 2227 } | 2224 } |
| 2228 Token name = identifiers.head; | 2225 Token name = identifiers.head; |
| 2229 identifiers = identifiers.tail; | 2226 identifiers = identifiers.tail; |
| 2230 if (!identifiers.isEmpty) { | 2227 if (!identifiers.isEmpty) { |
| 2231 if (optional('operator', identifiers.head)) { | 2228 if (optional('operator', identifiers.head)) { |
| 2232 name = identifiers.head; | 2229 name = identifiers.head; |
| 2233 identifiers = identifiers.tail; | 2230 identifiers = identifiers.tail; |
| 2234 } | 2231 } |
| 2235 } | 2232 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2299 | 2296 |
| 2300 Token externalModifier; | 2297 Token externalModifier; |
| 2301 Token staticModifier; | 2298 Token staticModifier; |
| 2302 // TODO(ahe): Consider using [parseModifiers] instead. | 2299 // TODO(ahe): Consider using [parseModifiers] instead. |
| 2303 void parseModifierList(Link<Token> tokens) { | 2300 void parseModifierList(Link<Token> tokens) { |
| 2304 int count = 0; | 2301 int count = 0; |
| 2305 int currentOrder = -1; | 2302 int currentOrder = -1; |
| 2306 for (; !tokens.isEmpty; tokens = tokens.tail) { | 2303 for (; !tokens.isEmpty; tokens = tokens.tail) { |
| 2307 Token token = tokens.head; | 2304 Token token = tokens.head; |
| 2308 if (optional("abstract", token)) { | 2305 if (optional("abstract", token)) { |
| 2309 reportRecoverableErrorCodeWithToken( | 2306 reportRecoverableError( |
| 2310 token, fasta.codeExtraneousModifier); | 2307 token, fasta.codeExtraneousModifier.bind(token)); |
| 2311 continue; | 2308 continue; |
| 2312 } | 2309 } |
| 2313 int order = modifierOrder(token); | 2310 int order = modifierOrder(token); |
| 2314 if (order < 127) { | 2311 if (order < 127) { |
| 2315 if (order > currentOrder) { | 2312 if (order > currentOrder) { |
| 2316 currentOrder = order; | 2313 currentOrder = order; |
| 2317 if (optional("var", token)) { | 2314 if (optional("var", token)) { |
| 2318 reportRecoverableErrorCodeWithToken( | 2315 reportRecoverableError( |
| 2319 token, fasta.codeExtraneousModifier); | 2316 token, fasta.codeExtraneousModifier.bind(token)); |
| 2320 } else if (optional("const", token)) { | 2317 } else if (optional("const", token)) { |
| 2321 if (getOrSet != null) { | 2318 if (getOrSet != null) { |
| 2322 reportRecoverableErrorCodeWithToken( | 2319 reportRecoverableError( |
| 2323 token, fasta.codeExtraneousModifier); | 2320 token, fasta.codeExtraneousModifier.bind(token)); |
| 2324 continue; | 2321 continue; |
| 2325 } | 2322 } |
| 2326 } else if (optional("external", token)) { | 2323 } else if (optional("external", token)) { |
| 2327 externalModifier = token; | 2324 externalModifier = token; |
| 2328 } else if (optional("static", token)) { | 2325 } else if (optional("static", token)) { |
| 2329 staticModifier = token; | 2326 staticModifier = token; |
| 2330 } else if (optional("covariant", token)) { | 2327 } else if (optional("covariant", token)) { |
| 2331 if (staticModifier != null || | 2328 if (staticModifier != null || |
| 2332 getOrSet == null || | 2329 getOrSet == null || |
| 2333 optional("get", getOrSet)) { | 2330 optional("get", getOrSet)) { |
| 2334 reportRecoverableErrorCodeWithToken( | 2331 reportRecoverableError( |
| 2335 token, fasta.codeExtraneousModifier); | 2332 token, fasta.codeExtraneousModifier.bind(token)); |
| 2336 continue; | 2333 continue; |
| 2337 } | 2334 } |
| 2338 } | 2335 } |
| 2339 } else { | 2336 } else { |
| 2340 reportRecoverableErrorCodeWithToken( | 2337 reportRecoverableError( |
| 2341 token, fasta.codeExtraneousModifier); | 2338 token, fasta.codeExtraneousModifier.bind(token)); |
| 2342 continue; | 2339 continue; |
| 2343 } | 2340 } |
| 2344 } else { | 2341 } else { |
| 2345 reportUnexpectedToken(token); | 2342 reportUnexpectedToken(token); |
| 2346 break; // Skip the remaining modifiers. | 2343 break; // Skip the remaining modifiers. |
| 2347 } | 2344 } |
| 2348 parseModifier(token); | 2345 parseModifier(token); |
| 2349 count++; | 2346 count++; |
| 2350 } | 2347 } |
| 2351 listener.handleModifiers(count); | 2348 listener.handleModifiers(count); |
| 2352 } | 2349 } |
| 2353 | 2350 |
| 2354 parseModifierList(modifiers); | 2351 parseModifierList(modifiers); |
| 2355 | 2352 |
| 2356 if (type == null) { | 2353 if (type == null) { |
| 2357 listener.handleNoType(name); | 2354 listener.handleNoType(name); |
| 2358 } else { | 2355 } else { |
| 2359 parseType(type, TypeContinuation.Optional); | 2356 parseType(type, TypeContinuation.Optional); |
| 2360 } | 2357 } |
| 2361 Token token; | 2358 Token token; |
| 2362 if (optional('operator', name)) { | 2359 if (optional('operator', name)) { |
| 2363 token = parseOperatorName(name); | 2360 token = parseOperatorName(name); |
| 2364 if (staticModifier != null) { | 2361 if (staticModifier != null) { |
| 2365 reportRecoverableErrorCodeWithToken( | 2362 reportRecoverableError( |
| 2366 staticModifier, fasta.codeExtraneousModifier); | 2363 staticModifier, fasta.codeExtraneousModifier.bind(staticModifier)); |
| 2367 } | 2364 } |
| 2368 } else { | 2365 } else { |
| 2369 token = parseIdentifier(name, IdentifierContext.methodDeclaration); | 2366 token = parseIdentifier(name, IdentifierContext.methodDeclaration); |
| 2370 } | 2367 } |
| 2371 | 2368 |
| 2372 token = parseQualifiedRestOpt( | 2369 token = parseQualifiedRestOpt( |
| 2373 token, IdentifierContext.methodDeclarationContinuation); | 2370 token, IdentifierContext.methodDeclarationContinuation); |
| 2374 bool isGetter = false; | 2371 bool isGetter = false; |
| 2375 if (getOrSet == null) { | 2372 if (getOrSet == null) { |
| 2376 token = parseTypeVariablesOpt(token); | 2373 token = parseTypeVariablesOpt(token); |
| 2377 } else { | 2374 } else { |
| 2378 isGetter = optional("get", getOrSet); | 2375 isGetter = optional("get", getOrSet); |
| 2379 listener.handleNoTypeVariables(token); | 2376 listener.handleNoTypeVariables(token); |
| 2380 } | 2377 } |
| 2381 checkFormals(isGetter, name, token); | 2378 checkFormals(isGetter, name, token); |
| 2382 token = parseFormalParametersOpt( | 2379 token = parseFormalParametersOpt( |
| 2383 token, | 2380 token, |
| 2384 staticModifier != null | 2381 staticModifier != null |
| 2385 ? MemberKind.StaticMethod | 2382 ? MemberKind.StaticMethod |
| 2386 : MemberKind.NonStaticMethod); | 2383 : MemberKind.NonStaticMethod); |
| 2387 token = parseInitializersOpt(token); | 2384 token = parseInitializersOpt(token); |
| 2388 AsyncModifier savedAsyncModifier = asyncState; | 2385 AsyncModifier savedAsyncModifier = asyncState; |
| 2389 Token asyncToken = token; | 2386 Token asyncToken = token; |
| 2390 token = parseAsyncModifier(token); | 2387 token = parseAsyncModifier(token); |
| 2391 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { | 2388 if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) { |
| 2392 reportRecoverableErrorCode(asyncToken, fasta.codeSetterNotSync); | 2389 reportRecoverableError(asyncToken, fasta.codeSetterNotSync); |
| 2393 } | 2390 } |
| 2394 if (optional('=', token)) { | 2391 if (optional('=', token)) { |
| 2395 token = parseRedirectingFactoryBody(token); | 2392 token = parseRedirectingFactoryBody(token); |
| 2396 } else { | 2393 } else { |
| 2397 token = parseFunctionBody( | 2394 token = parseFunctionBody( |
| 2398 token, false, staticModifier == null || externalModifier != null); | 2395 token, false, staticModifier == null || externalModifier != null); |
| 2399 } | 2396 } |
| 2400 asyncState = savedAsyncModifier; | 2397 asyncState = savedAsyncModifier; |
| 2401 listener.endMethod(getOrSet, start, token); | 2398 listener.endMethod(getOrSet, start, token); |
| 2402 return token.next; | 2399 return token.next; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2416 } | 2413 } |
| 2417 listener.handleModifiers(modifierCount); | 2414 listener.handleModifiers(modifierCount); |
| 2418 Token factoryKeyword = token; | 2415 Token factoryKeyword = token; |
| 2419 listener.beginFactoryMethod(factoryKeyword); | 2416 listener.beginFactoryMethod(factoryKeyword); |
| 2420 token = expect('factory', token); | 2417 token = expect('factory', token); |
| 2421 token = parseConstructorReference(token); | 2418 token = parseConstructorReference(token); |
| 2422 token = parseFormalParameters(token, MemberKind.Factory); | 2419 token = parseFormalParameters(token, MemberKind.Factory); |
| 2423 Token asyncToken = token; | 2420 Token asyncToken = token; |
| 2424 token = parseAsyncModifier(token); | 2421 token = parseAsyncModifier(token); |
| 2425 if (!inPlainSync) { | 2422 if (!inPlainSync) { |
| 2426 reportRecoverableErrorCode(asyncToken, fasta.codeFactoryNotSync); | 2423 reportRecoverableError(asyncToken, fasta.codeFactoryNotSync); |
| 2427 } | 2424 } |
| 2428 if (optional('=', token)) { | 2425 if (optional('=', token)) { |
| 2429 token = parseRedirectingFactoryBody(token); | 2426 token = parseRedirectingFactoryBody(token); |
| 2430 } else { | 2427 } else { |
| 2431 token = parseFunctionBody(token, false, isExternal); | 2428 token = parseFunctionBody(token, false, isExternal); |
| 2432 } | 2429 } |
| 2433 listener.endFactoryMethod(start, factoryKeyword, token); | 2430 listener.endFactoryMethod(start, factoryKeyword, token); |
| 2434 return token.next; | 2431 return token.next; |
| 2435 } | 2432 } |
| 2436 | 2433 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2536 listener.endRedirectingFactoryBody(equals, semicolon); | 2533 listener.endRedirectingFactoryBody(equals, semicolon); |
| 2537 return token; | 2534 return token; |
| 2538 } | 2535 } |
| 2539 | 2536 |
| 2540 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 2537 Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
| 2541 assert(!isExpression); | 2538 assert(!isExpression); |
| 2542 token = skipAsyncModifier(token); | 2539 token = skipAsyncModifier(token); |
| 2543 String value = token.stringValue; | 2540 String value = token.stringValue; |
| 2544 if (identical(value, ';')) { | 2541 if (identical(value, ';')) { |
| 2545 if (!allowAbstract) { | 2542 if (!allowAbstract) { |
| 2546 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2543 reportRecoverableError(token, fasta.codeExpectedBody); |
| 2547 } | 2544 } |
| 2548 listener.handleNoFunctionBody(token); | 2545 listener.handleNoFunctionBody(token); |
| 2549 } else { | 2546 } else { |
| 2550 if (identical(value, '=>')) { | 2547 if (identical(value, '=>')) { |
| 2551 token = parseExpression(token.next); | 2548 token = parseExpression(token.next); |
| 2552 expectSemicolon(token); | 2549 expectSemicolon(token); |
| 2553 listener.handleFunctionBodySkipped(token, true); | 2550 listener.handleFunctionBodySkipped(token, true); |
| 2554 } else if (identical(value, '=')) { | 2551 } else if (identical(value, '=')) { |
| 2555 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2552 reportRecoverableError(token, fasta.codeExpectedBody); |
| 2556 token = parseExpression(token.next); | 2553 token = parseExpression(token.next); |
| 2557 expectSemicolon(token); | 2554 expectSemicolon(token); |
| 2558 listener.handleFunctionBodySkipped(token, true); | 2555 listener.handleFunctionBodySkipped(token, true); |
| 2559 } else { | 2556 } else { |
| 2560 token = skipBlock(token); | 2557 token = skipBlock(token); |
| 2561 listener.handleFunctionBodySkipped(token, false); | 2558 listener.handleFunctionBodySkipped(token, false); |
| 2562 } | 2559 } |
| 2563 } | 2560 } |
| 2564 return token; | 2561 return token; |
| 2565 } | 2562 } |
| 2566 | 2563 |
| 2567 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 2564 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
| 2568 if (optional(';', token)) { | 2565 if (optional(';', token)) { |
| 2569 if (!allowAbstract) { | 2566 if (!allowAbstract) { |
| 2570 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2567 reportRecoverableError(token, fasta.codeExpectedBody); |
| 2571 } | 2568 } |
| 2572 listener.handleEmptyFunctionBody(token); | 2569 listener.handleEmptyFunctionBody(token); |
| 2573 return token; | 2570 return token; |
| 2574 } else if (optional('=>', token)) { | 2571 } else if (optional('=>', token)) { |
| 2575 Token begin = token; | 2572 Token begin = token; |
| 2576 token = parseExpression(token.next); | 2573 token = parseExpression(token.next); |
| 2577 if (!isExpression) { | 2574 if (!isExpression) { |
| 2578 expectSemicolon(token); | 2575 expectSemicolon(token); |
| 2579 listener.handleExpressionFunctionBody(begin, token); | 2576 listener.handleExpressionFunctionBody(begin, token); |
| 2580 } else { | 2577 } else { |
| 2581 listener.handleExpressionFunctionBody(begin, null); | 2578 listener.handleExpressionFunctionBody(begin, null); |
| 2582 } | 2579 } |
| 2583 return token; | 2580 return token; |
| 2584 } else if (optional('=', token)) { | 2581 } else if (optional('=', token)) { |
| 2585 Token begin = token; | 2582 Token begin = token; |
| 2586 // Recover from a bad factory method. | 2583 // Recover from a bad factory method. |
| 2587 reportRecoverableErrorCode(token, fasta.codeExpectedBody); | 2584 reportRecoverableError(token, fasta.codeExpectedBody); |
| 2588 token = parseExpression(token.next); | 2585 token = parseExpression(token.next); |
| 2589 if (!isExpression) { | 2586 if (!isExpression) { |
| 2590 expectSemicolon(token); | 2587 expectSemicolon(token); |
| 2591 listener.handleExpressionFunctionBody(begin, token); | 2588 listener.handleExpressionFunctionBody(begin, token); |
| 2592 } else { | 2589 } else { |
| 2593 listener.handleExpressionFunctionBody(begin, null); | 2590 listener.handleExpressionFunctionBody(begin, null); |
| 2594 } | 2591 } |
| 2595 return token; | 2592 return token; |
| 2596 } | 2593 } |
| 2597 Token begin = token; | 2594 Token begin = token; |
| 2598 int statementCount = 0; | 2595 int statementCount = 0; |
| 2599 if (!optional('{', token)) { | 2596 if (!optional('{', token)) { |
| 2600 token = reportUnrecoverableErrorCodeWithToken( | 2597 token = reportUnrecoverableError( |
| 2601 token, fasta.codeExpectedFunctionBody) | 2598 token, fasta.codeExpectedFunctionBody.bind(token)) |
| 2602 .next; | 2599 .next; |
| 2603 listener.handleInvalidFunctionBody(token); | 2600 listener.handleInvalidFunctionBody(token); |
| 2604 return token; | 2601 return token; |
| 2605 } | 2602 } |
| 2606 | 2603 |
| 2607 listener.beginBlockFunctionBody(begin); | 2604 listener.beginBlockFunctionBody(begin); |
| 2608 token = token.next; | 2605 token = token.next; |
| 2609 while (notEofOrValue('}', token)) { | 2606 while (notEofOrValue('}', token)) { |
| 2610 token = parseStatement(token); | 2607 token = parseStatement(token); |
| 2611 ++statementCount; | 2608 ++statementCount; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2650 asyncState = AsyncModifier.Async; | 2647 asyncState = AsyncModifier.Async; |
| 2651 } | 2648 } |
| 2652 } else if (optional('sync', token)) { | 2649 } else if (optional('sync', token)) { |
| 2653 async = token; | 2650 async = token; |
| 2654 token = token.next; | 2651 token = token.next; |
| 2655 if (optional('*', token)) { | 2652 if (optional('*', token)) { |
| 2656 asyncState = AsyncModifier.SyncStar; | 2653 asyncState = AsyncModifier.SyncStar; |
| 2657 star = token; | 2654 star = token; |
| 2658 token = token.next; | 2655 token = token.next; |
| 2659 } else { | 2656 } else { |
| 2660 reportRecoverableErrorCode(async, fasta.codeInvalidSyncModifier); | 2657 reportRecoverableError(async, fasta.codeInvalidSyncModifier); |
| 2661 } | 2658 } |
| 2662 } | 2659 } |
| 2663 listener.handleAsyncModifier(async, star); | 2660 listener.handleAsyncModifier(async, star); |
| 2664 if (inGenerator && optional('=>', token)) { | 2661 if (inGenerator && optional('=>', token)) { |
| 2665 reportRecoverableErrorCode(token, fasta.codeGeneratorReturnsValue); | 2662 reportRecoverableError(token, fasta.codeGeneratorReturnsValue); |
| 2666 } else if (!inPlainSync && optional(';', token)) { | 2663 } else if (!inPlainSync && optional(';', token)) { |
| 2667 reportRecoverableErrorCode(token, fasta.codeAbstractNotSync); | 2664 reportRecoverableError(token, fasta.codeAbstractNotSync); |
| 2668 } | 2665 } |
| 2669 return token; | 2666 return token; |
| 2670 } | 2667 } |
| 2671 | 2668 |
| 2672 int statementDepth = 0; | 2669 int statementDepth = 0; |
| 2673 Token parseStatement(Token token) { | 2670 Token parseStatement(Token token) { |
| 2674 if (statementDepth++ > 500) { | 2671 if (statementDepth++ > 500) { |
| 2675 // This happens for degenerate programs, for example, a lot of nested | 2672 // This happens for degenerate programs, for example, a lot of nested |
| 2676 // if-statements. The language test deep_nesting2_negative_test, for | 2673 // if-statements. The language test deep_nesting2_negative_test, for |
| 2677 // example, provokes this. | 2674 // example, provokes this. |
| 2678 return reportUnrecoverableErrorCode(token, fasta.codeStackOverflow).next; | 2675 return reportUnrecoverableError(token, fasta.codeStackOverflow).next; |
| 2679 } | 2676 } |
| 2680 Token result = parseStatementX(token); | 2677 Token result = parseStatementX(token); |
| 2681 statementDepth--; | 2678 statementDepth--; |
| 2682 return result; | 2679 return result; |
| 2683 } | 2680 } |
| 2684 | 2681 |
| 2685 Token parseStatementX(Token token) { | 2682 Token parseStatementX(Token token) { |
| 2686 final value = token.stringValue; | 2683 final value = token.stringValue; |
| 2687 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 2684 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
| 2688 return parseExpressionStatementOrDeclaration(token); | 2685 return parseExpressionStatementOrDeclaration(token); |
| 2689 } else if (identical(value, '{')) { | 2686 } else if (identical(value, '{')) { |
| 2690 return parseBlock(token); | 2687 return parseBlock(token); |
| 2691 } else if (identical(value, 'return')) { | 2688 } else if (identical(value, 'return')) { |
| 2692 return parseReturnStatement(token); | 2689 return parseReturnStatement(token); |
| 2693 } else if (identical(value, 'var') || identical(value, 'final')) { | 2690 } else if (identical(value, 'var') || identical(value, 'final')) { |
| 2694 return parseVariablesDeclaration(token); | 2691 return parseVariablesDeclaration(token); |
| 2695 } else if (identical(value, 'if')) { | 2692 } else if (identical(value, 'if')) { |
| 2696 return parseIfStatement(token); | 2693 return parseIfStatement(token); |
| 2697 } else if (identical(value, 'await') && optional('for', token.next)) { | 2694 } else if (identical(value, 'await') && optional('for', token.next)) { |
| 2698 if (!inAsync) { | 2695 if (!inAsync) { |
| 2699 reportRecoverableErrorCode(token, fasta.codeAwaitForNotAsync); | 2696 reportRecoverableError(token, fasta.codeAwaitForNotAsync); |
| 2700 } | 2697 } |
| 2701 return parseForStatement(token, token.next); | 2698 return parseForStatement(token, token.next); |
| 2702 } else if (identical(value, 'for')) { | 2699 } else if (identical(value, 'for')) { |
| 2703 return parseForStatement(null, token); | 2700 return parseForStatement(null, token); |
| 2704 } else if (identical(value, 'rethrow')) { | 2701 } else if (identical(value, 'rethrow')) { |
| 2705 return parseRethrowStatement(token); | 2702 return parseRethrowStatement(token); |
| 2706 } else if (identical(value, 'throw') && optional(';', token.next)) { | 2703 } else if (identical(value, 'throw') && optional(';', token.next)) { |
| 2707 // TODO(kasperl): Stop dealing with throw here. | 2704 // TODO(kasperl): Stop dealing with throw here. |
| 2708 return parseRethrowStatement(token); | 2705 return parseRethrowStatement(token); |
| 2709 } else if (identical(value, 'void')) { | 2706 } else if (identical(value, 'void')) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2727 } else if (identical(value, 'yield')) { | 2724 } else if (identical(value, 'yield')) { |
| 2728 switch (asyncState) { | 2725 switch (asyncState) { |
| 2729 case AsyncModifier.Sync: | 2726 case AsyncModifier.Sync: |
| 2730 return parseExpressionStatementOrDeclaration(token); | 2727 return parseExpressionStatementOrDeclaration(token); |
| 2731 | 2728 |
| 2732 case AsyncModifier.SyncStar: | 2729 case AsyncModifier.SyncStar: |
| 2733 case AsyncModifier.AsyncStar: | 2730 case AsyncModifier.AsyncStar: |
| 2734 return parseYieldStatement(token); | 2731 return parseYieldStatement(token); |
| 2735 | 2732 |
| 2736 case AsyncModifier.Async: | 2733 case AsyncModifier.Async: |
| 2737 reportRecoverableErrorCode(token, fasta.codeYieldNotGenerator); | 2734 reportRecoverableError(token, fasta.codeYieldNotGenerator); |
| 2738 return parseYieldStatement(token); | 2735 return parseYieldStatement(token); |
| 2739 } | 2736 } |
| 2740 throw "Internal error: Unknown asyncState: '$asyncState'."; | 2737 throw "Internal error: Unknown asyncState: '$asyncState'."; |
| 2741 } else if (identical(value, 'const')) { | 2738 } else if (identical(value, 'const')) { |
| 2742 return parseExpressionStatementOrConstDeclaration(token); | 2739 return parseExpressionStatementOrConstDeclaration(token); |
| 2743 } else if (token.isIdentifier) { | 2740 } else if (token.isIdentifier) { |
| 2744 return parseExpressionStatementOrDeclaration(token); | 2741 return parseExpressionStatementOrDeclaration(token); |
| 2745 } else if (identical(value, '@')) { | 2742 } else if (identical(value, '@')) { |
| 2746 return parseVariablesDeclaration(token); | 2743 return parseVariablesDeclaration(token); |
| 2747 } else { | 2744 } else { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2767 Token parseReturnStatement(Token token) { | 2764 Token parseReturnStatement(Token token) { |
| 2768 Token begin = token; | 2765 Token begin = token; |
| 2769 listener.beginReturnStatement(begin); | 2766 listener.beginReturnStatement(begin); |
| 2770 assert(identical('return', token.stringValue)); | 2767 assert(identical('return', token.stringValue)); |
| 2771 token = token.next; | 2768 token = token.next; |
| 2772 if (optional(';', token)) { | 2769 if (optional(';', token)) { |
| 2773 listener.endReturnStatement(false, begin, token); | 2770 listener.endReturnStatement(false, begin, token); |
| 2774 } else { | 2771 } else { |
| 2775 token = parseExpression(token); | 2772 token = parseExpression(token); |
| 2776 if (inGenerator) { | 2773 if (inGenerator) { |
| 2777 reportRecoverableErrorCode(begin.next, fasta.codeGeneratorReturnsValue); | 2774 reportRecoverableError(begin.next, fasta.codeGeneratorReturnsValue); |
| 2778 } | 2775 } |
| 2779 listener.endReturnStatement(true, begin, token); | 2776 listener.endReturnStatement(true, begin, token); |
| 2780 } | 2777 } |
| 2781 return expectSemicolon(token); | 2778 return expectSemicolon(token); |
| 2782 } | 2779 } |
| 2783 | 2780 |
| 2784 Token parseExpressionStatementOrDeclaration(Token token) { | 2781 Token parseExpressionStatementOrDeclaration(Token token) { |
| 2785 return parseType(token, TypeContinuation.ExpressionStatementOrDeclaration); | 2782 return parseType(token, TypeContinuation.ExpressionStatementOrDeclaration); |
| 2786 } | 2783 } |
| 2787 | 2784 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2889 | 2886 |
| 2890 Token parseRecoverExpression(Token token, FastaMessage message) => | 2887 Token parseRecoverExpression(Token token, FastaMessage message) => |
| 2891 parseExpression(token); | 2888 parseExpression(token); |
| 2892 | 2889 |
| 2893 int expressionDepth = 0; | 2890 int expressionDepth = 0; |
| 2894 Token parseExpression(Token token) { | 2891 Token parseExpression(Token token) { |
| 2895 if (expressionDepth++ > 500) { | 2892 if (expressionDepth++ > 500) { |
| 2896 // This happens in degenerate programs, for example, with a lot of nested | 2893 // This happens in degenerate programs, for example, with a lot of nested |
| 2897 // list literals. This is provoked by, for examaple, the language test | 2894 // list literals. This is provoked by, for examaple, the language test |
| 2898 // deep_nesting1_negative_test. | 2895 // deep_nesting1_negative_test. |
| 2899 return reportUnrecoverableErrorCode(token, fasta.codeStackOverflow).next; | 2896 return reportUnrecoverableError(token, fasta.codeStackOverflow).next; |
| 2900 } | 2897 } |
| 2901 listener.beginExpression(token); | 2898 listener.beginExpression(token); |
| 2902 Token result = optional('throw', token) | 2899 Token result = optional('throw', token) |
| 2903 ? parseThrowExpression(token, true) | 2900 ? parseThrowExpression(token, true) |
| 2904 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); | 2901 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); |
| 2905 expressionDepth--; | 2902 expressionDepth--; |
| 2906 return result; | 2903 return result; |
| 2907 } | 2904 } |
| 2908 | 2905 |
| 2909 Token parseExpressionWithoutCascade(Token token) { | 2906 Token parseExpressionWithoutCascade(Token token) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3030 String value = token.stringValue; | 3027 String value = token.stringValue; |
| 3031 // Prefix: | 3028 // Prefix: |
| 3032 if (optional('await', token)) { | 3029 if (optional('await', token)) { |
| 3033 if (inPlainSync) { | 3030 if (inPlainSync) { |
| 3034 return parsePrimary(token, IdentifierContext.expression); | 3031 return parsePrimary(token, IdentifierContext.expression); |
| 3035 } else { | 3032 } else { |
| 3036 return parseAwaitExpression(token, allowCascades); | 3033 return parseAwaitExpression(token, allowCascades); |
| 3037 } | 3034 } |
| 3038 } else if (identical(value, '+')) { | 3035 } else if (identical(value, '+')) { |
| 3039 // Dart no longer allows prefix-plus. | 3036 // Dart no longer allows prefix-plus. |
| 3040 reportRecoverableErrorCode(token, fasta.codeUnsupportedPrefixPlus); | 3037 reportRecoverableError(token, fasta.codeUnsupportedPrefixPlus); |
| 3041 return parseUnaryExpression(token.next, allowCascades); | 3038 return parseUnaryExpression(token.next, allowCascades); |
| 3042 } else if ((identical(value, '!')) || | 3039 } else if ((identical(value, '!')) || |
| 3043 (identical(value, '-')) || | 3040 (identical(value, '-')) || |
| 3044 (identical(value, '~'))) { | 3041 (identical(value, '~'))) { |
| 3045 Token operator = token; | 3042 Token operator = token; |
| 3046 // Right associative, so we recurse at the same precedence | 3043 // Right associative, so we recurse at the same precedence |
| 3047 // level. | 3044 // level. |
| 3048 token = parsePrecedenceExpression( | 3045 token = parsePrecedenceExpression( |
| 3049 token.next, POSTFIX_PRECEDENCE, allowCascades); | 3046 token.next, POSTFIX_PRECEDENCE, allowCascades); |
| 3050 listener.handleUnaryPrefixExpression(operator); | 3047 listener.handleUnaryPrefixExpression(operator); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3133 listener.handleNoTypeArguments(token); | 3130 listener.handleNoTypeArguments(token); |
| 3134 return parseLiteralMapSuffix(token, null); | 3131 return parseLiteralMapSuffix(token, null); |
| 3135 } else if (kind == LT_TOKEN) { | 3132 } else if (kind == LT_TOKEN) { |
| 3136 return parseLiteralListOrMapOrFunction(token, null); | 3133 return parseLiteralListOrMapOrFunction(token, null); |
| 3137 } else { | 3134 } else { |
| 3138 return expressionExpected(token); | 3135 return expressionExpected(token); |
| 3139 } | 3136 } |
| 3140 } | 3137 } |
| 3141 | 3138 |
| 3142 Token expressionExpected(Token token) { | 3139 Token expressionExpected(Token token) { |
| 3143 token = reportUnrecoverableErrorCodeWithToken( | 3140 token = reportUnrecoverableError( |
| 3144 token, fasta.codeExpectedExpression) | 3141 token, fasta.codeExpectedExpression.bind(token)) |
| 3145 .next; | 3142 .next; |
| 3146 listener.handleInvalidExpression(token); | 3143 listener.handleInvalidExpression(token); |
| 3147 return token; | 3144 return token; |
| 3148 } | 3145 } |
| 3149 | 3146 |
| 3150 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 3147 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
| 3151 BeginToken beginGroup = token; | 3148 BeginToken beginGroup = token; |
| 3152 Token nextToken = beginGroup.endGroup.next; | 3149 Token nextToken = beginGroup.endGroup.next; |
| 3153 int kind = nextToken.kind; | 3150 int kind = nextToken.kind; |
| 3154 if (mayParseFunctionExpressions && | 3151 if (mayParseFunctionExpressions && |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3199 Token parseSuperExpression(Token token, IdentifierContext context) { | 3196 Token parseSuperExpression(Token token, IdentifierContext context) { |
| 3200 Token beginToken = token; | 3197 Token beginToken = token; |
| 3201 listener.handleSuperExpression(token, context); | 3198 listener.handleSuperExpression(token, context); |
| 3202 token = token.next; | 3199 token = token.next; |
| 3203 if (optional('(', token)) { | 3200 if (optional('(', token)) { |
| 3204 // Super constructor. | 3201 // Super constructor. |
| 3205 listener.handleNoTypeArguments(token); | 3202 listener.handleNoTypeArguments(token); |
| 3206 token = parseArguments(token); | 3203 token = parseArguments(token); |
| 3207 listener.endSend(beginToken, token); | 3204 listener.endSend(beginToken, token); |
| 3208 } else if (optional("?.", token)) { | 3205 } else if (optional("?.", token)) { |
| 3209 reportRecoverableErrorCode(token, fasta.codeSuperNullAware); | 3206 reportRecoverableError(token, fasta.codeSuperNullAware); |
| 3210 } | 3207 } |
| 3211 return token; | 3208 return token; |
| 3212 } | 3209 } |
| 3213 | 3210 |
| 3214 /// '[' (expressionList ','?)? ']'. | 3211 /// '[' (expressionList ','?)? ']'. |
| 3215 /// | 3212 /// |
| 3216 /// Provide [constKeyword] if preceded by 'const', null if not. | 3213 /// Provide [constKeyword] if preceded by 'const', null if not. |
| 3217 /// This is a suffix parser because it is assumed that type arguments have | 3214 /// This is a suffix parser because it is assumed that type arguments have |
| 3218 /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed. | 3215 /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed. |
| 3219 Token parseLiteralListSuffix(Token token, Token constKeyword) { | 3216 Token parseLiteralListSuffix(Token token, Token constKeyword) { |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3675 Token forKeyword = token; | 3672 Token forKeyword = token; |
| 3676 listener.beginForStatement(forKeyword); | 3673 listener.beginForStatement(forKeyword); |
| 3677 token = expect('for', token); | 3674 token = expect('for', token); |
| 3678 Token leftParenthesis = token; | 3675 Token leftParenthesis = token; |
| 3679 token = expect('(', token); | 3676 token = expect('(', token); |
| 3680 token = parseVariablesDeclarationOrExpressionOpt(token); | 3677 token = parseVariablesDeclarationOrExpressionOpt(token); |
| 3681 if (optional('in', token)) { | 3678 if (optional('in', token)) { |
| 3682 return parseForInRest(awaitToken, forKeyword, leftParenthesis, token); | 3679 return parseForInRest(awaitToken, forKeyword, leftParenthesis, token); |
| 3683 } else { | 3680 } else { |
| 3684 if (awaitToken != null) { | 3681 if (awaitToken != null) { |
| 3685 reportRecoverableErrorCode(awaitToken, fasta.codeInvalidAwaitFor); | 3682 reportRecoverableError(awaitToken, fasta.codeInvalidAwaitFor); |
| 3686 } | 3683 } |
| 3687 return parseForRest(forKeyword, leftParenthesis, token); | 3684 return parseForRest(forKeyword, leftParenthesis, token); |
| 3688 } | 3685 } |
| 3689 } | 3686 } |
| 3690 | 3687 |
| 3691 Token parseVariablesDeclarationOrExpressionOpt(Token token) { | 3688 Token parseVariablesDeclarationOrExpressionOpt(Token token) { |
| 3692 final String value = token.stringValue; | 3689 final String value = token.stringValue; |
| 3693 if (identical(value, ';')) { | 3690 if (identical(value, ';')) { |
| 3694 listener.handleNoExpression(token); | 3691 listener.handleNoExpression(token); |
| 3695 return token; | 3692 return token; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3781 } | 3778 } |
| 3782 listener.endBlock(statementCount, begin, token); | 3779 listener.endBlock(statementCount, begin, token); |
| 3783 return expect('}', token); | 3780 return expect('}', token); |
| 3784 } | 3781 } |
| 3785 | 3782 |
| 3786 Token parseAwaitExpression(Token token, bool allowCascades) { | 3783 Token parseAwaitExpression(Token token, bool allowCascades) { |
| 3787 Token awaitToken = token; | 3784 Token awaitToken = token; |
| 3788 listener.beginAwaitExpression(awaitToken); | 3785 listener.beginAwaitExpression(awaitToken); |
| 3789 token = expect('await', token); | 3786 token = expect('await', token); |
| 3790 if (!inAsync) { | 3787 if (!inAsync) { |
| 3791 reportRecoverableErrorCode(awaitToken, fasta.codeAwaitNotAsync); | 3788 reportRecoverableError(awaitToken, fasta.codeAwaitNotAsync); |
| 3792 } | 3789 } |
| 3793 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades); | 3790 token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades); |
| 3794 listener.endAwaitExpression(awaitToken, token); | 3791 listener.endAwaitExpression(awaitToken, token); |
| 3795 return token; | 3792 return token; |
| 3796 } | 3793 } |
| 3797 | 3794 |
| 3798 Token parseThrowExpression(Token token, bool allowCascades) { | 3795 Token parseThrowExpression(Token token, bool allowCascades) { |
| 3799 Token throwToken = token; | 3796 Token throwToken = token; |
| 3800 listener.beginThrowExpression(throwToken); | 3797 listener.beginThrowExpression(throwToken); |
| 3801 token = expect('throw', token); | 3798 token = expect('throw', token); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3840 if (identical(value, 'catch')) { | 3837 if (identical(value, 'catch')) { |
| 3841 catchKeyword = token; | 3838 catchKeyword = token; |
| 3842 Token openParens = catchKeyword.next; | 3839 Token openParens = catchKeyword.next; |
| 3843 Token exceptionName = openParens.next; | 3840 Token exceptionName = openParens.next; |
| 3844 Token commaOrCloseParens = exceptionName.next; | 3841 Token commaOrCloseParens = exceptionName.next; |
| 3845 Token traceName = commaOrCloseParens.next; | 3842 Token traceName = commaOrCloseParens.next; |
| 3846 Token closeParens = traceName.next; | 3843 Token closeParens = traceName.next; |
| 3847 if (!optional("(", openParens)) { | 3844 if (!optional("(", openParens)) { |
| 3848 // Handled below by parseFormalParameters. | 3845 // Handled below by parseFormalParameters. |
| 3849 } else if (!exceptionName.isIdentifier) { | 3846 } else if (!exceptionName.isIdentifier) { |
| 3850 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3847 reportRecoverableError(exceptionName, fasta.codeCatchSyntax); |
| 3851 } else if (optional(")", commaOrCloseParens)) { | 3848 } else if (optional(")", commaOrCloseParens)) { |
| 3852 // OK: `catch (identifier)`. | 3849 // OK: `catch (identifier)`. |
| 3853 } else if (!optional(",", commaOrCloseParens)) { | 3850 } else if (!optional(",", commaOrCloseParens)) { |
| 3854 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3851 reportRecoverableError(exceptionName, fasta.codeCatchSyntax); |
| 3855 } else if (!traceName.isIdentifier) { | 3852 } else if (!traceName.isIdentifier) { |
| 3856 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3853 reportRecoverableError(exceptionName, fasta.codeCatchSyntax); |
| 3857 } else if (!optional(")", closeParens)) { | 3854 } else if (!optional(")", closeParens)) { |
| 3858 reportRecoverableErrorCode(exceptionName, fasta.codeCatchSyntax); | 3855 reportRecoverableError(exceptionName, fasta.codeCatchSyntax); |
| 3859 } | 3856 } |
| 3860 token = parseFormalParameters(token.next, MemberKind.Catch); | 3857 token = parseFormalParameters(token.next, MemberKind.Catch); |
| 3861 } | 3858 } |
| 3862 listener.endCatchClause(token); | 3859 listener.endCatchClause(token); |
| 3863 token = parseBlock(token); | 3860 token = parseBlock(token); |
| 3864 ++catchCount; | 3861 ++catchCount; |
| 3865 listener.handleCatchBlock(onKeyword, catchKeyword); | 3862 listener.handleCatchBlock(onKeyword, catchKeyword); |
| 3866 value = token.stringValue; // while condition | 3863 value = token.stringValue; // while condition |
| 3867 } | 3864 } |
| 3868 | 3865 |
| 3869 Token finallyKeyword = null; | 3866 Token finallyKeyword = null; |
| 3870 if (optional('finally', token)) { | 3867 if (optional('finally', token)) { |
| 3871 finallyKeyword = token; | 3868 finallyKeyword = token; |
| 3872 token = parseBlock(token.next); | 3869 token = parseBlock(token.next); |
| 3873 listener.handleFinallyBlock(finallyKeyword); | 3870 listener.handleFinallyBlock(finallyKeyword); |
| 3874 } else { | 3871 } else { |
| 3875 if (catchCount == 0) { | 3872 if (catchCount == 0) { |
| 3876 reportRecoverableErrorCode(tryKeyword, fasta.codeOnlyTry); | 3873 reportRecoverableError(tryKeyword, fasta.codeOnlyTry); |
| 3877 } | 3874 } |
| 3878 } | 3875 } |
| 3879 listener.endTryStatement(catchCount, tryKeyword, finallyKeyword); | 3876 listener.endTryStatement(catchCount, tryKeyword, finallyKeyword); |
| 3880 return token; | 3877 return token; |
| 3881 } | 3878 } |
| 3882 | 3879 |
| 3883 Token parseSwitchStatement(Token token) { | 3880 Token parseSwitchStatement(Token token) { |
| 3884 assert(optional('switch', token)); | 3881 assert(optional('switch', token)); |
| 3885 Token switchKeyword = token; | 3882 Token switchKeyword = token; |
| 3886 listener.beginSwitchStatement(switchKeyword); | 3883 listener.beginSwitchStatement(switchKeyword); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3947 token = parseExpression(token.next); | 3944 token = parseExpression(token.next); |
| 3948 listener.endCaseExpression(token); | 3945 listener.endCaseExpression(token); |
| 3949 Token colonToken = token; | 3946 Token colonToken = token; |
| 3950 token = expect(':', token); | 3947 token = expect(':', token); |
| 3951 listener.handleCaseMatch(caseKeyword, colonToken); | 3948 listener.handleCaseMatch(caseKeyword, colonToken); |
| 3952 expressionCount++; | 3949 expressionCount++; |
| 3953 peek = peekPastLabels(token); | 3950 peek = peekPastLabels(token); |
| 3954 } else { | 3951 } else { |
| 3955 if (expressionCount == 0) { | 3952 if (expressionCount == 0) { |
| 3956 // TODO(ahe): This is probably easy to recover from. | 3953 // TODO(ahe): This is probably easy to recover from. |
| 3957 reportUnrecoverableErrorCodeWithString( | 3954 reportUnrecoverableError( |
| 3958 token, fasta.codeExpectedButGot, "case"); | 3955 token, fasta.codeExpectedButGot.bind("case")); |
| 3959 } | 3956 } |
| 3960 break; | 3957 break; |
| 3961 } | 3958 } |
| 3962 } | 3959 } |
| 3963 listener.beginSwitchCase(labelCount, expressionCount, begin); | 3960 listener.beginSwitchCase(labelCount, expressionCount, begin); |
| 3964 // Finally zero or more statements. | 3961 // Finally zero or more statements. |
| 3965 int statementCount = 0; | 3962 int statementCount = 0; |
| 3966 while (!identical(token.kind, EOF_TOKEN)) { | 3963 while (!identical(token.kind, EOF_TOKEN)) { |
| 3967 String value = peek.stringValue; | 3964 String value = peek.stringValue; |
| 3968 if ((identical(value, 'case')) || | 3965 if ((identical(value, 'case')) || |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4008 commaToken = token; | 4005 commaToken = token; |
| 4009 token = token.next; | 4006 token = token.next; |
| 4010 token = parseExpression(token); | 4007 token = parseExpression(token); |
| 4011 } | 4008 } |
| 4012 if (optional(',', token)) { | 4009 if (optional(',', token)) { |
| 4013 Token firstExtra = token.next; | 4010 Token firstExtra = token.next; |
| 4014 while (optional(',', token)) { | 4011 while (optional(',', token)) { |
| 4015 token = token.next; | 4012 token = token.next; |
| 4016 Token begin = token; | 4013 Token begin = token; |
| 4017 token = parseExpression(token); | 4014 token = parseExpression(token); |
| 4018 listener.handleExtraneousExpression(begin, | 4015 listener.handleExtraneousExpression( |
| 4019 fasta.codeAssertExtraneousArgument.format(uri, token.charOffset)); | 4016 begin, fasta.codeAssertExtraneousArgument(uri, token.charOffset)); |
| 4020 } | 4017 } |
| 4021 reportRecoverableErrorCode( | 4018 reportRecoverableError(firstExtra, fasta.codeAssertExtraneousArgument); |
| 4022 firstExtra, fasta.codeAssertExtraneousArgument); | |
| 4023 } | 4019 } |
| 4024 Token rightParenthesis = token; | 4020 Token rightParenthesis = token; |
| 4025 token = expect(')', token); | 4021 token = expect(')', token); |
| 4026 mayParseFunctionExpressions = old; | 4022 mayParseFunctionExpressions = old; |
| 4027 listener.endAssert(assertKeyword, kind, leftParenthesis, commaToken, | 4023 listener.endAssert(assertKeyword, kind, leftParenthesis, commaToken, |
| 4028 rightParenthesis, token); | 4024 rightParenthesis, token); |
| 4029 if (kind == Assert.Expression) { | 4025 if (kind == Assert.Expression) { |
| 4030 reportRecoverableErrorCode(assertKeyword, fasta.codeAssertAsExpression); | 4026 reportRecoverableError(assertKeyword, fasta.codeAssertAsExpression); |
| 4031 } | 4027 } |
| 4032 return token; | 4028 return token; |
| 4033 } | 4029 } |
| 4034 | 4030 |
| 4035 Token parseAssertStatement(Token token) { | 4031 Token parseAssertStatement(Token token) { |
| 4036 token = parseAssert(token, Assert.Statement); | 4032 token = parseAssert(token, Assert.Statement); |
| 4037 return expectSemicolon(token); | 4033 return expectSemicolon(token); |
| 4038 } | 4034 } |
| 4039 | 4035 |
| 4040 Token parseContinueStatement(Token token) { | 4036 Token parseContinueStatement(Token token) { |
| 4041 assert(optional('continue', token)); | 4037 assert(optional('continue', token)); |
| 4042 Token continueKeyword = token; | 4038 Token continueKeyword = token; |
| 4043 token = token.next; | 4039 token = token.next; |
| 4044 bool hasTarget = false; | 4040 bool hasTarget = false; |
| 4045 if (token.isIdentifier) { | 4041 if (token.isIdentifier) { |
| 4046 token = parseIdentifier(token, IdentifierContext.labelReference); | 4042 token = parseIdentifier(token, IdentifierContext.labelReference); |
| 4047 hasTarget = true; | 4043 hasTarget = true; |
| 4048 } | 4044 } |
| 4049 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 4045 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 4050 return expectSemicolon(token); | 4046 return expectSemicolon(token); |
| 4051 } | 4047 } |
| 4052 | 4048 |
| 4053 Token parseEmptyStatement(Token token) { | 4049 Token parseEmptyStatement(Token token) { |
| 4054 listener.handleEmptyStatement(token); | 4050 listener.handleEmptyStatement(token); |
| 4055 return expectSemicolon(token); | 4051 return expectSemicolon(token); |
| 4056 } | 4052 } |
| 4057 | 4053 |
| 4058 /// Don't call this method. Should only be used as a last resort when there | 4054 /// 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. | 4055 /// is no feasible way to recover from a parser error. |
| 4060 Token reportUnrecoverableError(Token token, FastaMessage format()) { | 4056 Token reportUnrecoverableError( |
| 4057 Token token, FastaMessage Function(Uri, int) bind) { |
| 4061 Token next; | 4058 Token next; |
| 4062 if (token is ErrorToken) { | 4059 if (token is ErrorToken) { |
| 4063 next = reportErrorToken(token, false); | 4060 next = reportErrorToken(token, false); |
| 4064 } else { | 4061 } else { |
| 4065 next = listener.handleUnrecoverableError(token, format()); | 4062 next = |
| 4063 listener.handleUnrecoverableError(token, bind(uri, token.charOffset)); |
| 4066 } | 4064 } |
| 4067 return next ?? skipToEof(token); | 4065 return next ?? skipToEof(token); |
| 4068 } | 4066 } |
| 4069 | 4067 |
| 4070 void reportRecoverableError(Token token, FastaMessage format()) { | 4068 void reportRecoverableError( |
| 4069 Token token, FastaMessage Function(Uri, int) bind) { |
| 4071 if (token is ErrorToken) { | 4070 if (token is ErrorToken) { |
| 4072 reportErrorToken(token, true); | 4071 reportErrorToken(token, true); |
| 4073 } else { | 4072 } else { |
| 4074 listener.handleRecoverableError(token, format()); | 4073 listener.handleRecoverableError(token, bind(uri, token.charOffset)); |
| 4075 } | 4074 } |
| 4076 } | 4075 } |
| 4077 | 4076 |
| 4078 Token reportErrorToken(ErrorToken token, bool isRecoverable) { | 4077 Token reportErrorToken(ErrorToken token, bool isRecoverable) { |
| 4079 FastaCode code = token.errorCode; | 4078 FastaCode code = token.errorCode; |
| 4080 FastaMessage message; | 4079 BoundFastaMessage bind; |
| 4081 if (code == fasta.codeAsciiControlCharacter) { | 4080 if (code == fasta.codeAsciiControlCharacter) { |
| 4082 message = fasta.codeAsciiControlCharacter | 4081 bind = fasta.codeAsciiControlCharacter.bind(token.character); |
| 4083 .format(uri, token.charOffset, token.character); | |
| 4084 } else if (code == fasta.codeNonAsciiWhitespace) { | 4082 } else if (code == fasta.codeNonAsciiWhitespace) { |
| 4085 message = fasta.codeNonAsciiWhitespace | 4083 bind = fasta.codeNonAsciiWhitespace.bind(token.character); |
| 4086 .format(uri, token.charOffset, token.character); | |
| 4087 } else if (code == fasta.codeEncoding) { | 4084 } else if (code == fasta.codeEncoding) { |
| 4088 message = fasta.codeEncoding.format(uri, token.charOffset); | 4085 bind = fasta.codeEncoding; |
| 4089 } else if (code == fasta.codeNonAsciiIdentifier) { | 4086 } else if (code == fasta.codeNonAsciiIdentifier) { |
| 4090 message = fasta.codeNonAsciiIdentifier.format(uri, token.charOffset, | 4087 bind = fasta.codeNonAsciiIdentifier |
| 4091 new String.fromCharCodes([token.character]), token.character); | 4088 .bind(new String.fromCharCodes([token.character]), token.character); |
| 4092 } else if (code == fasta.codeUnterminatedString) { | 4089 } else if (code == fasta.codeUnterminatedString) { |
| 4093 message = fasta.codeUnterminatedString | 4090 bind = fasta.codeUnterminatedString.bind(token.start); |
| 4094 .format(uri, token.charOffset, token.start); | |
| 4095 } else if (code == fasta.codeUnmatchedToken) { | 4091 } else if (code == fasta.codeUnmatchedToken) { |
| 4096 Token begin = token.begin; | 4092 Token begin = token.begin; |
| 4097 message = fasta.codeUnmatchedToken | 4093 bind = fasta.codeUnmatchedToken.bind(closeBraceFor(begin.lexeme), begin); |
| 4098 .format(uri, token.charOffset, closeBraceFor(begin.lexeme), begin); | |
| 4099 } else if (code == fasta.codeUnspecified) { | 4094 } else if (code == fasta.codeUnspecified) { |
| 4100 message = fasta.codeUnspecified | 4095 bind = fasta.codeUnspecified.bind(token.assertionMessage); |
| 4101 .format(uri, token.charOffset, token.assertionMessage); | |
| 4102 } else { | 4096 } else { |
| 4103 message = code.format(uri, token.charOffset); | 4097 bind = code as BoundFastaCode; |
| 4104 } | 4098 } |
| 4105 if (isRecoverable) { | 4099 if (isRecoverable) { |
| 4106 listener.handleRecoverableError(token, message); | 4100 listener.handleRecoverableError(token, bind(uri, token.charOffset)); |
| 4107 return null; | 4101 return null; |
| 4108 } else { | 4102 } else { |
| 4109 Token next = listener.handleUnrecoverableError(token, message); | 4103 Token next = |
| 4104 listener.handleUnrecoverableError(token, bind(uri, token.charOffset)); |
| 4110 return next ?? skipToEof(token); | 4105 return next ?? skipToEof(token); |
| 4111 } | 4106 } |
| 4112 } | 4107 } |
| 4113 | 4108 |
| 4114 Token reportUnmatchedToken(BeginToken token) { | 4109 Token reportUnmatchedToken(BeginToken token) { |
| 4115 return reportUnrecoverableError( | 4110 return reportUnrecoverableError(token, |
| 4116 token, | 4111 fasta.codeUnmatchedToken.bind(closeBraceFor(token.lexeme), token)); |
| 4117 () => fasta.codeUnmatchedToken | |
| 4118 .format(uri, token.charOffset, closeBraceFor(token.lexeme), token)); | |
| 4119 } | 4112 } |
| 4120 | 4113 |
| 4121 Token reportUnexpectedToken(Token token) { | 4114 Token reportUnexpectedToken(Token token) { |
| 4122 return reportUnrecoverableError(token, | |
| 4123 () => fasta.codeUnexpectedToken.format(uri, token.charOffset, token)); | |
| 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( | 4115 return reportUnrecoverableError( |
| 4132 token, () => code.format(uri, token.charOffset)); | 4116 token, fasta.codeUnexpectedToken.bind(token)); |
| 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 } | 4117 } |
| 4152 } | 4118 } |
| 4153 | |
| 4154 typedef FastaMessage NoArgument(Uri uri, int charOffset); | |
| 4155 | |
| 4156 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); | |
| 4157 | |
| 4158 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); | |
| OLD | NEW |