| 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 '../scanner.dart' show ErrorToken; | 7 import '../scanner.dart' show ErrorToken; |
| 8 | 8 |
| 9 import '../scanner/recover.dart' show closeBraceFor, skipToEof; | 9 import '../scanner/recover.dart' show closeBraceFor, skipToEof; |
| 10 | 10 |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 | 453 |
| 454 Token skipFormalParameters(Token token) { | 454 Token skipFormalParameters(Token token) { |
| 455 // TODO(ahe): Shouldn't this be `beginFormalParameters`? | 455 // TODO(ahe): Shouldn't this be `beginFormalParameters`? |
| 456 listener.beginOptionalFormalParameters(token); | 456 listener.beginOptionalFormalParameters(token); |
| 457 if (!optional('(', token)) { | 457 if (!optional('(', token)) { |
| 458 if (optional(';', token)) { | 458 if (optional(';', token)) { |
| 459 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); | 459 reportRecoverableError(token, ErrorKind.ExpectedOpenParens); |
| 460 return token; | 460 return token; |
| 461 } | 461 } |
| 462 return reportUnrecoverableError( | 462 return reportUnrecoverableError( |
| 463 token, ErrorKind.ExpectedButGot, {"expected": "("}); | 463 token, ErrorKind.ExpectedButGot, {"expected": "("})?.next; |
| 464 } | 464 } |
| 465 BeginGroupToken beginGroupToken = token; | 465 BeginGroupToken beginGroupToken = token; |
| 466 Token endToken = beginGroupToken.endGroup; | 466 Token endToken = beginGroupToken.endGroup; |
| 467 listener.endFormalParameters(0, token, endToken); | 467 listener.endFormalParameters(0, token, endToken); |
| 468 return endToken.next; | 468 return endToken.next; |
| 469 } | 469 } |
| 470 | 470 |
| 471 /// Parses the formal parameter list of a function. | 471 /// Parses the formal parameter list of a function. |
| 472 /// | 472 /// |
| 473 /// If [inFunctionType] is true, then the names may be omitted (except for | 473 /// If [inFunctionType] is true, then the names may be omitted (except for |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 Token parseQualifiedRest(Token token, IdentifierContext context) { | 745 Token parseQualifiedRest(Token token, IdentifierContext context) { |
| 746 assert(optional('.', token)); | 746 assert(optional('.', token)); |
| 747 Token period = token; | 747 Token period = token; |
| 748 token = parseIdentifier(token.next, context); | 748 token = parseIdentifier(token.next, context); |
| 749 listener.handleQualified(period); | 749 listener.handleQualified(period); |
| 750 return token; | 750 return token; |
| 751 } | 751 } |
| 752 | 752 |
| 753 Token skipBlock(Token token) { | 753 Token skipBlock(Token token) { |
| 754 if (!optional('{', token)) { | 754 if (!optional('{', token)) { |
| 755 return reportUnrecoverableError(token, ErrorKind.ExpectedBlockToSkip); | 755 return reportUnrecoverableError(token, ErrorKind.ExpectedBlockToSkip) |
| 756 ?.next; |
| 756 } | 757 } |
| 757 BeginGroupToken beginGroupToken = token; | 758 BeginGroupToken beginGroupToken = token; |
| 758 Token endGroup = beginGroupToken.endGroup; | 759 Token endGroup = beginGroupToken.endGroup; |
| 759 if (endGroup == null) { | 760 if (endGroup == null) { |
| 760 return reportUnrecoverableError( | 761 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) |
| 761 beginGroupToken, ErrorKind.UnmatchedToken); | 762 ?.next; |
| 762 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | 763 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
| 763 return reportUnrecoverableError( | 764 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) |
| 764 beginGroupToken, ErrorKind.UnmatchedToken); | 765 ?.next; |
| 765 } | 766 } |
| 766 return beginGroupToken.endGroup; | 767 return beginGroupToken.endGroup; |
| 767 } | 768 } |
| 768 | 769 |
| 769 Token parseEnum(Token token) { | 770 Token parseEnum(Token token) { |
| 770 listener.beginEnum(token); | 771 listener.beginEnum(token); |
| 771 Token enumKeyword = token; | 772 Token enumKeyword = token; |
| 772 token = parseIdentifier(token.next, IdentifierContext.enumDeclaration); | 773 token = parseIdentifier(token.next, IdentifierContext.enumDeclaration); |
| 773 token = expect('{', token); | 774 token = expect('{', token); |
| 774 int count = 0; | 775 int count = 0; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 } while (optional(',', token)); | 864 } while (optional(',', token)); |
| 864 } | 865 } |
| 865 token = parseClassBody(token); | 866 token = parseClassBody(token); |
| 866 listener.endClassDeclaration(interfacesCount, begin, classKeyword, | 867 listener.endClassDeclaration(interfacesCount, begin, classKeyword, |
| 867 extendsKeyword, implementsKeyword, token); | 868 extendsKeyword, implementsKeyword, token); |
| 868 return token.next; | 869 return token.next; |
| 869 } | 870 } |
| 870 | 871 |
| 871 Token parseStringPart(Token token) { | 872 Token parseStringPart(Token token) { |
| 872 if (token.kind != STRING_TOKEN) { | 873 if (token.kind != STRING_TOKEN) { |
| 873 token = reportUnrecoverableError(token, ErrorKind.ExpectedString); | 874 token = reportUnrecoverableError(token, ErrorKind.ExpectedString)?.next; |
| 874 } | 875 } |
| 875 listener.handleStringPart(token); | 876 listener.handleStringPart(token); |
| 876 return token.next; | 877 return token.next; |
| 877 } | 878 } |
| 878 | 879 |
| 879 Token parseIdentifier(Token token, IdentifierContext context) { | 880 Token parseIdentifier(Token token, IdentifierContext context) { |
| 880 if (!token.isIdentifier()) { | 881 if (!token.isIdentifier()) { |
| 881 token = reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier); | 882 token = |
| 883 reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier)?.next; |
| 882 } | 884 } |
| 883 listener.handleIdentifier(token, context); | 885 listener.handleIdentifier(token, context); |
| 884 return token.next; | 886 return token.next; |
| 885 } | 887 } |
| 886 | 888 |
| 887 Token expect(String string, Token token) { | 889 Token expect(String string, Token token) { |
| 888 if (!identical(string, token.stringValue)) { | 890 if (!identical(string, token.stringValue)) { |
| 889 return reportUnrecoverableError( | 891 return reportUnrecoverableError( |
| 890 token, ErrorKind.ExpectedButGot, {"expected": string}); | 892 token, ErrorKind.ExpectedButGot, {"expected": string})?.next; |
| 891 } | 893 } |
| 892 return token.next; | 894 return token.next; |
| 893 } | 895 } |
| 894 | 896 |
| 895 Token parseTypeVariable(Token token) { | 897 Token parseTypeVariable(Token token) { |
| 896 listener.beginTypeVariable(token); | 898 listener.beginTypeVariable(token); |
| 897 token = parseIdentifier(token, IdentifierContext.typeVariableDeclaration); | 899 token = parseIdentifier(token, IdentifierContext.typeVariableDeclaration); |
| 898 Token extendsOrSuper = null; | 900 Token extendsOrSuper = null; |
| 899 if (optional('extends', token) || optional('super', token)) { | 901 if (optional('extends', token) || optional('super', token)) { |
| 900 extendsOrSuper = token; | 902 extendsOrSuper = token; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 } else if (identical(token.stringValue, 'void') && | 952 } else if (identical(token.stringValue, 'void') && |
| 951 isGeneralizedFunctionType(token.next)) { | 953 isGeneralizedFunctionType(token.next)) { |
| 952 listener.handleVoidKeyword(token); | 954 listener.handleVoidKeyword(token); |
| 953 token = token.next; | 955 token = token.next; |
| 954 } else { | 956 } else { |
| 955 if (isValidTypeReference(token)) { | 957 if (isValidTypeReference(token)) { |
| 956 token = parseIdentifier(token, IdentifierContext.typeReference); | 958 token = parseIdentifier(token, IdentifierContext.typeReference); |
| 957 token = parseQualifiedRestOpt( | 959 token = parseQualifiedRestOpt( |
| 958 token, IdentifierContext.typeReferenceContinuation); | 960 token, IdentifierContext.typeReferenceContinuation); |
| 959 } else { | 961 } else { |
| 960 token = reportUnrecoverableError(token, ErrorKind.ExpectedType); | 962 token = reportUnrecoverableError(token, ErrorKind.ExpectedType)?.next; |
| 961 listener.handleInvalidTypeReference(token); | 963 listener.handleInvalidTypeReference(token); |
| 962 } | 964 } |
| 963 token = parseTypeArgumentsOpt(token); | 965 token = parseTypeArgumentsOpt(token); |
| 964 listener.handleType(begin, token); | 966 listener.handleType(begin, token); |
| 965 } | 967 } |
| 966 | 968 |
| 967 // While we see a `Function(` treat the pushed type as return type. | 969 // While we see a `Function(` treat the pushed type as return type. |
| 968 // For example: `int Function() Function(int) Function(String x)`. | 970 // For example: `int Function() Function(int) Function(String x)`. |
| 969 while (isGeneralizedFunctionType(token)) { | 971 while (isGeneralizedFunctionType(token)) { |
| 970 token = parseFunctionType(token); | 972 token = parseFunctionType(token); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 handleNoStuff(token); | 1028 handleNoStuff(token); |
| 1027 return token; | 1029 return token; |
| 1028 } | 1030 } |
| 1029 | 1031 |
| 1030 Token parseTopLevelMember(Token token) { | 1032 Token parseTopLevelMember(Token token) { |
| 1031 Token start = token; | 1033 Token start = token; |
| 1032 listener.beginTopLevelMember(token); | 1034 listener.beginTopLevelMember(token); |
| 1033 | 1035 |
| 1034 Link<Token> identifiers = findMemberName(token); | 1036 Link<Token> identifiers = findMemberName(token); |
| 1035 if (identifiers.isEmpty) { | 1037 if (identifiers.isEmpty) { |
| 1036 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); | 1038 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) |
| 1039 ?.next; |
| 1037 } | 1040 } |
| 1038 Token afterName = identifiers.head; | 1041 Token afterName = identifiers.head; |
| 1039 identifiers = identifiers.tail; | 1042 identifiers = identifiers.tail; |
| 1040 | 1043 |
| 1041 if (identifiers.isEmpty) { | 1044 if (identifiers.isEmpty) { |
| 1042 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); | 1045 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) |
| 1046 ?.next; |
| 1043 } | 1047 } |
| 1044 Token name = identifiers.head; | 1048 Token name = identifiers.head; |
| 1045 identifiers = identifiers.tail; | 1049 identifiers = identifiers.tail; |
| 1046 Token getOrSet; | 1050 Token getOrSet; |
| 1047 if (!identifiers.isEmpty) { | 1051 if (!identifiers.isEmpty) { |
| 1048 String value = identifiers.head.stringValue; | 1052 String value = identifiers.head.stringValue; |
| 1049 if ((identical(value, 'get')) || (identical(value, 'set'))) { | 1053 if ((identical(value, 'get')) || (identical(value, 'set'))) { |
| 1050 getOrSet = identifiers.head; | 1054 getOrSet = identifiers.head; |
| 1051 identifiers = identifiers.tail; | 1055 identifiers = identifiers.tail; |
| 1052 } | 1056 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1077 if (getOrSet != null) { | 1081 if (getOrSet != null) { |
| 1078 // If we found a "get" keyword, this must be an abstract | 1082 // If we found a "get" keyword, this must be an abstract |
| 1079 // getter. | 1083 // getter. |
| 1080 isField = (!identical(getOrSet.stringValue, 'get')); | 1084 isField = (!identical(getOrSet.stringValue, 'get')); |
| 1081 // TODO(ahe): This feels like a hack. | 1085 // TODO(ahe): This feels like a hack. |
| 1082 } else { | 1086 } else { |
| 1083 isField = true; | 1087 isField = true; |
| 1084 } | 1088 } |
| 1085 break; | 1089 break; |
| 1086 } else { | 1090 } else { |
| 1087 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 1091 token = |
| 1092 reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; |
| 1088 if (identical(token.kind, EOF_TOKEN)) return token; | 1093 if (identical(token.kind, EOF_TOKEN)) return token; |
| 1089 } | 1094 } |
| 1090 } | 1095 } |
| 1091 var modifiers = identifiers.reverse(); | 1096 var modifiers = identifiers.reverse(); |
| 1092 return isField | 1097 return isField |
| 1093 ? parseFields(start, modifiers, type, getOrSet, name, true) | 1098 ? parseFields(start, modifiers, type, getOrSet, name, true) |
| 1094 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); | 1099 : parseTopLevelMethod(start, modifiers, type, getOrSet, name); |
| 1095 } | 1100 } |
| 1096 | 1101 |
| 1097 bool isVarFinalOrConst(Token token) { | 1102 bool isVarFinalOrConst(Token token) { |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 */ | 1619 */ |
| 1615 Token peekAfterIfType(Token token) { | 1620 Token peekAfterIfType(Token token) { |
| 1616 if (!optional('void', token) && !token.isIdentifier()) { | 1621 if (!optional('void', token) && !token.isIdentifier()) { |
| 1617 return null; | 1622 return null; |
| 1618 } | 1623 } |
| 1619 return peekAfterType(token); | 1624 return peekAfterType(token); |
| 1620 } | 1625 } |
| 1621 | 1626 |
| 1622 Token skipClassBody(Token token) { | 1627 Token skipClassBody(Token token) { |
| 1623 if (!optional('{', token)) { | 1628 if (!optional('{', token)) { |
| 1624 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip); | 1629 return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip) |
| 1630 ?.next; |
| 1625 } | 1631 } |
| 1626 BeginGroupToken beginGroupToken = token; | 1632 BeginGroupToken beginGroupToken = token; |
| 1627 Token endGroup = beginGroupToken.endGroup; | 1633 Token endGroup = beginGroupToken.endGroup; |
| 1628 if (endGroup == null) { | 1634 if (endGroup == null) { |
| 1629 return reportUnrecoverableError( | 1635 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) |
| 1630 beginGroupToken, ErrorKind.UnmatchedToken); | 1636 ?.next; |
| 1631 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { | 1637 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
| 1632 return reportUnrecoverableError( | 1638 return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken) |
| 1633 beginGroupToken, ErrorKind.UnmatchedToken); | 1639 ?.next; |
| 1634 } | 1640 } |
| 1635 return endGroup; | 1641 return endGroup; |
| 1636 } | 1642 } |
| 1637 | 1643 |
| 1638 Token parseClassBody(Token token) { | 1644 Token parseClassBody(Token token) { |
| 1639 Token begin = token; | 1645 Token begin = token; |
| 1640 listener.beginClassBody(token); | 1646 listener.beginClassBody(token); |
| 1641 if (!optional('{', token)) { | 1647 if (!optional('{', token)) { |
| 1642 token = reportUnrecoverableError(token, ErrorKind.ExpectedClassBody); | 1648 token = |
| 1649 reportUnrecoverableError(token, ErrorKind.ExpectedClassBody)?.next; |
| 1643 } | 1650 } |
| 1644 token = token.next; | 1651 token = token.next; |
| 1645 int count = 0; | 1652 int count = 0; |
| 1646 while (notEofOrValue('}', token)) { | 1653 while (notEofOrValue('}', token)) { |
| 1647 token = parseMember(token); | 1654 token = parseMember(token); |
| 1648 ++count; | 1655 ++count; |
| 1649 } | 1656 } |
| 1650 expect('}', token); | 1657 expect('}', token); |
| 1651 listener.endClassBody(count, begin, token); | 1658 listener.endClassBody(count, begin, token); |
| 1652 return token; | 1659 return token; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1669 listener.beginMember(token); | 1676 listener.beginMember(token); |
| 1670 if (isFactoryDeclaration(token)) { | 1677 if (isFactoryDeclaration(token)) { |
| 1671 token = parseFactoryMethod(token); | 1678 token = parseFactoryMethod(token); |
| 1672 listener.endMember(); | 1679 listener.endMember(); |
| 1673 assert(token != null); | 1680 assert(token != null); |
| 1674 return token; | 1681 return token; |
| 1675 } | 1682 } |
| 1676 | 1683 |
| 1677 Link<Token> identifiers = findMemberName(token); | 1684 Link<Token> identifiers = findMemberName(token); |
| 1678 if (identifiers.isEmpty) { | 1685 if (identifiers.isEmpty) { |
| 1679 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); | 1686 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) |
| 1687 ?.next; |
| 1680 } | 1688 } |
| 1681 Token afterName = identifiers.head; | 1689 Token afterName = identifiers.head; |
| 1682 identifiers = identifiers.tail; | 1690 identifiers = identifiers.tail; |
| 1683 | 1691 |
| 1684 if (identifiers.isEmpty) { | 1692 if (identifiers.isEmpty) { |
| 1685 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration); | 1693 return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration) |
| 1694 ?.next; |
| 1686 } | 1695 } |
| 1687 Token name = identifiers.head; | 1696 Token name = identifiers.head; |
| 1688 identifiers = identifiers.tail; | 1697 identifiers = identifiers.tail; |
| 1689 if (!identifiers.isEmpty) { | 1698 if (!identifiers.isEmpty) { |
| 1690 if (optional('operator', identifiers.head)) { | 1699 if (optional('operator', identifiers.head)) { |
| 1691 name = identifiers.head; | 1700 name = identifiers.head; |
| 1692 identifiers = identifiers.tail; | 1701 identifiers = identifiers.tail; |
| 1693 } | 1702 } |
| 1694 } | 1703 } |
| 1695 Token getOrSet; | 1704 Token getOrSet; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1727 isField = !optional("get", getOrSet); | 1736 isField = !optional("get", getOrSet); |
| 1728 // TODO(ahe): This feels like a hack. | 1737 // TODO(ahe): This feels like a hack. |
| 1729 } else { | 1738 } else { |
| 1730 isField = true; | 1739 isField = true; |
| 1731 } | 1740 } |
| 1732 break; | 1741 break; |
| 1733 } else if ((identical(value, '=')) || (identical(value, ','))) { | 1742 } else if ((identical(value, '=')) || (identical(value, ','))) { |
| 1734 isField = true; | 1743 isField = true; |
| 1735 break; | 1744 break; |
| 1736 } else { | 1745 } else { |
| 1737 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 1746 token = |
| 1747 reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; |
| 1738 if (identical(token.kind, EOF_TOKEN)) { | 1748 if (identical(token.kind, EOF_TOKEN)) { |
| 1739 // TODO(ahe): This is a hack, see parseTopLevelMember. | 1749 // TODO(ahe): This is a hack, see parseTopLevelMember. |
| 1740 listener.endFields(1, null, start, token); | 1750 listener.endFields(1, null, start, token); |
| 1741 listener.endMember(); | 1751 listener.endMember(); |
| 1742 return token; | 1752 return token; |
| 1743 } | 1753 } |
| 1744 } | 1754 } |
| 1745 } | 1755 } |
| 1746 | 1756 |
| 1747 var modifiers = identifiers.reverse(); | 1757 var modifiers = identifiers.reverse(); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2045 expectSemicolon(token); | 2055 expectSemicolon(token); |
| 2046 listener.endExpressionFunctionBody(begin, token); | 2056 listener.endExpressionFunctionBody(begin, token); |
| 2047 } else { | 2057 } else { |
| 2048 listener.endExpressionFunctionBody(begin, null); | 2058 listener.endExpressionFunctionBody(begin, null); |
| 2049 } | 2059 } |
| 2050 return token; | 2060 return token; |
| 2051 } | 2061 } |
| 2052 Token begin = token; | 2062 Token begin = token; |
| 2053 int statementCount = 0; | 2063 int statementCount = 0; |
| 2054 if (!optional('{', token)) { | 2064 if (!optional('{', token)) { |
| 2055 token = reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody); | 2065 token = |
| 2066 reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody)?.next; |
| 2056 listener.handleInvalidFunctionBody(token); | 2067 listener.handleInvalidFunctionBody(token); |
| 2057 return token; | 2068 return token; |
| 2058 } | 2069 } |
| 2059 | 2070 |
| 2060 listener.beginFunctionBody(begin); | 2071 listener.beginFunctionBody(begin); |
| 2061 token = token.next; | 2072 token = token.next; |
| 2062 while (notEofOrValue('}', token)) { | 2073 while (notEofOrValue('}', token)) { |
| 2063 token = parseStatement(token); | 2074 token = parseStatement(token); |
| 2064 ++statementCount; | 2075 ++statementCount; |
| 2065 } | 2076 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2114 listener.handleAsyncModifier(async, star); | 2125 listener.handleAsyncModifier(async, star); |
| 2115 return token; | 2126 return token; |
| 2116 } | 2127 } |
| 2117 | 2128 |
| 2118 int statementDepth = 0; | 2129 int statementDepth = 0; |
| 2119 Token parseStatement(Token token) { | 2130 Token parseStatement(Token token) { |
| 2120 if (statementDepth++ > 500) { | 2131 if (statementDepth++ > 500) { |
| 2121 // This happens for degenerate programs, for example, a lot of nested | 2132 // This happens for degenerate programs, for example, a lot of nested |
| 2122 // if-statements. The language test deep_nesting2_negative_test, for | 2133 // if-statements. The language test deep_nesting2_negative_test, for |
| 2123 // example, provokes this. | 2134 // example, provokes this. |
| 2124 return reportUnrecoverableError(token, ErrorKind.StackOverflow); | 2135 return reportUnrecoverableError(token, ErrorKind.StackOverflow)?.next; |
| 2125 } | 2136 } |
| 2126 Token result = parseStatementX(token); | 2137 Token result = parseStatementX(token); |
| 2127 statementDepth--; | 2138 statementDepth--; |
| 2128 return result; | 2139 return result; |
| 2129 } | 2140 } |
| 2130 | 2141 |
| 2131 Token parseStatementX(Token token) { | 2142 Token parseStatementX(Token token) { |
| 2132 final value = token.stringValue; | 2143 final value = token.stringValue; |
| 2133 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 2144 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
| 2134 return parseExpressionStatementOrDeclaration(token); | 2145 return parseExpressionStatementOrDeclaration(token); |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2419 continue; | 2430 continue; |
| 2420 } | 2431 } |
| 2421 } | 2432 } |
| 2422 if (!mayParseFunctionExpressions && identical(value, '{')) { | 2433 if (!mayParseFunctionExpressions && identical(value, '{')) { |
| 2423 break; | 2434 break; |
| 2424 } | 2435 } |
| 2425 if (token is BeginGroupToken) { | 2436 if (token is BeginGroupToken) { |
| 2426 BeginGroupToken begin = token; | 2437 BeginGroupToken begin = token; |
| 2427 token = (begin.endGroup != null) ? begin.endGroup : token; | 2438 token = (begin.endGroup != null) ? begin.endGroup : token; |
| 2428 } else if (token is ErrorToken) { | 2439 } else if (token is ErrorToken) { |
| 2429 reportErrorToken(token, false); | 2440 reportErrorToken(token, false)?.next; |
| 2430 } | 2441 } |
| 2431 token = token.next; | 2442 token = token.next; |
| 2432 } | 2443 } |
| 2433 return token; | 2444 return token; |
| 2434 } | 2445 } |
| 2435 | 2446 |
| 2436 Token parseRecoverExpression(Token token) => parseExpression(token); | 2447 Token parseRecoverExpression(Token token) => parseExpression(token); |
| 2437 | 2448 |
| 2438 int expressionDepth = 0; | 2449 int expressionDepth = 0; |
| 2439 Token parseExpression(Token token) { | 2450 Token parseExpression(Token token) { |
| 2440 if (expressionDepth++ > 500) { | 2451 if (expressionDepth++ > 500) { |
| 2441 // This happens in degenerate programs, for example, with a lot of nested | 2452 // This happens in degenerate programs, for example, with a lot of nested |
| 2442 // list literals. This is provoked by, for examaple, the language test | 2453 // list literals. This is provoked by, for examaple, the language test |
| 2443 // deep_nesting1_negative_test. | 2454 // deep_nesting1_negative_test. |
| 2444 return reportUnrecoverableError(token, ErrorKind.StackOverflow); | 2455 return reportUnrecoverableError(token, ErrorKind.StackOverflow)?.next; |
| 2445 } | 2456 } |
| 2446 listener.beginExpression(token); | 2457 listener.beginExpression(token); |
| 2447 Token result = optional('throw', token) | 2458 Token result = optional('throw', token) |
| 2448 ? parseThrowExpression(token, true) | 2459 ? parseThrowExpression(token, true) |
| 2449 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); | 2460 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); |
| 2450 expressionDepth--; | 2461 expressionDepth--; |
| 2451 return result; | 2462 return result; |
| 2452 } | 2463 } |
| 2453 | 2464 |
| 2454 Token parseExpressionWithoutCascade(Token token) { | 2465 Token parseExpressionWithoutCascade(Token token) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2501 token = parsePrimary(token.next); | 2512 token = parsePrimary(token.next); |
| 2502 listener.handleBinaryExpression(operator); | 2513 listener.handleBinaryExpression(operator); |
| 2503 } else if ((identical(info, OPEN_PAREN_INFO)) || | 2514 } else if ((identical(info, OPEN_PAREN_INFO)) || |
| 2504 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { | 2515 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { |
| 2505 token = parseArgumentOrIndexStar(token); | 2516 token = parseArgumentOrIndexStar(token); |
| 2506 } else if ((identical(info, PLUS_PLUS_INFO)) || | 2517 } else if ((identical(info, PLUS_PLUS_INFO)) || |
| 2507 (identical(info, MINUS_MINUS_INFO))) { | 2518 (identical(info, MINUS_MINUS_INFO))) { |
| 2508 listener.handleUnaryPostfixAssignmentExpression(token); | 2519 listener.handleUnaryPostfixAssignmentExpression(token); |
| 2509 token = token.next; | 2520 token = token.next; |
| 2510 } else { | 2521 } else { |
| 2511 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 2522 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken) |
| 2523 ?.next; |
| 2512 } | 2524 } |
| 2513 } else if (identical(info, IS_INFO)) { | 2525 } else if (identical(info, IS_INFO)) { |
| 2514 token = parseIsOperatorRest(token); | 2526 token = parseIsOperatorRest(token); |
| 2515 } else if (identical(info, AS_INFO)) { | 2527 } else if (identical(info, AS_INFO)) { |
| 2516 token = parseAsOperatorRest(token); | 2528 token = parseAsOperatorRest(token); |
| 2517 } else if (identical(info, QUESTION_INFO)) { | 2529 } else if (identical(info, QUESTION_INFO)) { |
| 2518 token = parseConditionalExpressionRest(token); | 2530 token = parseConditionalExpressionRest(token); |
| 2519 } else { | 2531 } else { |
| 2520 // Left associative, so we recurse at the next higher | 2532 // Left associative, so we recurse at the next higher |
| 2521 // precedence level. | 2533 // precedence level. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2541 listener.beginCascade(token); | 2553 listener.beginCascade(token); |
| 2542 assert(optional('..', token)); | 2554 assert(optional('..', token)); |
| 2543 Token cascadeOperator = token; | 2555 Token cascadeOperator = token; |
| 2544 token = token.next; | 2556 token = token.next; |
| 2545 if (optional('[', token)) { | 2557 if (optional('[', token)) { |
| 2546 token = parseArgumentOrIndexStar(token); | 2558 token = parseArgumentOrIndexStar(token); |
| 2547 } else if (token.isIdentifier()) { | 2559 } else if (token.isIdentifier()) { |
| 2548 token = parseSend(token, IdentifierContext.expressionContinuation); | 2560 token = parseSend(token, IdentifierContext.expressionContinuation); |
| 2549 listener.handleBinaryExpression(cascadeOperator); | 2561 listener.handleBinaryExpression(cascadeOperator); |
| 2550 } else { | 2562 } else { |
| 2551 return reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 2563 return reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; |
| 2552 } | 2564 } |
| 2553 Token mark; | 2565 Token mark; |
| 2554 do { | 2566 do { |
| 2555 mark = token; | 2567 mark = token; |
| 2556 if (optional('.', token)) { | 2568 if (optional('.', token)) { |
| 2557 Token period = token; | 2569 Token period = token; |
| 2558 token = parseSend(token.next, IdentifierContext.expressionContinuation); | 2570 token = parseSend(token.next, IdentifierContext.expressionContinuation); |
| 2559 listener.handleBinaryExpression(period); | 2571 listener.handleBinaryExpression(period); |
| 2560 } | 2572 } |
| 2561 token = parseArgumentOrIndexStar(token); | 2573 token = parseArgumentOrIndexStar(token); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2669 listener.handleNoTypeArguments(token); | 2681 listener.handleNoTypeArguments(token); |
| 2670 return parseLiteralMapSuffix(token, null); | 2682 return parseLiteralMapSuffix(token, null); |
| 2671 } else if (kind == LT_TOKEN) { | 2683 } else if (kind == LT_TOKEN) { |
| 2672 return parseLiteralListOrMapOrFunction(token, null); | 2684 return parseLiteralListOrMapOrFunction(token, null); |
| 2673 } else { | 2685 } else { |
| 2674 return expressionExpected(token); | 2686 return expressionExpected(token); |
| 2675 } | 2687 } |
| 2676 } | 2688 } |
| 2677 | 2689 |
| 2678 Token expressionExpected(Token token) { | 2690 Token expressionExpected(Token token) { |
| 2679 token = reportUnrecoverableError(token, ErrorKind.ExpectedExpression); | 2691 token = reportUnrecoverableError(token, ErrorKind.ExpectedExpression)?.next; |
| 2680 listener.handleInvalidExpression(token); | 2692 listener.handleInvalidExpression(token); |
| 2681 return token; | 2693 return token; |
| 2682 } | 2694 } |
| 2683 | 2695 |
| 2684 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 2696 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
| 2685 BeginGroupToken beginGroup = token; | 2697 BeginGroupToken beginGroup = token; |
| 2686 // TODO(eernst): Check for NPE as described in issue 26252. | 2698 // TODO(eernst): Check for NPE as described in issue 26252. |
| 2687 Token nextToken = beginGroup.endGroup.next; | 2699 Token nextToken = beginGroup.endGroup.next; |
| 2688 int kind = nextToken.kind; | 2700 int kind = nextToken.kind; |
| 2689 if (mayParseFunctionExpressions && | 2701 if (mayParseFunctionExpressions && |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2703 } | 2715 } |
| 2704 | 2716 |
| 2705 Token parseParenthesizedExpression(Token token) { | 2717 Token parseParenthesizedExpression(Token token) { |
| 2706 // We expect [begin] to be of type [BeginGroupToken], but we don't know for | 2718 // We expect [begin] to be of type [BeginGroupToken], but we don't know for |
| 2707 // sure until after calling expect. | 2719 // sure until after calling expect. |
| 2708 dynamic begin = token; | 2720 dynamic begin = token; |
| 2709 token = expect('(', token); | 2721 token = expect('(', token); |
| 2710 // [begin] is now known to have type [BeginGroupToken]. | 2722 // [begin] is now known to have type [BeginGroupToken]. |
| 2711 token = parseExpression(token); | 2723 token = parseExpression(token); |
| 2712 if (!identical(begin.endGroup, token)) { | 2724 if (!identical(begin.endGroup, token)) { |
| 2713 reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 2725 reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; |
| 2714 token = begin.endGroup; | 2726 token = begin.endGroup; |
| 2715 } | 2727 } |
| 2716 listener.handleParenthesizedExpression(begin); | 2728 listener.handleParenthesizedExpression(begin); |
| 2717 return expect(')', token); | 2729 return expect(')', token); |
| 2718 } | 2730 } |
| 2719 | 2731 |
| 2720 Token parseThisExpression(Token token) { | 2732 Token parseThisExpression(Token token) { |
| 2721 Token beginToken = token; | 2733 Token beginToken = token; |
| 2722 listener.handleThisExpression(token); | 2734 listener.handleThisExpression(token); |
| 2723 token = token.next; | 2735 token = token.next; |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2892 } | 2904 } |
| 2893 } | 2905 } |
| 2894 return false; | 2906 return false; |
| 2895 } | 2907 } |
| 2896 | 2908 |
| 2897 Token parseRequiredArguments(Token token) { | 2909 Token parseRequiredArguments(Token token) { |
| 2898 if (optional('(', token)) { | 2910 if (optional('(', token)) { |
| 2899 token = parseArguments(token); | 2911 token = parseArguments(token); |
| 2900 } else { | 2912 } else { |
| 2901 listener.handleNoArguments(token); | 2913 listener.handleNoArguments(token); |
| 2902 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); | 2914 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next; |
| 2903 } | 2915 } |
| 2904 return token; | 2916 return token; |
| 2905 } | 2917 } |
| 2906 | 2918 |
| 2907 Token parseNewExpression(Token token) { | 2919 Token parseNewExpression(Token token) { |
| 2908 Token newKeyword = token; | 2920 Token newKeyword = token; |
| 2909 token = expect('new', token); | 2921 token = expect('new', token); |
| 2910 token = parseConstructorReference(token); | 2922 token = parseConstructorReference(token); |
| 2911 token = parseRequiredArguments(token); | 2923 token = parseRequiredArguments(token); |
| 2912 listener.handleNewExpression(newKeyword); | 2924 listener.handleNewExpression(newKeyword); |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3523 | 3535 |
| 3524 /// Don't call this method. Should only be used as a last resort when there | 3536 /// Don't call this method. Should only be used as a last resort when there |
| 3525 /// is no feasible way to recover from a parser error. | 3537 /// is no feasible way to recover from a parser error. |
| 3526 Token reportUnrecoverableError(Token token, ErrorKind kind, [Map arguments]) { | 3538 Token reportUnrecoverableError(Token token, ErrorKind kind, [Map arguments]) { |
| 3527 Token next; | 3539 Token next; |
| 3528 if (token is ErrorToken) { | 3540 if (token is ErrorToken) { |
| 3529 next = reportErrorToken(token, false); | 3541 next = reportErrorToken(token, false); |
| 3530 } else { | 3542 } else { |
| 3531 arguments ??= {}; | 3543 arguments ??= {}; |
| 3532 arguments.putIfAbsent("actual", () => token.value); | 3544 arguments.putIfAbsent("actual", () => token.value); |
| 3533 next = listener.handleUnrecoverableError(token, kind, arguments)?.next; | 3545 next = listener.handleUnrecoverableError(token, kind, arguments); |
| 3534 } | 3546 } |
| 3535 return next ?? skipToEof(token); | 3547 return next ?? skipToEof(token); |
| 3536 } | 3548 } |
| 3537 | 3549 |
| 3538 void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) { | 3550 void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) { |
| 3539 if (token is ErrorToken) { | 3551 if (token is ErrorToken) { |
| 3540 reportErrorToken(token, true); | 3552 reportErrorToken(token, true); |
| 3541 } else { | 3553 } else { |
| 3542 arguments ??= {}; | 3554 arguments ??= {}; |
| 3543 listener.handleRecoverableError(token, kind, arguments); | 3555 listener.handleRecoverableError(token, kind, arguments); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3574 arguments = {"text": token.assertionMessage}; | 3586 arguments = {"text": token.assertionMessage}; |
| 3575 break; | 3587 break; |
| 3576 | 3588 |
| 3577 default: | 3589 default: |
| 3578 break; | 3590 break; |
| 3579 } | 3591 } |
| 3580 if (isRecoverable) { | 3592 if (isRecoverable) { |
| 3581 listener.handleRecoverableError(token, kind, arguments); | 3593 listener.handleRecoverableError(token, kind, arguments); |
| 3582 return null; | 3594 return null; |
| 3583 } else { | 3595 } else { |
| 3584 return listener.handleUnrecoverableError(token, kind, arguments)?.next; | 3596 return listener.handleUnrecoverableError(token, kind, arguments); |
| 3585 } | 3597 } |
| 3586 } | 3598 } |
| 3587 } | 3599 } |
| OLD | NEW |