Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2965393002: Use FastaMessage instead of String. Part 1. (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698