Chromium Code Reviews| 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 void checkStarredModifier(Token token, Token star, String name) { | |
|
floitsch
2014/11/03 17:55:54
Add comment what exactly this checks.
Johnni Winther
2014/11/04 12:24:33
Done.
| |
| 1412 if (star.charOffset > token.charOffset + token.charCount) { | |
| 1413 listener.reportError(new TokenPair(token, star), | |
| 1414 MessageKind.INVALID_STARRED_KEYWORD, {'keyword': name}); | |
| 1415 } | |
| 1416 } | |
| 1417 | |
| 1418 Token parseAsyncModifier(Token token) { | |
| 1419 Token async; | |
| 1420 Token star; | |
| 1421 awaitIsKeyword = false; | |
| 1422 yieldIsKeyword = false; | |
| 1423 if (optional('async', token)) { | |
| 1424 awaitIsKeyword = true; | |
| 1425 async = token; | |
| 1426 token = token.next; | |
| 1427 if (optional('*', token)) { | |
| 1428 yieldIsKeyword = true; | |
| 1429 star = token; | |
| 1430 token = token.next; | |
| 1431 checkStarredModifier(async, star, 'async*'); | |
| 1432 } | |
| 1433 } else if (optional('sync', token)) { | |
| 1434 async = token; | |
| 1435 token = token.next; | |
| 1436 if (optional('*', token)) { | |
| 1437 yieldIsKeyword = true; | |
| 1438 star = token; | |
| 1439 token = token.next; | |
| 1440 | |
| 1441 checkStarredModifier(async, star, 'sync*'); | |
| 1442 } else { | |
| 1443 listener.reportError(async, | |
| 1444 MessageKind.INVALID_SYNC_MODIFIER); | |
| 1445 } | |
| 1446 } | |
| 1447 listener.handleAsyncModifier(async, star); | |
| 1448 return token; | |
| 1449 } | |
| 1450 | |
| 1381 Token parseStatement(Token token) { | 1451 Token parseStatement(Token token) { |
| 1382 final value = token.stringValue; | 1452 final value = token.stringValue; |
| 1383 if (identical(token.kind, IDENTIFIER_TOKEN)) { | 1453 if (identical(token.kind, IDENTIFIER_TOKEN)) { |
| 1384 return parseExpressionStatementOrDeclaration(token); | 1454 return parseExpressionStatementOrDeclaration(token); |
| 1385 } else if (identical(value, '{')) { | 1455 } else if (identical(value, '{')) { |
| 1386 return parseBlock(token); | 1456 return parseBlock(token); |
| 1387 } else if (identical(value, 'return')) { | 1457 } else if (identical(value, 'return')) { |
| 1388 return parseReturnStatement(token); | 1458 return parseReturnStatement(token); |
| 1389 } else if (identical(value, 'var') || identical(value, 'final')) { | 1459 } else if (identical(value, 'var') || identical(value, 'final')) { |
| 1390 return parseVariablesDeclaration(token); | 1460 return parseVariablesDeclaration(token); |
| 1391 } else if (identical(value, 'if')) { | 1461 } else if (identical(value, 'if')) { |
| 1392 return parseIfStatement(token); | 1462 return parseIfStatement(token); |
| 1463 } else if (awaitIsKeyword && identical(value, 'await')) { | |
| 1464 if (identical(token.next.stringValue, 'for')) { | |
| 1465 return parseForStatement(token, token.next); | |
| 1466 } else { | |
| 1467 return parseExpressionStatement(token); | |
| 1468 } | |
| 1393 } else if (identical(value, 'for')) { | 1469 } else if (identical(value, 'for')) { |
| 1394 return parseForStatement(token); | 1470 return parseForStatement(null, token); |
| 1395 } else if (identical(value, 'rethrow')) { | 1471 } else if (identical(value, 'rethrow')) { |
| 1396 return parseRethrowStatement(token); | 1472 return parseRethrowStatement(token); |
| 1397 } else if (identical(value, 'throw') && optional(';', token.next)) { | 1473 } else if (identical(value, 'throw') && optional(';', token.next)) { |
| 1398 // TODO(kasperl): Stop dealing with throw here. | 1474 // TODO(kasperl): Stop dealing with throw here. |
| 1399 return parseRethrowStatement(token); | 1475 return parseRethrowStatement(token); |
| 1400 } else if (identical(value, 'void')) { | 1476 } else if (identical(value, 'void')) { |
| 1401 return parseExpressionStatementOrDeclaration(token); | 1477 return parseExpressionStatementOrDeclaration(token); |
| 1402 } else if (identical(value, 'while')) { | 1478 } else if (identical(value, 'while')) { |
| 1403 return parseWhileStatement(token); | 1479 return parseWhileStatement(token); |
| 1404 } else if (identical(value, 'do')) { | 1480 } else if (identical(value, 'do')) { |
| 1405 return parseDoWhileStatement(token); | 1481 return parseDoWhileStatement(token); |
| 1406 } else if (identical(value, 'try')) { | 1482 } else if (identical(value, 'try')) { |
| 1407 return parseTryStatement(token); | 1483 return parseTryStatement(token); |
| 1408 } else if (identical(value, 'switch')) { | 1484 } else if (identical(value, 'switch')) { |
| 1409 return parseSwitchStatement(token); | 1485 return parseSwitchStatement(token); |
| 1410 } else if (identical(value, 'break')) { | 1486 } else if (identical(value, 'break')) { |
| 1411 return parseBreakStatement(token); | 1487 return parseBreakStatement(token); |
| 1412 } else if (identical(value, 'continue')) { | 1488 } else if (identical(value, 'continue')) { |
| 1413 return parseContinueStatement(token); | 1489 return parseContinueStatement(token); |
| 1414 } else if (identical(value, 'assert')) { | 1490 } else if (identical(value, 'assert')) { |
| 1415 return parseAssertStatement(token); | 1491 return parseAssertStatement(token); |
| 1416 } else if (identical(value, ';')) { | 1492 } else if (identical(value, ';')) { |
| 1417 return parseEmptyStatement(token); | 1493 return parseEmptyStatement(token); |
| 1494 } else if (yieldIsKeyword && identical(value, 'yield')) { | |
| 1495 return parseYieldStatement(token); | |
| 1418 } else if (identical(value, 'const')) { | 1496 } else if (identical(value, 'const')) { |
| 1419 return parseExpressionStatementOrConstDeclaration(token); | 1497 return parseExpressionStatementOrConstDeclaration(token); |
| 1420 } else if (token.isIdentifier()) { | 1498 } else if (token.isIdentifier()) { |
| 1421 return parseExpressionStatementOrDeclaration(token); | 1499 return parseExpressionStatementOrDeclaration(token); |
| 1422 } else { | 1500 } else { |
| 1423 return parseExpressionStatement(token); | 1501 return parseExpressionStatement(token); |
| 1424 } | 1502 } |
| 1425 } | 1503 } |
| 1426 | 1504 |
| 1505 Token parseYieldStatement(Token token) { | |
| 1506 Token begin = token; | |
| 1507 listener.beginYieldStatement(begin); | |
| 1508 assert(identical('yield', token.stringValue)); | |
| 1509 token = token.next; | |
| 1510 Token starToken; | |
| 1511 if (optional('*', token)) { | |
| 1512 starToken = token; | |
| 1513 token = token.next; | |
| 1514 checkStarredModifier(begin, starToken, 'yield*'); | |
| 1515 } | |
| 1516 token = parseExpression(token); | |
| 1517 listener.endYieldStatement(begin, starToken, token); | |
| 1518 return expectSemicolon(token); | |
| 1519 } | |
| 1520 | |
| 1521 | |
| 1427 Token parseReturnStatement(Token token) { | 1522 Token parseReturnStatement(Token token) { |
| 1428 Token begin = token; | 1523 Token begin = token; |
| 1429 listener.beginReturnStatement(begin); | 1524 listener.beginReturnStatement(begin); |
| 1430 assert(identical('return', token.stringValue)); | 1525 assert(identical('return', token.stringValue)); |
| 1431 token = token.next; | 1526 token = token.next; |
| 1432 if (optional(';', token)) { | 1527 if (optional(';', token)) { |
| 1433 listener.endReturnStatement(false, begin, token); | 1528 listener.endReturnStatement(false, begin, token); |
| 1434 } else { | 1529 } else { |
| 1435 token = parseExpression(token); | 1530 token = parseExpression(token); |
| 1436 listener.endReturnStatement(true, begin, token); | 1531 listener.endReturnStatement(true, begin, token); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1471 if (identical(afterIdKind, EQ_TOKEN) || | 1566 if (identical(afterIdKind, EQ_TOKEN) || |
| 1472 identical(afterIdKind, SEMICOLON_TOKEN) || | 1567 identical(afterIdKind, SEMICOLON_TOKEN) || |
| 1473 identical(afterIdKind, COMMA_TOKEN)) { | 1568 identical(afterIdKind, COMMA_TOKEN)) { |
| 1474 // We are looking at "type identifier" followed by '=', ';', ','. | 1569 // We are looking at "type identifier" followed by '=', ';', ','. |
| 1475 return parseVariablesDeclaration(token); | 1570 return parseVariablesDeclaration(token); |
| 1476 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { | 1571 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { |
| 1477 // We are looking at "type identifier '('". | 1572 // We are looking at "type identifier '('". |
| 1478 BeginGroupToken beginParen = afterId; | 1573 BeginGroupToken beginParen = afterId; |
| 1479 Token endParen = beginParen.endGroup; | 1574 Token endParen = beginParen.endGroup; |
| 1480 Token afterParens = endParen.next; | 1575 Token afterParens = endParen.next; |
| 1481 if (optional('{', afterParens) || optional('=>', afterParens)) { | 1576 if (optional('{', afterParens) || |
| 1577 optional('=>', afterParens) || | |
| 1578 optional('async', afterParens) || | |
| 1579 optional('sync', afterParens)) { | |
| 1482 // We are looking at "type identifier '(' ... ')'" followed | 1580 // We are looking at "type identifier '(' ... ')'" followed |
| 1483 // by '=>' or '{'. | 1581 // by '=>' or '{'. |
| 1484 return parseFunctionDeclaration(token); | 1582 return parseFunctionDeclaration(token); |
| 1485 } | 1583 } |
| 1486 } | 1584 } |
| 1487 // Fall-through to expression statement. | 1585 // Fall-through to expression statement. |
| 1488 } else { | 1586 } else { |
| 1489 if (optional(':', token.next)) { | 1587 if (optional(':', token.next)) { |
| 1490 return parseLabeledStatement(token); | 1588 return parseLabeledStatement(token); |
| 1491 } else if (optional('(', token.next)) { | 1589 } else if (optional('(', token.next)) { |
| 1492 BeginGroupToken begin = token.next; | 1590 BeginGroupToken begin = token.next; |
| 1493 String afterParens = begin.endGroup.next.stringValue; | 1591 String afterParens = begin.endGroup.next.stringValue; |
| 1494 if (identical(afterParens, '{') || identical(afterParens, '=>')) { | 1592 if (identical(afterParens, '{') || |
| 1593 identical(afterParens, '=>') || | |
| 1594 identical(afterParens, 'async') || | |
| 1595 identical(afterParens, 'sync')) { | |
| 1495 return parseFunctionDeclaration(token); | 1596 return parseFunctionDeclaration(token); |
| 1496 } | 1597 } |
| 1497 } | 1598 } |
| 1498 } | 1599 } |
| 1499 return parseExpressionStatement(token); | 1600 return parseExpressionStatement(token); |
| 1500 } | 1601 } |
| 1501 | 1602 |
| 1502 Token parseExpressionStatementOrConstDeclaration(Token token) { | 1603 Token parseExpressionStatementOrConstDeclaration(Token token) { |
| 1503 assert(identical(token.stringValue, 'const')); | 1604 assert(identical(token.stringValue, 'const')); |
| 1504 if (isModifier(token.next)) { | 1605 if (isModifier(token.next)) { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1665 token = parseExpressionWithoutCascade(token.next); | 1766 token = parseExpressionWithoutCascade(token.next); |
| 1666 listener.handleAssignmentExpression(assignment); | 1767 listener.handleAssignmentExpression(assignment); |
| 1667 } | 1768 } |
| 1668 listener.endCascade(); | 1769 listener.endCascade(); |
| 1669 return token; | 1770 return token; |
| 1670 } | 1771 } |
| 1671 | 1772 |
| 1672 Token parseUnaryExpression(Token token, bool allowCascades) { | 1773 Token parseUnaryExpression(Token token, bool allowCascades) { |
| 1673 String value = token.stringValue; | 1774 String value = token.stringValue; |
| 1674 // Prefix: | 1775 // Prefix: |
| 1675 if (identical(value, '+')) { | 1776 if (awaitIsKeyword && optional('await', token)) { |
| 1777 return parseAwaitExpression(token, allowCascades); | |
| 1778 } else if (identical(value, '+')) { | |
| 1676 // Dart no longer allows prefix-plus. | 1779 // Dart no longer allows prefix-plus. |
| 1677 listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS); | 1780 listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS); |
| 1678 return parseUnaryExpression(token.next, allowCascades); | 1781 return parseUnaryExpression(token.next, allowCascades); |
| 1679 } else if ((identical(value, '!')) || | 1782 } else if ((identical(value, '!')) || |
| 1680 (identical(value, '-')) || | 1783 (identical(value, '-')) || |
| 1681 (identical(value, '~'))) { | 1784 (identical(value, '~'))) { |
| 1682 Token operator = token; | 1785 Token operator = token; |
| 1683 // Right associative, so we recurse at the same precedence | 1786 // Right associative, so we recurse at the same precedence |
| 1684 // level. | 1787 // level. |
| 1685 token = parsePrecedenceExpression(token.next, POSTFIX_PRECEDENCE, | 1788 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)) || | 1863 (identical(kind, OPEN_CURLY_BRACKET_TOKEN)) || |
| 1761 identical(token.stringValue, '[]')) { | 1864 identical(token.stringValue, '[]')) { |
| 1762 return parseLiteralListOrMap(token); | 1865 return parseLiteralListOrMap(token); |
| 1763 } else { | 1866 } else { |
| 1764 return listener.expectedExpression(token); | 1867 return listener.expectedExpression(token); |
| 1765 } | 1868 } |
| 1766 } | 1869 } |
| 1767 | 1870 |
| 1768 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { | 1871 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
| 1769 BeginGroupToken beginGroup = token; | 1872 BeginGroupToken beginGroup = token; |
| 1770 int kind = beginGroup.endGroup.next.kind; | 1873 Token nextToken = beginGroup.endGroup.next; |
| 1874 int kind = nextToken.kind; | |
| 1771 if (mayParseFunctionExpressions && | 1875 if (mayParseFunctionExpressions && |
| 1772 (identical(kind, FUNCTION_TOKEN) | 1876 (identical(kind, FUNCTION_TOKEN) || |
| 1773 || identical(kind, OPEN_CURLY_BRACKET_TOKEN))) { | 1877 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || |
| 1774 return parseUnamedFunction(token); | 1878 (identical(kind, KEYWORD_TOKEN) && |
| 1879 (nextToken.value == 'async' || nextToken.value == 'sync')))) { | |
| 1880 return parseUnnamedFunction(token); | |
| 1775 } else { | 1881 } else { |
| 1776 bool old = mayParseFunctionExpressions; | 1882 bool old = mayParseFunctionExpressions; |
| 1777 mayParseFunctionExpressions = true; | 1883 mayParseFunctionExpressions = true; |
| 1778 token = parseParenthesizedExpression(token); | 1884 token = parseParenthesizedExpression(token); |
| 1779 mayParseFunctionExpressions = old; | 1885 mayParseFunctionExpressions = old; |
| 1780 return token; | 1886 return token; |
| 1781 } | 1887 } |
| 1782 } | 1888 } |
| 1783 | 1889 |
| 1784 Token parseParenthesizedExpression(Token token) { | 1890 Token parseParenthesizedExpression(Token token) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1886 return parseFunctionExpression(token); | 1992 return parseFunctionExpression(token); |
| 1887 } else { | 1993 } else { |
| 1888 return parseSend(token); | 1994 return parseSend(token); |
| 1889 } | 1995 } |
| 1890 } | 1996 } |
| 1891 | 1997 |
| 1892 bool isFunctionDeclaration(Token token) { | 1998 bool isFunctionDeclaration(Token token) { |
| 1893 if (optional('(', token)) { | 1999 if (optional('(', token)) { |
| 1894 BeginGroupToken begin = token; | 2000 BeginGroupToken begin = token; |
| 1895 String afterParens = begin.endGroup.next.stringValue; | 2001 String afterParens = begin.endGroup.next.stringValue; |
| 1896 if (identical(afterParens, '{') || identical(afterParens, '=>')) { | 2002 if (identical(afterParens, '{') || |
| 2003 identical(afterParens, '=>') || | |
| 2004 identical(afterParens, 'async') || | |
| 2005 identical(afterParens, 'sync')) { | |
| 1897 return true; | 2006 return true; |
| 1898 } | 2007 } |
| 1899 } | 2008 } |
| 1900 return false; | 2009 return false; |
| 1901 } | 2010 } |
| 1902 | 2011 |
| 1903 Token parseRequiredArguments(Token token) { | 2012 Token parseRequiredArguments(Token token) { |
| 1904 if (optional('(', token)) { | 2013 if (optional('(', token)) { |
| 1905 token = parseArguments(token); | 2014 token = parseArguments(token); |
| 1906 } else { | 2015 } else { |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2144 token = parseStatement(token); | 2253 token = parseStatement(token); |
| 2145 Token elseToken = null; | 2254 Token elseToken = null; |
| 2146 if (optional('else', token)) { | 2255 if (optional('else', token)) { |
| 2147 elseToken = token; | 2256 elseToken = token; |
| 2148 token = parseStatement(token.next); | 2257 token = parseStatement(token.next); |
| 2149 } | 2258 } |
| 2150 listener.endIfStatement(ifToken, elseToken); | 2259 listener.endIfStatement(ifToken, elseToken); |
| 2151 return token; | 2260 return token; |
| 2152 } | 2261 } |
| 2153 | 2262 |
| 2154 Token parseForStatement(Token token) { | 2263 Token parseForStatement(Token awaitToken, Token token) { |
| 2155 Token forToken = token; | 2264 Token forToken = token; |
| 2156 listener.beginForStatement(forToken); | 2265 listener.beginForStatement(forToken); |
| 2157 token = expect('for', token); | 2266 token = expect('for', token); |
| 2158 token = expect('(', token); | 2267 token = expect('(', token); |
| 2159 token = parseVariablesDeclarationOrExpressionOpt(token); | 2268 token = parseVariablesDeclarationOrExpressionOpt(token); |
| 2160 if (optional('in', token)) { | 2269 if (optional('in', token)) { |
| 2161 return parseForInRest(forToken, token); | 2270 return parseForInRest(awaitToken, forToken, token); |
| 2162 } else { | 2271 } else { |
| 2272 if (awaitToken != null) { | |
| 2273 listener.reportError(awaitToken, MessageKind.INVALID_AWAIT_FOR); | |
| 2274 } | |
| 2163 return parseForRest(forToken, token); | 2275 return parseForRest(forToken, token); |
| 2164 } | 2276 } |
| 2165 } | 2277 } |
| 2166 | 2278 |
| 2167 Token parseVariablesDeclarationOrExpressionOpt(Token token) { | 2279 Token parseVariablesDeclarationOrExpressionOpt(Token token) { |
| 2168 final String value = token.stringValue; | 2280 final String value = token.stringValue; |
| 2169 if (identical(value, ';')) { | 2281 if (identical(value, ';')) { |
| 2170 listener.handleNoExpression(token); | 2282 listener.handleNoExpression(token); |
| 2171 return token; | 2283 return token; |
| 2172 } else if ((identical(value, 'var')) || (identical(value, 'final'))) { | 2284 } else if ((identical(value, 'var')) || (identical(value, 'final'))) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2199 } else { | 2311 } else { |
| 2200 break; | 2312 break; |
| 2201 } | 2313 } |
| 2202 } | 2314 } |
| 2203 token = expect(')', token); | 2315 token = expect(')', token); |
| 2204 token = parseStatement(token); | 2316 token = parseStatement(token); |
| 2205 listener.endForStatement(expressionCount, forToken, token); | 2317 listener.endForStatement(expressionCount, forToken, token); |
| 2206 return token; | 2318 return token; |
| 2207 } | 2319 } |
| 2208 | 2320 |
| 2209 Token parseForInRest(Token forToken, Token token) { | 2321 Token parseForInRest(Token awaitToken, Token forToken, Token token) { |
| 2210 assert(optional('in', token)); | 2322 assert(optional('in', token)); |
| 2211 Token inKeyword = token; | 2323 Token inKeyword = token; |
| 2212 token = parseExpression(token.next); | 2324 token = parseExpression(token.next); |
| 2213 token = expect(')', token); | 2325 token = expect(')', token); |
| 2214 token = parseStatement(token); | 2326 token = parseStatement(token); |
| 2215 listener.endForIn(forToken, inKeyword, token); | 2327 listener.endForIn(awaitToken, forToken, inKeyword, token); |
| 2216 return token; | 2328 return token; |
| 2217 } | 2329 } |
| 2218 | 2330 |
| 2219 Token parseWhileStatement(Token token) { | 2331 Token parseWhileStatement(Token token) { |
| 2220 Token whileToken = token; | 2332 Token whileToken = token; |
| 2221 listener.beginWhileStatement(whileToken); | 2333 listener.beginWhileStatement(whileToken); |
| 2222 token = expect('while', token); | 2334 token = expect('while', token); |
| 2223 token = parseParenthesizedExpression(token); | 2335 token = parseParenthesizedExpression(token); |
| 2224 token = parseStatement(token); | 2336 token = parseStatement(token); |
| 2225 listener.endWhileStatement(whileToken, token); | 2337 listener.endWhileStatement(whileToken, token); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 2244 int statementCount = 0; | 2356 int statementCount = 0; |
| 2245 token = expect('{', token); | 2357 token = expect('{', token); |
| 2246 while (notEofOrValue('}', token)) { | 2358 while (notEofOrValue('}', token)) { |
| 2247 token = parseStatement(token); | 2359 token = parseStatement(token); |
| 2248 ++statementCount; | 2360 ++statementCount; |
| 2249 } | 2361 } |
| 2250 listener.endBlock(statementCount, begin, token); | 2362 listener.endBlock(statementCount, begin, token); |
| 2251 return expect('}', token); | 2363 return expect('}', token); |
| 2252 } | 2364 } |
| 2253 | 2365 |
| 2366 Token parseAwaitExpression(Token token, bool allowCascades) { | |
| 2367 Token awaitToken = token; | |
| 2368 listener.beginAwaitExpression(awaitToken); | |
| 2369 token = expect('await', token); | |
| 2370 token = parseUnaryExpression(token, allowCascades); | |
| 2371 listener.endAwaitExpression(awaitToken, token); | |
| 2372 return token; | |
| 2373 } | |
| 2374 | |
| 2254 Token parseThrowExpression(Token token, bool allowCascades) { | 2375 Token parseThrowExpression(Token token, bool allowCascades) { |
| 2255 Token throwToken = token; | 2376 Token throwToken = token; |
| 2256 listener.beginThrowExpression(throwToken); | 2377 listener.beginThrowExpression(throwToken); |
| 2257 token = expect('throw', token); | 2378 token = expect('throw', token); |
| 2258 token = allowCascades | 2379 token = allowCascades |
| 2259 ? parseExpression(token) | 2380 ? parseExpression(token) |
| 2260 : parseExpressionWithoutCascade(token); | 2381 : parseExpressionWithoutCascade(token); |
| 2261 listener.endThrowExpression(throwToken, token); | 2382 listener.endThrowExpression(throwToken, token); |
| 2262 return token; | 2383 return token; |
| 2263 } | 2384 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2446 } | 2567 } |
| 2447 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2568 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 2448 return expectSemicolon(token); | 2569 return expectSemicolon(token); |
| 2449 } | 2570 } |
| 2450 | 2571 |
| 2451 Token parseEmptyStatement(Token token) { | 2572 Token parseEmptyStatement(Token token) { |
| 2452 listener.handleEmptyStatement(token); | 2573 listener.handleEmptyStatement(token); |
| 2453 return expectSemicolon(token); | 2574 return expectSemicolon(token); |
| 2454 } | 2575 } |
| 2455 } | 2576 } |
| OLD | NEW |