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

Side by Side Diff: pkg/dart_parser/lib/src/parser.dart

Issue 2664593002: Port parser and scanner fixes from rasta branch. (Closed)
Patch Set: Update status files. Created 3 years, 10 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 dart_parser.parser; 5 library dart_parser.parser;
6 6
7 import 'package:dart_scanner/dart_scanner.dart' show
8 ErrorToken;
9
10 import 'package:dart_scanner/src/recover.dart' show
11 closeBraceFor,
12 skipToEof;
13
7 import 'package:dart_scanner/src/keyword.dart' show 14 import 'package:dart_scanner/src/keyword.dart' show
8 Keyword; 15 Keyword;
9 16
10 import 'package:dart_scanner/src/precedence.dart' show 17 import 'package:dart_scanner/src/precedence.dart' show
11 ASSIGNMENT_PRECEDENCE, 18 ASSIGNMENT_PRECEDENCE,
12 AS_INFO, 19 AS_INFO,
13 CASCADE_PRECEDENCE, 20 CASCADE_PRECEDENCE,
14 EOF_INFO,
15 EQUALITY_PRECEDENCE, 21 EQUALITY_PRECEDENCE,
16 GT_INFO, 22 GT_INFO,
17 IS_INFO, 23 IS_INFO,
18 MINUS_MINUS_INFO, 24 MINUS_MINUS_INFO,
19 OPEN_PAREN_INFO, 25 OPEN_PAREN_INFO,
20 OPEN_SQUARE_BRACKET_INFO, 26 OPEN_SQUARE_BRACKET_INFO,
21 PERIOD_INFO, 27 PERIOD_INFO,
22 PLUS_PLUS_INFO, 28 PLUS_PLUS_INFO,
23 POSTFIX_PRECEDENCE, 29 POSTFIX_PRECEDENCE,
24 PrecedenceInfo, 30 PrecedenceInfo,
25 QUESTION_INFO, 31 QUESTION_INFO,
26 QUESTION_PERIOD_INFO, 32 QUESTION_PERIOD_INFO,
27 RELATIONAL_PRECEDENCE; 33 RELATIONAL_PRECEDENCE;
28 34
29 import 'package:dart_scanner/src/token.dart' show 35 import 'package:dart_scanner/src/token.dart' show
30 BadInputToken,
31 BeginGroupToken, 36 BeginGroupToken,
32 ErrorToken,
33 KeywordToken, 37 KeywordToken,
34 SymbolToken, 38 SymbolToken,
35 Token, 39 Token,
36 UnmatchedToken,
37 UnterminatedToken,
38 isUserDefinableOperator; 40 isUserDefinableOperator;
39 41
40 import 'package:dart_scanner/src/token_constants.dart' show 42 import 'package:dart_scanner/src/token_constants.dart' show
41 BAD_INPUT_TOKEN,
42 COMMA_TOKEN, 43 COMMA_TOKEN,
43 DOUBLE_TOKEN, 44 DOUBLE_TOKEN,
44 EOF_TOKEN, 45 EOF_TOKEN,
45 EQ_TOKEN, 46 EQ_TOKEN,
46 FUNCTION_TOKEN, 47 FUNCTION_TOKEN,
47 GT_TOKEN, 48 GT_TOKEN,
48 GT_GT_TOKEN, 49 GT_GT_TOKEN,
49 HASH_TOKEN, 50 HASH_TOKEN,
50 HEXADECIMAL_TOKEN, 51 HEXADECIMAL_TOKEN,
51 IDENTIFIER_TOKEN, 52 IDENTIFIER_TOKEN,
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 ++interfacesCount; 772 ++interfacesCount;
772 } while (optional(',', token)); 773 } while (optional(',', token));
773 } 774 }
774 token = parseClassBody(token); 775 token = parseClassBody(token);
775 listener.endClassDeclaration( 776 listener.endClassDeclaration(
776 interfacesCount, begin, extendsKeyword, implementsKeyword, token); 777 interfacesCount, begin, extendsKeyword, implementsKeyword, token);
777 return token.next; 778 return token.next;
778 } 779 }
779 780
780 Token parseStringPart(Token token) { 781 Token parseStringPart(Token token) {
781 if (identical(token.kind, STRING_TOKEN)) { 782 if (token.kind != STRING_TOKEN) {
782 listener.handleStringPart(token); 783 token = reportUnrecoverableError(token, ErrorKind.ExpectedString);
783 return token.next;
784 } else {
785 return reportUnrecoverableError(token, ErrorKind.ExpectedString);
786 } 784 }
785 listener.handleStringPart(token);
786 return token.next;
787 } 787 }
788 788
789 Token parseIdentifier(Token token) { 789 Token parseIdentifier(Token token) {
790 if (!token.isIdentifier()) { 790 if (!token.isIdentifier()) {
791 token = reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier); 791 token = reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier);
792 } 792 }
793 listener.handleIdentifier(token); 793 listener.handleIdentifier(token);
794 return token.next; 794 return token.next;
795 } 795 }
796 796
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 } else { 1140 } else {
1141 listener.handleNoTypeVariables(token); 1141 listener.handleNoTypeVariables(token);
1142 } 1142 }
1143 token = parseFormalParametersOpt(token); 1143 token = parseFormalParametersOpt(token);
1144 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1144 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1145 token = parseAsyncModifier(token); 1145 token = parseAsyncModifier(token);
1146 token = parseFunctionBody(token, false, externalModifier != null); 1146 token = parseFunctionBody(token, false, externalModifier != null);
1147 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; 1147 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled;
1148 Token endToken = token; 1148 Token endToken = token;
1149 token = token.next; 1149 token = token.next;
1150 if (token.kind == BAD_INPUT_TOKEN) {
1151 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
1152 }
1153 listener.endTopLevelMethod(start, getOrSet, endToken); 1150 listener.endTopLevelMethod(start, getOrSet, endToken);
1154 return token; 1151 return token;
1155 } 1152 }
1156 1153
1157 /// Looks ahead to find the name of a member. Returns a link of the modifiers, 1154 /// Looks ahead to find the name of a member. Returns a link of the modifiers,
1158 /// set/get, (operator) name, and either the start of the method body or the 1155 /// set/get, (operator) name, and either the start of the method body or the
1159 /// end of the declaration. 1156 /// end of the declaration.
1160 /// 1157 ///
1161 /// Examples: 1158 /// Examples:
1162 /// 1159 ///
(...skipping 18 matching lines...) Expand all
1181 /// 1178 ///
1182 Link<Token> findMemberName(Token token) { 1179 Link<Token> findMemberName(Token token) {
1183 Link<Token> identifiers = const Link<Token>(); 1180 Link<Token> identifiers = const Link<Token>();
1184 1181
1185 // `true` if 'get' has been seen. 1182 // `true` if 'get' has been seen.
1186 bool isGetter = false; 1183 bool isGetter = false;
1187 // `true` if an identifier has been seen after 'get'. 1184 // `true` if an identifier has been seen after 'get'.
1188 bool hasName = false; 1185 bool hasName = false;
1189 1186
1190 while (token.kind != EOF_TOKEN) { 1187 while (token.kind != EOF_TOKEN) {
1191 String value = token.stringValue; 1188 if (optional('get', token)) {
1192 if (value == 'get') {
1193 isGetter = true; 1189 isGetter = true;
1194 } else if (hasName && (value == 'sync' || value == 'async')) { 1190 } else if (hasName &&
1191 (optional("sync", token) || optional("async", token))) {
1195 // Skip. 1192 // Skip.
1196 token = token.next; 1193 token = token.next;
1197 value = token.stringValue; 1194 if (optional("*", token)) {
1198 if (value == '*') {
1199 // Skip. 1195 // Skip.
1200 token = token.next; 1196 token = token.next;
1201 } 1197 }
1202 continue; 1198 continue;
1203 } else if (value == '(' || value == '{' || value == '=>') { 1199 } else if (optional("(", token) || optional("{", token) ||
1200 optional("=>", token)) {
1204 // A method. 1201 // A method.
1205 identifiers = identifiers.prepend(token); 1202 identifiers = identifiers.prepend(token);
1206 return identifiers; 1203 return identifiers;
1207 } else if (value == '=' || value == ';' || value == ',') { 1204 } else if (optional("=", token) || optional(";", token) ||
1205 optional(",", token)) {
1208 // A field or abstract getter. 1206 // A field or abstract getter.
1209 identifiers = identifiers.prepend(token); 1207 identifiers = identifiers.prepend(token);
1210 return identifiers; 1208 return identifiers;
1211 } else if (isGetter) { 1209 } else if (isGetter) {
1212 hasName = true; 1210 hasName = true;
1213 } 1211 }
1214 identifiers = identifiers.prepend(token); 1212 identifiers = identifiers.prepend(token);
1215 if (isValidTypeReference(token)) { 1213 if (isValidTypeReference(token)) {
1216 // type ... 1214 // type ...
1217 if (optional('.', token.next)) { 1215 if (optional('.', token.next)) {
1218 // type '.' ... 1216 // type '.' ...
1219 if (token.next.next.isIdentifier()) { 1217 if (token.next.next.isIdentifier()) {
1220 // type '.' identifier 1218 // type '.' identifier
1221 token = token.next.next; 1219 token = token.next.next;
1222 } 1220 }
1223 } 1221 }
1224 if (optional('<', token.next)) { 1222 if (optional('<', token.next)) {
1225 if (token.next is BeginGroupToken) { 1223 if (token.next is BeginGroupToken) {
1226 BeginGroupToken beginGroup = token.next; 1224 BeginGroupToken beginGroup = token.next;
1227 if (beginGroup.endGroup == null) { 1225 if (beginGroup.endGroup == null) {
1228 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken); 1226 reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
Johnni Winther 2017/01/30 09:04:38 Why not use the token returned from [reportUnrecov
ahe 2017/01/30 13:26:22 Because I'm not trying to change or improve error
1227 } else {
1228 token = beginGroup.endGroup;
1229 } 1229 }
1230 token = beginGroup.endGroup;
1231 } 1230 }
1232 } 1231 }
1233 } 1232 }
1234 token = token.next; 1233 token = token.next;
1235 } 1234 }
1236 return const Link<Token>(); 1235 return const Link<Token>();
1237 } 1236 }
1238 1237
1239 Token parseFieldInitializerOpt(Token token) { 1238 Token parseFieldInitializerOpt(Token token) {
1240 if (optional('=', token)) { 1239 if (optional('=', token)) {
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 listener.endFunctionName(token); 1666 listener.endFunctionName(token);
1668 if (getOrSet == null) { 1667 if (getOrSet == null) {
1669 token = parseTypeVariablesOpt(token); 1668 token = parseTypeVariablesOpt(token);
1670 } else { 1669 } else {
1671 listener.handleNoTypeVariables(token); 1670 listener.handleNoTypeVariables(token);
1672 } 1671 }
1673 token = parseFormalParametersOpt(token); 1672 token = parseFormalParametersOpt(token);
1674 token = parseInitializersOpt(token); 1673 token = parseInitializersOpt(token);
1675 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1674 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1676 token = parseAsyncModifier(token); 1675 token = parseAsyncModifier(token);
1677 if (optional('=', token)) { 1676 token = parseFunctionBody(token, false, true);
1678 token = parseRedirectingFactoryBody(token);
1679 } else {
1680 token = parseFunctionBody(token, false, true);
1681 }
1682 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; 1677 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled;
1683 listener.endFunction(getOrSet, token); 1678 listener.endFunction(getOrSet, token);
1684 return token.next; 1679 return token.next;
1685 } 1680 }
1686 1681
1687 Token parseUnnamedFunction(Token token) { 1682 Token parseUnnamedFunction(Token token) {
1688 listener.beginUnnamedFunction(token); 1683 listener.beginUnnamedFunction(token);
1689 token = parseFormalParameters(token); 1684 token = parseFormalParameters(token);
1690 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; 1685 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
1691 token = parseAsyncModifier(token); 1686 token = parseAsyncModifier(token);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1754 String value = token.stringValue; 1749 String value = token.stringValue;
1755 if (identical(value, ';')) { 1750 if (identical(value, ';')) {
1756 if (!allowAbstract) { 1751 if (!allowAbstract) {
1757 reportRecoverableError(token, ErrorKind.ExpectedBody); 1752 reportRecoverableError(token, ErrorKind.ExpectedBody);
1758 } 1753 }
1759 listener.handleNoFunctionBody(token); 1754 listener.handleNoFunctionBody(token);
1760 } else { 1755 } else {
1761 if (identical(value, '=>')) { 1756 if (identical(value, '=>')) {
1762 token = parseExpression(token.next); 1757 token = parseExpression(token.next);
1763 expectSemicolon(token); 1758 expectSemicolon(token);
1764 } else if (value == '=') { 1759 } else if (identical(value, '=')) {
1765 token = parseRedirectingFactoryBody(token); 1760 reportRecoverableError(token, ErrorKind.ExpectedBody);
1761 token = parseExpression(token.next);
1766 expectSemicolon(token); 1762 expectSemicolon(token);
1767 } else { 1763 } else {
1768 token = skipBlock(token); 1764 token = skipBlock(token);
1769 } 1765 }
1770 listener.handleFunctionBodySkipped(token); 1766 listener.handleFunctionBodySkipped(token);
1771 } 1767 }
1772 return token; 1768 return token;
1773 } 1769 }
1774 1770
1775 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { 1771 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
1776 if (optional(';', token)) { 1772 if (optional(';', token)) {
1777 if (!allowAbstract) { 1773 if (!allowAbstract) {
1778 reportRecoverableError(token, ErrorKind.ExpectedBody); 1774 reportRecoverableError(token, ErrorKind.ExpectedBody);
1779 } 1775 }
1780 listener.endFunctionBody(0, null, token); 1776 listener.endFunctionBody(0, null, token);
1781 return token; 1777 return token;
1782 } else if (optional('=>', token)) { 1778 } else if (optional('=>', token)) {
1783 Token begin = token; 1779 Token begin = token;
1784 token = parseExpression(token.next); 1780 token = parseExpression(token.next);
1785 if (!isExpression) { 1781 if (!isExpression) {
1786 expectSemicolon(token); 1782 expectSemicolon(token);
1787 listener.endReturnStatement(true, begin, token); 1783 listener.endReturnStatement(true, begin, token);
1788 } else { 1784 } else {
1789 listener.endReturnStatement(true, begin, null); 1785 listener.endReturnStatement(true, begin, null);
1790 } 1786 }
1791 return token; 1787 return token;
1788 } else if (optional('=', token)) {
1789 Token begin = token;
1790 // Recover from a bad factory method.
1791 reportRecoverableError(token, ErrorKind.ExpectedBody);
1792 token = parseExpression(token.next);
1793 if (!isExpression) {
1794 expectSemicolon(token);
1795 listener.endReturnStatement(true, begin, token);
1796 } else {
1797 listener.endReturnStatement(true, begin, null);
1798 }
1799 return token;
1792 } 1800 }
1793 Token begin = token; 1801 Token begin = token;
1794 int statementCount = 0; 1802 int statementCount = 0;
1795 if (!optional('{', token)) { 1803 if (!optional('{', token)) {
1796 token = reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody); 1804 token = reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody);
1797 listener.handleInvalidFunctionBody(token); 1805 listener.handleInvalidFunctionBody(token);
1798 return token; 1806 return token;
1799 } 1807 }
1800 1808
1801 listener.beginFunctionBody(begin); 1809 listener.beginFunctionBody(begin);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1849 star = token; 1857 star = token;
1850 token = token.next; 1858 token = token.next;
1851 } else { 1859 } else {
1852 reportRecoverableError(async, ErrorKind.InvalidSyncModifier); 1860 reportRecoverableError(async, ErrorKind.InvalidSyncModifier);
1853 } 1861 }
1854 } 1862 }
1855 listener.handleAsyncModifier(async, star); 1863 listener.handleAsyncModifier(async, star);
1856 return token; 1864 return token;
1857 } 1865 }
1858 1866
1867 int statementDepth = 0;
1859 Token parseStatement(Token token) { 1868 Token parseStatement(Token token) {
1869 if (statementDepth++ > 500) {
Johnni Winther 2017/01/30 09:04:38 When does this occur?
ahe 2017/01/30 13:26:22 Deeply nested if statements. See tests/language/de
1870 reportRecoverableError(
1871 token, ErrorKind.Unspecified, {'text': 'Stack overflow'});
1872 return skipToEof(token);
1873 }
1874 Token result = parseStatementX(token);
1875 statementDepth--;
1876 return result;
1877 }
1878
1879 Token parseStatementX(Token token) {
1860 final value = token.stringValue; 1880 final value = token.stringValue;
1861 if (identical(token.kind, IDENTIFIER_TOKEN)) { 1881 if (identical(token.kind, IDENTIFIER_TOKEN)) {
1862 return parseExpressionStatementOrDeclaration(token); 1882 return parseExpressionStatementOrDeclaration(token);
1863 } else if (identical(value, '{')) { 1883 } else if (identical(value, '{')) {
1864 return parseBlock(token); 1884 return parseBlock(token);
1865 } else if (identical(value, 'return')) { 1885 } else if (identical(value, 'return')) {
1866 return parseReturnStatement(token); 1886 return parseReturnStatement(token);
1867 } else if (identical(value, 'var') || identical(value, 'final')) { 1887 } else if (identical(value, 'var') || identical(value, 'final')) {
1868 return parseVariablesDeclaration(token); 1888 return parseVariablesDeclaration(token);
1869 } else if (identical(value, 'if')) { 1889 } else if (identical(value, 'if')) {
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
2154 BeginGroupToken begin = token; 2174 BeginGroupToken begin = token;
2155 token = (begin.endGroup != null) ? begin.endGroup : token; 2175 token = (begin.endGroup != null) ? begin.endGroup : token;
2156 } else if (token is ErrorToken) { 2176 } else if (token is ErrorToken) {
2157 reportErrorToken(token, false); 2177 reportErrorToken(token, false);
2158 } 2178 }
2159 token = token.next; 2179 token = token.next;
2160 } 2180 }
2161 return token; 2181 return token;
2162 } 2182 }
2163 2183
2184 int expressionDepth = 0;
2164 Token parseExpression(Token token) { 2185 Token parseExpression(Token token) {
2186 if (expressionDepth++ > 500) {
2187 reportRecoverableError(
Johnni Winther 2017/01/30 09:04:38 When does this occur?
ahe 2017/01/30 13:26:22 Deeply nested array literals, for example, see: te
2188 token, ErrorKind.Unspecified, {'text': 'Stack overflow'});
2189 return token.next;
2190 }
2165 listener.beginExpression(token); 2191 listener.beginExpression(token);
2166 return optional('throw', token) 2192 Token result = optional('throw', token)
2167 ? parseThrowExpression(token, true) 2193 ? parseThrowExpression(token, true)
2168 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true); 2194 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true);
2195 expressionDepth--;
2196 return result;
2169 } 2197 }
2170 2198
2171 Token parseExpressionWithoutCascade(Token token) { 2199 Token parseExpressionWithoutCascade(Token token) {
2172 listener.beginExpression(token); 2200 listener.beginExpression(token);
2173 return optional('throw', token) 2201 return optional('throw', token)
2174 ? parseThrowExpression(token, false) 2202 ? parseThrowExpression(token, false)
2175 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, false); 2203 : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, false);
2176 } 2204 }
2177 2205
2178 Token parseConditionalExpressionRest(Token token) { 2206 Token parseConditionalExpressionRest(Token token) {
(...skipping 24 matching lines...) Expand all
2203 token = parseCascadeExpression(token); 2231 token = parseCascadeExpression(token);
2204 } else if (identical(tokenLevel, ASSIGNMENT_PRECEDENCE)) { 2232 } else if (identical(tokenLevel, ASSIGNMENT_PRECEDENCE)) {
2205 // Right associative, so we recurse at the same precedence 2233 // Right associative, so we recurse at the same precedence
2206 // level. 2234 // level.
2207 listener.beginExpression(token.next); 2235 listener.beginExpression(token.next);
2208 token = parsePrecedenceExpression(token.next, level, allowCascades); 2236 token = parsePrecedenceExpression(token.next, level, allowCascades);
2209 listener.handleAssignmentExpression(operator); 2237 listener.handleAssignmentExpression(operator);
2210 } else if (identical(tokenLevel, POSTFIX_PRECEDENCE)) { 2238 } else if (identical(tokenLevel, POSTFIX_PRECEDENCE)) {
2211 if (identical(info, PERIOD_INFO) || 2239 if (identical(info, PERIOD_INFO) ||
2212 identical(info, QUESTION_PERIOD_INFO)) { 2240 identical(info, QUESTION_PERIOD_INFO)) {
2213 // Left associative, so we recurse at the next higher 2241 // Left associative, so we recurse at the next higher precedence
2214 // precedence level. However, POSTFIX_PRECEDENCE is the 2242 // level. However, POSTFIX_PRECEDENCE is the highest level, so we
2215 // highest level, so we just call parseUnaryExpression 2243 // should just call [parseUnaryExpression] directly. However, a
2216 // directly. 2244 // unary expression isn't legal after a period, so we call
2217 token = parseUnaryExpression(token.next, allowCascades); 2245 // [parsePrimary] instead.
2246 token = parsePrimary(token.next);
2218 listener.handleBinaryExpression(operator); 2247 listener.handleBinaryExpression(operator);
2219 } else if ((identical(info, OPEN_PAREN_INFO)) || 2248 } else if ((identical(info, OPEN_PAREN_INFO)) ||
2220 (identical(info, OPEN_SQUARE_BRACKET_INFO))) { 2249 (identical(info, OPEN_SQUARE_BRACKET_INFO))) {
2221 token = parseArgumentOrIndexStar(token); 2250 token = parseArgumentOrIndexStar(token);
2222 } else if ((identical(info, PLUS_PLUS_INFO)) || 2251 } else if ((identical(info, PLUS_PLUS_INFO)) ||
2223 (identical(info, MINUS_MINUS_INFO))) { 2252 (identical(info, MINUS_MINUS_INFO))) {
2224 listener.handleUnaryPostfixAssignmentExpression(token); 2253 listener.handleUnaryPostfixAssignmentExpression(token);
2225 token = token.next; 2254 token = token.next;
2226 } else { 2255 } else {
2227 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken); 2256 token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after
3241 void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) { 3270 void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) {
3242 if (token is ErrorToken) { 3271 if (token is ErrorToken) {
3243 reportErrorToken(token, true); 3272 reportErrorToken(token, true);
3244 } else { 3273 } else {
3245 arguments ??= {}; 3274 arguments ??= {};
3246 listener.handleRecoverableError(token, kind, arguments); 3275 listener.handleRecoverableError(token, kind, arguments);
3247 } 3276 }
3248 } 3277 }
3249 3278
3250 Token reportErrorToken(ErrorToken token, bool isRecoverable) { 3279 Token reportErrorToken(ErrorToken token, bool isRecoverable) {
3251 ErrorKind kind; 3280 ErrorKind kind = token.errorCode;
3252 Map arguments = const {}; 3281 Map arguments = const {};
3253 if (token is BadInputToken) { 3282 switch (kind) {
3254 String hex = token.character.toRadixString(16); 3283 case ErrorKind.NonAsciiIdentifier:
3255 if (hex.length < 4) { 3284 String hex = token.character.toRadixString(16);
3256 String padding = "0000".substring(hex.length); 3285 if (hex.length < 4) {
3257 hex = "$padding$hex"; 3286 String padding = "0000".substring(hex.length);
3258 } 3287 hex = "$padding$hex";
3259 kind = ErrorKind.InvalidInputCharacter; 3288 }
3260 arguments = {'characterHex': hex}; 3289 arguments = {'characterHex': hex};
3261 } else if (token is UnterminatedToken) { 3290 break;
3262 switch (token.start) { 3291
3263 case '1e': 3292 case ErrorKind.UnterminatedString:
3264 kind = ErrorKind.MissingExponent; 3293 arguments = {'quote': token.start};
3265 break; 3294 break;
3266 case '"': 3295
3267 case "'": 3296 case ErrorKind.UnmatchedToken:
3268 case '"""': 3297 String begin = token.begin.value;
3269 case "'''": 3298 String end = closeBraceFor(begin);
3270 case 'r"': 3299 arguments = {'begin': begin, 'end': end};
3271 case "r'": 3300 break;
3272 case 'r"""': 3301
3273 case "r'''": 3302 case ErrorKind.Unspecified:
3274 kind = ErrorKind.UnterminatedString; 3303 arguments = {"text": token.assertionMessage};
3275 arguments = {'quote': token.start}; 3304 break;
3276 break; 3305
3277 case '0x': 3306 default:
3278 kind = ErrorKind.ExpectedHexDigit; 3307 break;
3279 break;
3280 case r'$':
3281 kind = ErrorKind.MalformedStringLiteral;
3282 break;
3283 case '/*':
3284 kind = ErrorKind.UnterminatedComment;
3285 break;
3286 default:
3287 kind = ErrorKind.UnterminatedToken;
3288 break;
3289 }
3290 } else if (token is UnmatchedToken) {
3291 String begin = token.begin.value;
3292 String end = closeBraceFor(begin);
3293 kind = ErrorKind.UnmatchedToken;
3294 arguments = {'begin': begin, 'end': end};
3295 } else {
3296 return listener.handleUnrecoverableError(
3297 token, ErrorKind.Unspecified, {"text": token.assertionMessage});
3298 } 3308 }
3299 if (isRecoverable) { 3309 if (isRecoverable) {
3300 listener.handleRecoverableError(token, kind, arguments); 3310 listener.handleRecoverableError(token, kind, arguments);
3301 return null; 3311 return null;
3302 } else { 3312 } else {
3303 return listener.handleUnrecoverableError(token, kind, arguments); 3313 return listener.handleUnrecoverableError(token, kind, arguments);
3304 } 3314 }
3305 } 3315 }
3306 } 3316 }
3307
3308 String closeBraceFor(String openBrace) {
3309 return const {
3310 '(': ')',
3311 '[': ']',
3312 '{': '}',
3313 '<': '>',
3314 r'${': '}',
3315 }[openBrace];
3316 }
3317
3318 Token skipToEof(Token token) {
3319 while (!identical(token.info, EOF_INFO)) {
3320 token = token.next;
3321 }
3322 return token;
3323 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698