| 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 part of scanner; | 5 part of scanner; |
| 6 | 6 |
| 7 class FormalParameterType { | 7 class FormalParameterType { |
| 8 final String type; | 8 final String type; |
| 9 const FormalParameterType(this.type); | 9 const FormalParameterType(this.type); |
| 10 bool get isRequired => this == REQUIRED; | 10 bool get isRequired => this == REQUIRED; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 * | 34 * |
| 35 * Parse methods are generally named parseGrammarProductionSuffix. The | 35 * Parse methods are generally named parseGrammarProductionSuffix. The |
| 36 * suffix can be one of "opt", or "star". "opt" means zero or one | 36 * suffix can be one of "opt", or "star". "opt" means zero or one |
| 37 * matches, "star" means zero or more matches. For example, | 37 * matches, "star" means zero or more matches. For example, |
| 38 * [parseMetadataStar] corresponds to this grammar snippet: [: | 38 * [parseMetadataStar] corresponds to this grammar snippet: [: |
| 39 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. | 39 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. |
| 40 */ | 40 */ |
| 41 class Parser { | 41 class Parser { |
| 42 final Listener listener; | 42 final Listener listener; |
| 43 bool mayParseFunctionExpressions = true; | 43 bool mayParseFunctionExpressions = true; |
| 44 bool yieldIsKeyword = false; |
| 45 bool awaitIsKeyword = false; |
| 44 | 46 |
| 45 Parser(this.listener); | 47 Parser(this.listener); |
| 46 | 48 |
| 47 Token parseUnit(Token token) { | 49 Token parseUnit(Token token) { |
| 48 listener.beginCompilationUnit(token); | 50 listener.beginCompilationUnit(token); |
| 49 int count = 0; | 51 int count = 0; |
| 50 while (!identical(token.kind, EOF_TOKEN)) { | 52 while (!identical(token.kind, EOF_TOKEN)) { |
| 51 token = parseTopLevelDeclaration(token); | 53 token = parseTopLevelDeclaration(token); |
| 52 listener.endTopLevelDeclaration(token); | 54 listener.endTopLevelDeclaration(token); |
| 53 count++; | 55 count++; |
| (...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 } | 859 } |
| 858 | 860 |
| 859 if (type == null) { | 861 if (type == null) { |
| 860 listener.handleNoType(name); | 862 listener.handleNoType(name); |
| 861 } else { | 863 } else { |
| 862 parseReturnTypeOpt(type); | 864 parseReturnTypeOpt(type); |
| 863 } | 865 } |
| 864 Token token = parseIdentifier(name); | 866 Token token = parseIdentifier(name); |
| 865 | 867 |
| 866 token = parseFormalParametersOpt(token); | 868 token = parseFormalParametersOpt(token); |
| 869 bool previousYieldIsKeyword = yieldIsKeyword; |
| 870 bool previousAwaitIsKeyword = awaitIsKeyword; |
| 871 token = parseAsyncModifier(token); |
| 867 token = parseFunctionBody(token, false, externalModifier != null); | 872 token = parseFunctionBody(token, false, externalModifier != null); |
| 873 yieldIsKeyword = previousYieldIsKeyword; |
| 874 awaitIsKeyword = previousAwaitIsKeyword; |
| 868 listener.endTopLevelMethod(start, getOrSet, token); | 875 listener.endTopLevelMethod(start, getOrSet, token); |
| 869 return token.next; | 876 return token.next; |
| 870 } | 877 } |
| 871 | 878 |
| 872 Link<Token> findMemberName(Token token) { | 879 Link<Token> findMemberName(Token token) { |
| 873 Token start = token; | 880 Token start = token; |
| 874 Link<Token> identifiers = const Link<Token>(); | 881 Link<Token> identifiers = const Link<Token>(); |
| 875 while (!identical(token.kind, EOF_TOKEN)) { | 882 while (!identical(token.kind, EOF_TOKEN)) { |
| 876 String value = token.stringValue; | 883 String value = token.stringValue; |
| 877 if ((identical(value, '(')) || (identical(value, '{')) | 884 if ((identical(value, '(')) || (identical(value, '{')) |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1199 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, | 1206 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, |
| 1200 {'modifier': staticModifier}); | 1207 {'modifier': staticModifier}); |
| 1201 } | 1208 } |
| 1202 } else { | 1209 } else { |
| 1203 token = parseIdentifier(name); | 1210 token = parseIdentifier(name); |
| 1204 } | 1211 } |
| 1205 | 1212 |
| 1206 token = parseQualifiedRestOpt(token); | 1213 token = parseQualifiedRestOpt(token); |
| 1207 token = parseFormalParametersOpt(token); | 1214 token = parseFormalParametersOpt(token); |
| 1208 token = parseInitializersOpt(token); | 1215 token = parseInitializersOpt(token); |
| 1216 bool previousYieldIsKeyword = yieldIsKeyword; |
| 1217 bool previousAwaitIsKeyword = awaitIsKeyword; |
| 1218 token = parseAsyncModifier(token); |
| 1209 if (optional('=', token)) { | 1219 if (optional('=', token)) { |
| 1210 token = parseRedirectingFactoryBody(token); | 1220 token = parseRedirectingFactoryBody(token); |
| 1211 } else { | 1221 } else { |
| 1212 token = parseFunctionBody( | 1222 token = parseFunctionBody( |
| 1213 token, false, staticModifier == null || externalModifier != null); | 1223 token, false, staticModifier == null || externalModifier != null); |
| 1214 } | 1224 } |
| 1225 yieldIsKeyword = previousYieldIsKeyword; |
| 1226 awaitIsKeyword = previousAwaitIsKeyword; |
| 1215 listener.endMethod(getOrSet, start, token); | 1227 listener.endMethod(getOrSet, start, token); |
| 1216 return token.next; | 1228 return token.next; |
| 1217 } | 1229 } |
| 1218 | 1230 |
| 1219 Token parseFactoryMethod(Token token) { | 1231 Token parseFactoryMethod(Token token) { |
| 1220 assert(isFactoryDeclaration(token)); | 1232 assert(isFactoryDeclaration(token)); |
| 1221 Token start = token; | 1233 Token start = token; |
| 1222 Token externalModifier; | 1234 Token externalModifier; |
| 1223 if (identical(token.stringValue, 'external')) { | 1235 if (identical(token.stringValue, 'external')) { |
| 1224 externalModifier = token; | 1236 externalModifier = token; |
| 1225 token = token.next; | 1237 token = token.next; |
| 1226 } | 1238 } |
| 1227 Token constKeyword = null; | 1239 Token constKeyword = null; |
| 1228 if (optional('const', token)) { | 1240 if (optional('const', token)) { |
| 1229 constKeyword = token; | 1241 constKeyword = token; |
| 1230 token = token.next; | 1242 token = token.next; |
| 1231 } | 1243 } |
| 1232 Token factoryKeyword = token; | 1244 Token factoryKeyword = token; |
| 1233 listener.beginFactoryMethod(factoryKeyword); | 1245 listener.beginFactoryMethod(factoryKeyword); |
| 1234 token = token.next; // Skip 'factory'. | 1246 token = token.next; // Skip 'factory'. |
| 1235 token = parseConstructorReference(token); | 1247 token = parseConstructorReference(token); |
| 1236 token = parseFormalParameters(token); | 1248 token = parseFormalParameters(token); |
| 1249 bool previousYieldIsKeyword = yieldIsKeyword; |
| 1250 bool previousAwaitIsKeyword = awaitIsKeyword; |
| 1251 token = parseAsyncModifier(token); |
| 1237 if (optional('=', token)) { | 1252 if (optional('=', token)) { |
| 1238 token = parseRedirectingFactoryBody(token); | 1253 token = parseRedirectingFactoryBody(token); |
| 1239 } else { | 1254 } else { |
| 1240 token = parseFunctionBody(token, false, externalModifier != null); | 1255 token = parseFunctionBody(token, false, externalModifier != null); |
| 1241 } | 1256 } |
| 1242 listener.endFactoryMethod(start, token); | 1257 listener.endFactoryMethod(start, token); |
| 1243 return token.next; | 1258 return token.next; |
| 1244 } | 1259 } |
| 1245 | 1260 |
| 1246 Token parseOperatorName(Token token) { | 1261 Token parseOperatorName(Token token) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1270 if (optional('operator', token)) { | 1285 if (optional('operator', token)) { |
| 1271 token = parseOperatorName(token); | 1286 token = parseOperatorName(token); |
| 1272 } else { | 1287 } else { |
| 1273 token = parseIdentifier(token); | 1288 token = parseIdentifier(token); |
| 1274 } | 1289 } |
| 1275 } | 1290 } |
| 1276 token = parseQualifiedRestOpt(token); | 1291 token = parseQualifiedRestOpt(token); |
| 1277 listener.endFunctionName(token); | 1292 listener.endFunctionName(token); |
| 1278 token = parseFormalParametersOpt(token); | 1293 token = parseFormalParametersOpt(token); |
| 1279 token = parseInitializersOpt(token); | 1294 token = parseInitializersOpt(token); |
| 1295 bool previousYieldIsKeyword = yieldIsKeyword; |
| 1296 bool previousAwaitIsKeyword = awaitIsKeyword; |
| 1297 token = parseAsyncModifier(token); |
| 1280 if (optional('=', token)) { | 1298 if (optional('=', token)) { |
| 1281 token = parseRedirectingFactoryBody(token); | 1299 token = parseRedirectingFactoryBody(token); |
| 1282 } else { | 1300 } else { |
| 1283 token = parseFunctionBody(token, false, true); | 1301 token = parseFunctionBody(token, false, true); |
| 1284 } | 1302 } |
| 1303 yieldIsKeyword = previousYieldIsKeyword; |
| 1304 awaitIsKeyword = previousAwaitIsKeyword; |
| 1285 listener.endFunction(getOrSet, token); | 1305 listener.endFunction(getOrSet, token); |
| 1286 return token.next; | 1306 return token.next; |
| 1287 } | 1307 } |
| 1288 | 1308 |
| 1289 Token parseUnamedFunction(Token token) { | 1309 Token parseUnnamedFunction(Token token) { |
| 1290 listener.beginUnamedFunction(token); | 1310 listener.beginUnnamedFunction(token); |
| 1291 token = parseFormalParameters(token); | 1311 token = parseFormalParameters(token); |
| 1312 bool previousYieldIsKeyword = yieldIsKeyword; |
| 1313 bool previousAwaitIsKeyword = awaitIsKeyword; |
| 1314 token = parseAsyncModifier(token); |
| 1292 bool isBlock = optional('{', token); | 1315 bool isBlock = optional('{', token); |
| 1293 token = parseFunctionBody(token, true, false); | 1316 token = parseFunctionBody(token, true, false); |
| 1294 listener.endUnamedFunction(token); | 1317 yieldIsKeyword = previousYieldIsKeyword; |
| 1318 awaitIsKeyword = previousAwaitIsKeyword; |
| 1319 listener.endUnnamedFunction(token); |
| 1295 return isBlock ? token.next : token; | 1320 return isBlock ? token.next : token; |
| 1296 } | 1321 } |
| 1297 | 1322 |
| 1298 Token parseFunctionDeclaration(Token token) { | 1323 Token parseFunctionDeclaration(Token token) { |
| 1299 listener.beginFunctionDeclaration(token); | 1324 listener.beginFunctionDeclaration(token); |
| 1300 token = parseFunction(token, null); | 1325 token = parseFunction(token, null); |
| 1301 listener.endFunctionDeclaration(token); | 1326 listener.endFunctionDeclaration(token); |
| 1302 return token; | 1327 return token; |
| 1303 } | 1328 } |
| 1304 | 1329 |
| 1305 Token parseFunctionExpression(Token token) { | 1330 Token parseFunctionExpression(Token token) { |
| 1306 listener.beginFunction(token); | 1331 listener.beginFunction(token); |
| 1307 listener.handleModifiers(0); | 1332 listener.handleModifiers(0); |
| 1308 token = parseReturnTypeOpt(token); | 1333 token = parseReturnTypeOpt(token); |
| 1309 listener.beginFunctionName(token); | 1334 listener.beginFunctionName(token); |
| 1310 token = parseIdentifier(token); | 1335 token = parseIdentifier(token); |
| 1311 listener.endFunctionName(token); | 1336 listener.endFunctionName(token); |
| 1312 token = parseFormalParameters(token); | 1337 token = parseFormalParameters(token); |
| 1313 listener.handleNoInitializers(); | 1338 listener.handleNoInitializers(); |
| 1339 bool previousYieldIsKeyword = yieldIsKeyword; |
| 1340 bool previousAwaitIsKeyword = awaitIsKeyword; |
| 1341 token = parseAsyncModifier(token); |
| 1314 bool isBlock = optional('{', token); | 1342 bool isBlock = optional('{', token); |
| 1315 token = parseFunctionBody(token, true, false); | 1343 token = parseFunctionBody(token, true, false); |
| 1344 yieldIsKeyword = previousYieldIsKeyword; |
| 1345 awaitIsKeyword = previousAwaitIsKeyword; |
| 1316 listener.endFunction(null, token); | 1346 listener.endFunction(null, token); |
| 1317 return isBlock ? token.next : token; | 1347 return isBlock ? token.next : token; |
| 1318 } | 1348 } |
| 1319 | 1349 |
| 1320 Token parseConstructorReference(Token token) { | 1350 Token parseConstructorReference(Token token) { |
| 1321 Token start = token; | 1351 Token start = token; |
| 1322 listener.beginConstructorReference(start); | 1352 listener.beginConstructorReference(start); |
| 1323 token = parseIdentifier(token); | 1353 token = parseIdentifier(token); |
| 1324 token = parseQualifiedRestOpt(token); | 1354 token = parseQualifiedRestOpt(token); |
| 1325 token = parseTypeArgumentsOpt(token); | 1355 token = parseTypeArgumentsOpt(token); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 token = token.next; | 1401 token = token.next; |
| 1372 while (notEofOrValue('}', token)) { | 1402 while (notEofOrValue('}', token)) { |
| 1373 token = parseStatement(token); | 1403 token = parseStatement(token); |
| 1374 ++statementCount; | 1404 ++statementCount; |
| 1375 } | 1405 } |
| 1376 listener.endFunctionBody(statementCount, begin, token); | 1406 listener.endFunctionBody(statementCount, begin, token); |
| 1377 expect('}', token); | 1407 expect('}', token); |
| 1378 return token; | 1408 return token; |
| 1379 } | 1409 } |
| 1380 | 1410 |
| 1411 /// `async*` and `sync*` are parsed a two tokens, [token] and [star]. This |
| 1412 /// method checks that there is no whitespace between [token] and [star]. |
| 1413 void checkStarredModifier(Token token, Token star, String name) { |
| 1414 if (star.charOffset > token.charOffset + token.charCount) { |
| 1415 listener.reportError(new TokenPair(token, star), |
| 1416 MessageKind.INVALID_STARRED_KEYWORD, {'keyword': name}); |
| 1417 } |
| 1418 } |
| 1419 |
| 1420 Token parseAsyncModifier(Token token) { |
| 1421 Token async; |
| 1422 Token star; |
| 1423 awaitIsKeyword = false; |
| 1424 yieldIsKeyword = false; |
| 1425 if (optional('async', token)) { |
| 1426 awaitIsKeyword = true; |
| 1427 async = token; |
| 1428 token = token.next; |
| 1429 if (optional('*', token)) { |
| 1430 yieldIsKeyword = true; |
| 1431 star = token; |
| 1432 token = token.next; |
| 1433 checkStarredModifier(async, star, 'async*'); |
| 1434 } |
| 1435 } else if (optional('sync', token)) { |
| 1436 async = token; |
| 1437 token = token.next; |
| 1438 if (optional('*', token)) { |
| 1439 yieldIsKeyword = true; |
| 1440 star = token; |
| 1441 token = token.next; |
| 1442 |
| 1443 checkStarredModifier(async, star, 'sync*'); |
| 1444 } else { |
| 1445 listener.reportError(async, |
| 1446 MessageKind.INVALID_SYNC_MODIFIER); |
| 1447 } |
| 1448 } |
| 1449 listener.handleAsyncModifier(async, star); |
| 1450 return token; |
| 1451 } |
| 1452 |
| 1381 Token parseStatement(Token token) { | 1453 Token parseStatement(Token token) { |
| 1382 final value = token.stringValue; | 1454 final value = token.stringValue; |
| 1383 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 1455 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
| 1384 return parseExpressionStatementOrDeclaration(token); | 1456 return parseExpressionStatementOrDeclaration(token); |
| 1385 } else if (identical(value, '{')) { | 1457 } else if (identical(value, '{')) { |
| 1386 return parseBlock(token); | 1458 return parseBlock(token); |
| 1387 } else if (identical(value, 'return')) { | 1459 } else if (identical(value, 'return')) { |
| 1388 return parseReturnStatement(token); | 1460 return parseReturnStatement(token); |
| 1389 } else if (identical(value, 'var') || identical(value, 'final')) { | 1461 } else if (identical(value, 'var') || identical(value, 'final')) { |
| 1390 return parseVariablesDeclaration(token); | 1462 return parseVariablesDeclaration(token); |
| 1391 } else if (identical(value, 'if')) { | 1463 } else if (identical(value, 'if')) { |
| 1392 return parseIfStatement(token); | 1464 return parseIfStatement(token); |
| 1465 } else if (awaitIsKeyword && identical(value, 'await')) { |
| 1466 if (identical(token.next.stringValue, 'for')) { |
| 1467 return parseForStatement(token, token.next); |
| 1468 } else { |
| 1469 return parseExpressionStatement(token); |
| 1470 } |
| 1393 } else if (identical(value, 'for')) { | 1471 } else if (identical(value, 'for')) { |
| 1394 return parseForStatement(token); | 1472 return parseForStatement(null, token); |
| 1395 } else if (identical(value, 'rethrow')) { | 1473 } else if (identical(value, 'rethrow')) { |
| 1396 return parseRethrowStatement(token); | 1474 return parseRethrowStatement(token); |
| 1397 } else if (identical(value, 'throw') && optional(';', token.next)) { | 1475 } else if (identical(value, 'throw') && optional(';', token.next)) { |
| 1398 // TODO(kasperl): Stop dealing with throw here. | 1476 // TODO(kasperl): Stop dealing with throw here. |
| 1399 return parseRethrowStatement(token); | 1477 return parseRethrowStatement(token); |
| 1400 } else if (identical(value, 'void')) { | 1478 } else if (identical(value, 'void')) { |
| 1401 return parseExpressionStatementOrDeclaration(token); | 1479 return parseExpressionStatementOrDeclaration(token); |
| 1402 } else if (identical(value, 'while')) { | 1480 } else if (identical(value, 'while')) { |
| 1403 return parseWhileStatement(token); | 1481 return parseWhileStatement(token); |
| 1404 } else if (identical(value, 'do')) { | 1482 } else if (identical(value, 'do')) { |
| 1405 return parseDoWhileStatement(token); | 1483 return parseDoWhileStatement(token); |
| 1406 } else if (identical(value, 'try')) { | 1484 } else if (identical(value, 'try')) { |
| 1407 return parseTryStatement(token); | 1485 return parseTryStatement(token); |
| 1408 } else if (identical(value, 'switch')) { | 1486 } else if (identical(value, 'switch')) { |
| 1409 return parseSwitchStatement(token); | 1487 return parseSwitchStatement(token); |
| 1410 } else if (identical(value, 'break')) { | 1488 } else if (identical(value, 'break')) { |
| 1411 return parseBreakStatement(token); | 1489 return parseBreakStatement(token); |
| 1412 } else if (identical(value, 'continue')) { | 1490 } else if (identical(value, 'continue')) { |
| 1413 return parseContinueStatement(token); | 1491 return parseContinueStatement(token); |
| 1414 } else if (identical(value, 'assert')) { | 1492 } else if (identical(value, 'assert')) { |
| 1415 return parseAssertStatement(token); | 1493 return parseAssertStatement(token); |
| 1416 } else if (identical(value, ';')) { | 1494 } else if (identical(value, ';')) { |
| 1417 return parseEmptyStatement(token); | 1495 return parseEmptyStatement(token); |
| 1496 } else if (yieldIsKeyword && identical(value, 'yield')) { |
| 1497 return parseYieldStatement(token); |
| 1418 } else if (identical(value, 'const')) { | 1498 } else if (identical(value, 'const')) { |
| 1419 return parseExpressionStatementOrConstDeclaration(token); | 1499 return parseExpressionStatementOrConstDeclaration(token); |
| 1420 } else if (token.isIdentifier()) { | 1500 } else if (token.isIdentifier()) { |
| 1421 return parseExpressionStatementOrDeclaration(token); | 1501 return parseExpressionStatementOrDeclaration(token); |
| 1422 } else { | 1502 } else { |
| 1423 return parseExpressionStatement(token); | 1503 return parseExpressionStatement(token); |
| 1424 } | 1504 } |
| 1425 } | 1505 } |
| 1426 | 1506 |
| 1507 Token parseYieldStatement(Token token) { |
| 1508 Token begin = token; |
| 1509 listener.beginYieldStatement(begin); |
| 1510 assert(identical('yield', token.stringValue)); |
| 1511 token = token.next; |
| 1512 Token starToken; |
| 1513 if (optional('*', token)) { |
| 1514 starToken = token; |
| 1515 token = token.next; |
| 1516 checkStarredModifier(begin, starToken, 'yield*'); |
| 1517 } |
| 1518 token = parseExpression(token); |
| 1519 listener.endYieldStatement(begin, starToken, token); |
| 1520 return expectSemicolon(token); |
| 1521 } |
| 1522 |
| 1523 |
| 1427 Token parseReturnStatement(Token token) { | 1524 Token parseReturnStatement(Token token) { |
| 1428 Token begin = token; | 1525 Token begin = token; |
| 1429 listener.beginReturnStatement(begin); | 1526 listener.beginReturnStatement(begin); |
| 1430 assert(identical('return', token.stringValue)); | 1527 assert(identical('return', token.stringValue)); |
| 1431 token = token.next; | 1528 token = token.next; |
| 1432 if (optional(';', token)) { | 1529 if (optional(';', token)) { |
| 1433 listener.endReturnStatement(false, begin, token); | 1530 listener.endReturnStatement(false, begin, token); |
| 1434 } else { | 1531 } else { |
| 1435 token = parseExpression(token); | 1532 token = parseExpression(token); |
| 1436 listener.endReturnStatement(true, begin, token); | 1533 listener.endReturnStatement(true, begin, token); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1471 if (identical(afterIdKind, EQ_TOKEN) || | 1568 if (identical(afterIdKind, EQ_TOKEN) || |
| 1472 identical(afterIdKind, SEMICOLON_TOKEN) || | 1569 identical(afterIdKind, SEMICOLON_TOKEN) || |
| 1473 identical(afterIdKind, COMMA_TOKEN)) { | 1570 identical(afterIdKind, COMMA_TOKEN)) { |
| 1474 // We are looking at "type identifier" followed by '=', ';', ','. | 1571 // We are looking at "type identifier" followed by '=', ';', ','. |
| 1475 return parseVariablesDeclaration(token); | 1572 return parseVariablesDeclaration(token); |
| 1476 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { | 1573 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { |
| 1477 // We are looking at "type identifier '('". | 1574 // We are looking at "type identifier '('". |
| 1478 BeginGroupToken beginParen = afterId; | 1575 BeginGroupToken beginParen = afterId; |
| 1479 Token endParen = beginParen.endGroup; | 1576 Token endParen = beginParen.endGroup; |
| 1480 Token afterParens = endParen.next; | 1577 Token afterParens = endParen.next; |
| 1481 if (optional('{', afterParens) || optional('=>', afterParens)) { | 1578 if (optional('{', afterParens) || |
| 1579 optional('=>', afterParens) || |
| 1580 optional('async', afterParens) || |
| 1581 optional('sync', afterParens)) { |
| 1482 // We are looking at "type identifier '(' ... ')'" followed | 1582 // We are looking at "type identifier '(' ... ')'" followed |
| 1483 // by '=>' or '{'. | 1583 // by '=>' or '{'. |
| 1484 return parseFunctionDeclaration(token); | 1584 return parseFunctionDeclaration(token); |
| 1485 } | 1585 } |
| 1486 } | 1586 } |
| 1487 // Fall-through to expression statement. | 1587 // Fall-through to expression statement. |
| 1488 } else { | 1588 } else { |
| 1489 if (optional(':', token.next)) { | 1589 if (optional(':', token.next)) { |
| 1490 return parseLabeledStatement(token); | 1590 return parseLabeledStatement(token); |
| 1491 } else if (optional('(', token.next)) { | 1591 } else if (optional('(', token.next)) { |
| 1492 BeginGroupToken begin = token.next; | 1592 BeginGroupToken begin = token.next; |
| 1493 String afterParens = begin.endGroup.next.stringValue; | 1593 String afterParens = begin.endGroup.next.stringValue; |
| 1494 if (identical(afterParens, '{') || identical(afterParens, '=>')) { | 1594 if (identical(afterParens, '{') || |
| 1595 identical(afterParens, '=>') || |
| 1596 identical(afterParens, 'async') || |
| 1597 identical(afterParens, 'sync')) { |
| 1495 return parseFunctionDeclaration(token); | 1598 return parseFunctionDeclaration(token); |
| 1496 } | 1599 } |
| 1497 } | 1600 } |
| 1498 } | 1601 } |
| 1499 return parseExpressionStatement(token); | 1602 return parseExpressionStatement(token); |
| 1500 } | 1603 } |
| 1501 | 1604 |
| 1502 Token parseExpressionStatementOrConstDeclaration(Token token) { | 1605 Token parseExpressionStatementOrConstDeclaration(Token token) { |
| 1503 assert(identical(token.stringValue, 'const')); | 1606 assert(identical(token.stringValue, 'const')); |
| 1504 if (isModifier(token.next)) { | 1607 if (isModifier(token.next)) { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 token = parseExpressionWithoutCascade(token.next); | 1768 token = parseExpressionWithoutCascade(token.next); |
| 1666 listener.handleAssignmentExpression(assignment); | 1769 listener.handleAssignmentExpression(assignment); |
| 1667 } | 1770 } |
| 1668 listener.endCascade(); | 1771 listener.endCascade(); |
| 1669 return token; | 1772 return token; |
| 1670 } | 1773 } |
| 1671 | 1774 |
| 1672 Token parseUnaryExpression(Token token, bool allowCascades) { | 1775 Token parseUnaryExpression(Token token, bool allowCascades) { |
| 1673 String value = token.stringValue; | 1776 String value = token.stringValue; |
| 1674 // Prefix: | 1777 // Prefix: |
| 1675 if (identical(value, '+')) { | 1778 if (awaitIsKeyword && optional('await', token)) { |
| 1779 return parseAwaitExpression(token, allowCascades); |
| 1780 } else if (identical(value, '+')) { |
| 1676 // Dart no longer allows prefix-plus. | 1781 // Dart no longer allows prefix-plus. |
| 1677 listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS); | 1782 listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS); |
| 1678 return parseUnaryExpression(token.next, allowCascades); | 1783 return parseUnaryExpression(token.next, allowCascades); |
| 1679 } else if ((identical(value, '!')) || | 1784 } else if ((identical(value, '!')) || |
| 1680 (identical(value, '-')) || | 1785 (identical(value, '-')) || |
| 1681 (identical(value, '~'))) { | 1786 (identical(value, '~'))) { |
| 1682 Token operator = token; | 1787 Token operator = token; |
| 1683 // Right associative, so we recurse at the same precedence | 1788 // Right associative, so we recurse at the same precedence |
| 1684 // level. | 1789 // level. |
| 1685 token = parsePrecedenceExpression(token.next, POSTFIX_PRECEDENCE, | 1790 token = parsePrecedenceExpression(token.next, POSTFIX_PRECEDENCE, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 (identical(kind, OPEN_CURLY_BRACKET_TOKEN)) || | 1865 (identical(kind, OPEN_CURLY_BRACKET_TOKEN)) || |
| 1761 identical(token.stringValue, '[]')) { | 1866 identical(token.stringValue, '[]')) { |
| 1762 return parseLiteralListOrMap(token); | 1867 return parseLiteralListOrMap(token); |
| 1763 } else { | 1868 } else { |
| 1764 return listener.expectedExpression(token); | 1869 return listener.expectedExpression(token); |
| 1765 } | 1870 } |
| 1766 } | 1871 } |
| 1767 | 1872 |
| 1768 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 1873 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
| 1769 BeginGroupToken beginGroup = token; | 1874 BeginGroupToken beginGroup = token; |
| 1770 int kind = beginGroup.endGroup.next.kind; | 1875 Token nextToken = beginGroup.endGroup.next; |
| 1876 int kind = nextToken.kind; |
| 1771 if (mayParseFunctionExpressions && | 1877 if (mayParseFunctionExpressions && |
| 1772 (identical(kind, FUNCTION_TOKEN) | 1878 (identical(kind, FUNCTION_TOKEN) || |
| 1773 || identical(kind, OPEN_CURLY_BRACKET_TOKEN))) { | 1879 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || |
| 1774 return parseUnamedFunction(token); | 1880 (identical(kind, KEYWORD_TOKEN) && |
| 1881 (nextToken.value == 'async' || nextToken.value == 'sync')))) { |
| 1882 return parseUnnamedFunction(token); |
| 1775 } else { | 1883 } else { |
| 1776 bool old = mayParseFunctionExpressions; | 1884 bool old = mayParseFunctionExpressions; |
| 1777 mayParseFunctionExpressions = true; | 1885 mayParseFunctionExpressions = true; |
| 1778 token = parseParenthesizedExpression(token); | 1886 token = parseParenthesizedExpression(token); |
| 1779 mayParseFunctionExpressions = old; | 1887 mayParseFunctionExpressions = old; |
| 1780 return token; | 1888 return token; |
| 1781 } | 1889 } |
| 1782 } | 1890 } |
| 1783 | 1891 |
| 1784 Token parseParenthesizedExpression(Token token) { | 1892 Token parseParenthesizedExpression(Token token) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1886 return parseFunctionExpression(token); | 1994 return parseFunctionExpression(token); |
| 1887 } else { | 1995 } else { |
| 1888 return parseSend(token); | 1996 return parseSend(token); |
| 1889 } | 1997 } |
| 1890 } | 1998 } |
| 1891 | 1999 |
| 1892 bool isFunctionDeclaration(Token token) { | 2000 bool isFunctionDeclaration(Token token) { |
| 1893 if (optional('(', token)) { | 2001 if (optional('(', token)) { |
| 1894 BeginGroupToken begin = token; | 2002 BeginGroupToken begin = token; |
| 1895 String afterParens = begin.endGroup.next.stringValue; | 2003 String afterParens = begin.endGroup.next.stringValue; |
| 1896 if (identical(afterParens, '{') || identical(afterParens, '=>')) { | 2004 if (identical(afterParens, '{') || |
| 2005 identical(afterParens, '=>') || |
| 2006 identical(afterParens, 'async') || |
| 2007 identical(afterParens, 'sync')) { |
| 1897 return true; | 2008 return true; |
| 1898 } | 2009 } |
| 1899 } | 2010 } |
| 1900 return false; | 2011 return false; |
| 1901 } | 2012 } |
| 1902 | 2013 |
| 1903 Token parseRequiredArguments(Token token) { | 2014 Token parseRequiredArguments(Token token) { |
| 1904 if (optional('(', token)) { | 2015 if (optional('(', token)) { |
| 1905 token = parseArguments(token); | 2016 token = parseArguments(token); |
| 1906 } else { | 2017 } else { |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2144 token = parseStatement(token); | 2255 token = parseStatement(token); |
| 2145 Token elseToken = null; | 2256 Token elseToken = null; |
| 2146 if (optional('else', token)) { | 2257 if (optional('else', token)) { |
| 2147 elseToken = token; | 2258 elseToken = token; |
| 2148 token = parseStatement(token.next); | 2259 token = parseStatement(token.next); |
| 2149 } | 2260 } |
| 2150 listener.endIfStatement(ifToken, elseToken); | 2261 listener.endIfStatement(ifToken, elseToken); |
| 2151 return token; | 2262 return token; |
| 2152 } | 2263 } |
| 2153 | 2264 |
| 2154 Token parseForStatement(Token token) { | 2265 Token parseForStatement(Token awaitToken, Token token) { |
| 2155 Token forToken = token; | 2266 Token forToken = token; |
| 2156 listener.beginForStatement(forToken); | 2267 listener.beginForStatement(forToken); |
| 2157 token = expect('for', token); | 2268 token = expect('for', token); |
| 2158 token = expect('(', token); | 2269 token = expect('(', token); |
| 2159 token = parseVariablesDeclarationOrExpressionOpt(token); | 2270 token = parseVariablesDeclarationOrExpressionOpt(token); |
| 2160 if (optional('in', token)) { | 2271 if (optional('in', token)) { |
| 2161 return parseForInRest(forToken, token); | 2272 return parseForInRest(awaitToken, forToken, token); |
| 2162 } else { | 2273 } else { |
| 2274 if (awaitToken != null) { |
| 2275 listener.reportError(awaitToken, MessageKind.INVALID_AWAIT_FOR); |
| 2276 } |
| 2163 return parseForRest(forToken, token); | 2277 return parseForRest(forToken, token); |
| 2164 } | 2278 } |
| 2165 } | 2279 } |
| 2166 | 2280 |
| 2167 Token parseVariablesDeclarationOrExpressionOpt(Token token) { | 2281 Token parseVariablesDeclarationOrExpressionOpt(Token token) { |
| 2168 final String value = token.stringValue; | 2282 final String value = token.stringValue; |
| 2169 if (identical(value, ';')) { | 2283 if (identical(value, ';')) { |
| 2170 listener.handleNoExpression(token); | 2284 listener.handleNoExpression(token); |
| 2171 return token; | 2285 return token; |
| 2172 } else if ((identical(value, 'var')) || (identical(value, 'final'))) { | 2286 } else if ((identical(value, 'var')) || (identical(value, 'final'))) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2199 } else { | 2313 } else { |
| 2200 break; | 2314 break; |
| 2201 } | 2315 } |
| 2202 } | 2316 } |
| 2203 token = expect(')', token); | 2317 token = expect(')', token); |
| 2204 token = parseStatement(token); | 2318 token = parseStatement(token); |
| 2205 listener.endForStatement(expressionCount, forToken, token); | 2319 listener.endForStatement(expressionCount, forToken, token); |
| 2206 return token; | 2320 return token; |
| 2207 } | 2321 } |
| 2208 | 2322 |
| 2209 Token parseForInRest(Token forToken, Token token) { | 2323 Token parseForInRest(Token awaitToken, Token forToken, Token token) { |
| 2210 assert(optional('in', token)); | 2324 assert(optional('in', token)); |
| 2211 Token inKeyword = token; | 2325 Token inKeyword = token; |
| 2212 token = parseExpression(token.next); | 2326 token = parseExpression(token.next); |
| 2213 token = expect(')', token); | 2327 token = expect(')', token); |
| 2214 token = parseStatement(token); | 2328 token = parseStatement(token); |
| 2215 listener.endForIn(forToken, inKeyword, token); | 2329 listener.endForIn(awaitToken, forToken, inKeyword, token); |
| 2216 return token; | 2330 return token; |
| 2217 } | 2331 } |
| 2218 | 2332 |
| 2219 Token parseWhileStatement(Token token) { | 2333 Token parseWhileStatement(Token token) { |
| 2220 Token whileToken = token; | 2334 Token whileToken = token; |
| 2221 listener.beginWhileStatement(whileToken); | 2335 listener.beginWhileStatement(whileToken); |
| 2222 token = expect('while', token); | 2336 token = expect('while', token); |
| 2223 token = parseParenthesizedExpression(token); | 2337 token = parseParenthesizedExpression(token); |
| 2224 token = parseStatement(token); | 2338 token = parseStatement(token); |
| 2225 listener.endWhileStatement(whileToken, token); | 2339 listener.endWhileStatement(whileToken, token); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2244 int statementCount = 0; | 2358 int statementCount = 0; |
| 2245 token = expect('{', token); | 2359 token = expect('{', token); |
| 2246 while (notEofOrValue('}', token)) { | 2360 while (notEofOrValue('}', token)) { |
| 2247 token = parseStatement(token); | 2361 token = parseStatement(token); |
| 2248 ++statementCount; | 2362 ++statementCount; |
| 2249 } | 2363 } |
| 2250 listener.endBlock(statementCount, begin, token); | 2364 listener.endBlock(statementCount, begin, token); |
| 2251 return expect('}', token); | 2365 return expect('}', token); |
| 2252 } | 2366 } |
| 2253 | 2367 |
| 2368 Token parseAwaitExpression(Token token, bool allowCascades) { |
| 2369 Token awaitToken = token; |
| 2370 listener.beginAwaitExpression(awaitToken); |
| 2371 token = expect('await', token); |
| 2372 token = parseUnaryExpression(token, allowCascades); |
| 2373 listener.endAwaitExpression(awaitToken, token); |
| 2374 return token; |
| 2375 } |
| 2376 |
| 2254 Token parseThrowExpression(Token token, bool allowCascades) { | 2377 Token parseThrowExpression(Token token, bool allowCascades) { |
| 2255 Token throwToken = token; | 2378 Token throwToken = token; |
| 2256 listener.beginThrowExpression(throwToken); | 2379 listener.beginThrowExpression(throwToken); |
| 2257 token = expect('throw', token); | 2380 token = expect('throw', token); |
| 2258 token = allowCascades | 2381 token = allowCascades |
| 2259 ? parseExpression(token) | 2382 ? parseExpression(token) |
| 2260 : parseExpressionWithoutCascade(token); | 2383 : parseExpressionWithoutCascade(token); |
| 2261 listener.endThrowExpression(throwToken, token); | 2384 listener.endThrowExpression(throwToken, token); |
| 2262 return token; | 2385 return token; |
| 2263 } | 2386 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2446 } | 2569 } |
| 2447 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2570 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 2448 return expectSemicolon(token); | 2571 return expectSemicolon(token); |
| 2449 } | 2572 } |
| 2450 | 2573 |
| 2451 Token parseEmptyStatement(Token token) { | 2574 Token parseEmptyStatement(Token token) { |
| 2452 listener.handleEmptyStatement(token); | 2575 listener.handleEmptyStatement(token); |
| 2453 return expectSemicolon(token); | 2576 return expectSemicolon(token); |
| 2454 } | 2577 } |
| 2455 } | 2578 } |
| OLD | NEW |