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 library dart2js.parser; | 5 library dart2js.parser; |
| 6 | 6 |
| 7 import '../options.dart' show | 7 import '../options.dart' show |
| 8 ParserOptions; | 8 ParserOptions; |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../tokens/keyword.dart' show | 10 import '../tokens/keyword.dart' show |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 KeywordToken, | 34 KeywordToken, |
| 35 SymbolToken, | 35 SymbolToken, |
| 36 Token; | 36 Token; |
| 37 import '../tokens/token_constants.dart' show | 37 import '../tokens/token_constants.dart' show |
| 38 BAD_INPUT_TOKEN, | 38 BAD_INPUT_TOKEN, |
| 39 COMMA_TOKEN, | 39 COMMA_TOKEN, |
| 40 DOUBLE_TOKEN, | 40 DOUBLE_TOKEN, |
| 41 EOF_TOKEN, | 41 EOF_TOKEN, |
| 42 EQ_TOKEN, | 42 EQ_TOKEN, |
| 43 FUNCTION_TOKEN, | 43 FUNCTION_TOKEN, |
| 44 GT_TOKEN, | |
| 45 GT_GT_TOKEN, | |
| 44 HASH_TOKEN, | 46 HASH_TOKEN, |
| 45 HEXADECIMAL_TOKEN, | 47 HEXADECIMAL_TOKEN, |
| 46 IDENTIFIER_TOKEN, | 48 IDENTIFIER_TOKEN, |
| 47 INT_TOKEN, | 49 INT_TOKEN, |
| 48 KEYWORD_TOKEN, | 50 KEYWORD_TOKEN, |
| 49 LT_TOKEN, | 51 LT_TOKEN, |
| 50 OPEN_CURLY_BRACKET_TOKEN, | 52 OPEN_CURLY_BRACKET_TOKEN, |
| 51 OPEN_PAREN_TOKEN, | 53 OPEN_PAREN_TOKEN, |
| 52 OPEN_SQUARE_BRACKET_TOKEN, | 54 OPEN_SQUARE_BRACKET_TOKEN, |
| 53 PERIOD_TOKEN, | 55 PERIOD_TOKEN, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 * matches, "star" means zero or more matches. For example, | 98 * matches, "star" means zero or more matches. For example, |
| 97 * [parseMetadataStar] corresponds to this grammar snippet: [: | 99 * [parseMetadataStar] corresponds to this grammar snippet: [: |
| 98 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. | 100 * metadata* :], and [parseTypeOpt] corresponds to: [: type? :]. |
| 99 */ | 101 */ |
| 100 class Parser { | 102 class Parser { |
| 101 final Listener listener; | 103 final Listener listener; |
| 102 final ParserOptions parserOptions; | 104 final ParserOptions parserOptions; |
| 103 bool mayParseFunctionExpressions = true; | 105 bool mayParseFunctionExpressions = true; |
| 104 bool asyncAwaitKeywordsEnabled; | 106 bool asyncAwaitKeywordsEnabled; |
| 105 | 107 |
| 106 Parser(this.listener, this.parserOptions, | 108 final bool enableGenericMethodSyntax; |
| 107 {this.asyncAwaitKeywordsEnabled: false}); | 109 |
| 110 Parser(this.listener, ParserOptions parserOptions, | |
| 111 {this.asyncAwaitKeywordsEnabled: false}) : | |
| 112 parserOptions = parserOptions, | |
| 113 enableGenericMethodSyntax = parserOptions.enableGenericMethodSyntax; | |
| 108 | 114 |
| 109 Token parseUnit(Token token) { | 115 Token parseUnit(Token token) { |
| 110 listener.beginCompilationUnit(token); | 116 listener.beginCompilationUnit(token); |
| 111 int count = 0; | 117 int count = 0; |
| 112 while (!identical(token.kind, EOF_TOKEN)) { | 118 while (!identical(token.kind, EOF_TOKEN)) { |
| 113 token = parseTopLevelDeclaration(token); | 119 token = parseTopLevelDeclaration(token); |
| 114 listener.endTopLevelDeclaration(token); | 120 listener.endTopLevelDeclaration(token); |
| 115 count++; | 121 count++; |
| 116 } | 122 } |
| 117 listener.endCompilationUnit(count, token); | 123 listener.endCompilationUnit(count, token); |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 if (identical(kind, KEYWORD_TOKEN)) { | 524 if (identical(kind, KEYWORD_TOKEN)) { |
| 519 Keyword keyword = (token as KeywordToken).keyword; | 525 Keyword keyword = (token as KeywordToken).keyword; |
| 520 String value = keyword.syntax; | 526 String value = keyword.syntax; |
| 521 return keyword.isPseudo | 527 return keyword.isPseudo |
| 522 || (identical(value, 'dynamic')) | 528 || (identical(value, 'dynamic')) |
| 523 || (identical(value, 'void')); | 529 || (identical(value, 'void')); |
| 524 } | 530 } |
| 525 return false; | 531 return false; |
| 526 } | 532 } |
| 527 | 533 |
| 534 /// Returns true if [token] matches '<' type (',' type)* '>' '(', and | |
| 535 /// otherwise returns false. The final '(' is not part of the grammar | |
| 536 /// construct `typeArguments`, but it is required here such that type | |
| 537 /// arguments in generic method invocations can be recognized, and as few as | |
| 538 /// possible other constructs will pass (e.g., 'a < C, D > 3'). | |
| 539 bool isValidMethodTypeArguments(Token token) { | |
| 540 return tryParseMethodTypeArguments(token) != null; | |
| 541 } | |
| 542 | |
| 543 /// Returns token after match if [token] matches '<' type (',' type)* '>' '(', | |
| 544 /// and otherwise returns null. Does not produce listener events. With respect | |
| 545 /// to the final '(', please see the description of | |
| 546 /// [isValidMethodTypeArguments]. | |
| 547 Token tryParseMethodTypeArguments(Token token) { | |
| 548 if (!identical(token.kind, LT_TOKEN)) return null; | |
| 549 BeginGroupToken beginToken = token; | |
| 550 Token endToken = beginToken.endGroup; | |
| 551 if (endToken == null || | |
| 552 !identical(endToken.next.kind, OPEN_PAREN_TOKEN)) return null; | |
|
Johnni Winther
2016/04/11 12:41:00
Nit: Add braces arround `return null;`
eernst
2016/04/11 12:55:30
Done.
| |
| 553 token = tryParseType(token.next); | |
| 554 while (token != null && identical(token.kind, COMMA_TOKEN)) { | |
| 555 token = tryParseType(token.next); | |
| 556 } | |
| 557 if (token == null || !identical(token.kind, GT_TOKEN)) return null; | |
| 558 return token.next; | |
| 559 } | |
| 560 | |
| 561 /// Returns token after match if [token] matches typeName typeArguments?, and | |
| 562 /// otherwise returns null. Does not produce listener events. | |
| 563 Token tryParseType(Token token) { | |
| 564 token = tryParseQualified(token); | |
| 565 if (token == null) return null; | |
| 566 Token tokenAfterQualified = token; | |
| 567 token = tryParseNestedTypeArguments(token); | |
| 568 return token == null ? tokenAfterQualified : token; | |
| 569 } | |
| 570 | |
| 571 /// Returns token after match if [token] matches identifier ('.' identifier)?, | |
| 572 /// and otherwise returns null. Does not produce listener events. | |
| 573 Token tryParseQualified(Token token) { | |
| 574 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; | |
| 575 token = token.next; | |
| 576 if (!identical(token.kind, PERIOD_TOKEN)) return token; | |
| 577 token = token.next; | |
| 578 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; | |
| 579 return token.next; | |
| 580 } | |
| 581 | |
| 582 /// Returns token after match if [token] matches '<' type (',' type)* '>', | |
| 583 /// and otherwise returns null. Does not produce listener events. The final | |
| 584 /// '>' may be the first character in a '>>' token, in which case a synthetic | |
| 585 /// '>' token is created and returned, representing the second '>' in the | |
| 586 /// '>>' token. | |
| 587 Token tryParseNestedTypeArguments(Token token) { | |
| 588 if (!identical(token.kind, LT_TOKEN)) return null; | |
| 589 // If the initial '<' matches the first '>' in a '>>' token, we will have | |
| 590 // `token.endGroup == null`, so we cannot rely on `token.endGroup == null` | |
| 591 // to imply that the match must fail. Hence no `token.endGroup == null` | |
| 592 // test here. | |
| 593 token = tryParseType(token.next); | |
| 594 while (token != null && identical(token.kind, COMMA_TOKEN)) { | |
| 595 token = tryParseType(token.next); | |
| 596 } | |
| 597 if (token == null) return null; | |
| 598 if (identical(token.kind, GT_TOKEN)) return token.next; | |
| 599 if (!identical(token.kind, GT_GT_TOKEN)) return null; | |
| 600 // [token] is '>>' of which the final '>' that we are parsing is the first | |
| 601 // character. In order to keep the parsing process on track we must return | |
| 602 // a synthetic '>' corresponding to the second character of that '>>'. | |
| 603 Token syntheticToken = new SymbolToken(GT_INFO, token.charOffset + 1); | |
| 604 syntheticToken.next = token.next; | |
| 605 return syntheticToken; | |
| 606 } | |
| 607 | |
| 528 Token parseQualified(Token token) { | 608 Token parseQualified(Token token) { |
| 529 token = parseIdentifier(token); | 609 token = parseIdentifier(token); |
| 530 while (optional('.', token)) { | 610 while (optional('.', token)) { |
| 531 token = parseQualifiedRest(token); | 611 token = parseQualifiedRest(token); |
| 532 } | 612 } |
| 533 return token; | 613 return token; |
| 534 } | 614 } |
| 535 | 615 |
| 536 Token parseQualifiedRestOpt(Token token) { | 616 Token parseQualifiedRestOpt(Token token) { |
| 537 if (optional('.', token)) { | 617 if (optional('.', token)) { |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 listener.handleModifiers(0); | 1084 listener.handleModifiers(0); |
| 1005 } | 1085 } |
| 1006 | 1086 |
| 1007 if (type == null) { | 1087 if (type == null) { |
| 1008 listener.handleNoType(name); | 1088 listener.handleNoType(name); |
| 1009 } else { | 1089 } else { |
| 1010 parseReturnTypeOpt(type); | 1090 parseReturnTypeOpt(type); |
| 1011 } | 1091 } |
| 1012 Token token = parseIdentifier(name); | 1092 Token token = parseIdentifier(name); |
| 1013 | 1093 |
| 1094 if (enableGenericMethodSyntax && getOrSet == null) { | |
| 1095 token = parseTypeVariablesOpt(token); | |
| 1096 } else { | |
| 1097 listener.handleNoTypeVariables(token); | |
| 1098 } | |
| 1014 token = parseFormalParametersOpt(token); | 1099 token = parseFormalParametersOpt(token); |
| 1015 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1100 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1016 token = parseAsyncModifier(token); | 1101 token = parseAsyncModifier(token); |
| 1017 token = parseFunctionBody(token, false, externalModifier != null); | 1102 token = parseFunctionBody(token, false, externalModifier != null); |
| 1018 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1103 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1019 Token endToken = token; | 1104 Token endToken = token; |
| 1020 token = token.next; | 1105 token = token.next; |
| 1021 if (token.kind == BAD_INPUT_TOKEN) { | 1106 if (token.kind == BAD_INPUT_TOKEN) { |
| 1022 token = listener.unexpected(token); | 1107 token = listener.unexpected(token); |
| 1023 } | 1108 } |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1312 } | 1397 } |
| 1313 } | 1398 } |
| 1314 | 1399 |
| 1315 token = afterName; | 1400 token = afterName; |
| 1316 bool isField; | 1401 bool isField; |
| 1317 while (true) { | 1402 while (true) { |
| 1318 // Loop to allow the listener to rewrite the token stream for | 1403 // Loop to allow the listener to rewrite the token stream for |
| 1319 // error handling. | 1404 // error handling. |
| 1320 final String value = token.stringValue; | 1405 final String value = token.stringValue; |
| 1321 if ((identical(value, '(')) || (identical(value, '.')) | 1406 if ((identical(value, '(')) || (identical(value, '.')) |
| 1322 || (identical(value, '{')) || (identical(value, '=>'))) { | 1407 || (identical(value, '{')) || (identical(value, '=>')) |
| 1408 || (enableGenericMethodSyntax && identical(value, '<'))) { | |
| 1323 isField = false; | 1409 isField = false; |
| 1324 break; | 1410 break; |
| 1325 } else if (identical(value, ';')) { | 1411 } else if (identical(value, ';')) { |
| 1326 if (getOrSet != null) { | 1412 if (getOrSet != null) { |
| 1327 // If we found a "get" keyword, this must be an abstract | 1413 // If we found a "get" keyword, this must be an abstract |
| 1328 // getter. | 1414 // getter. |
| 1329 isField = (!identical(getOrSet.stringValue, 'get')); | 1415 isField = (!identical(getOrSet.stringValue, 'get')); |
| 1330 // TODO(ahe): This feels like a hack. | 1416 // TODO(ahe): This feels like a hack. |
| 1331 } else { | 1417 } else { |
| 1332 isField = true; | 1418 isField = true; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1413 if (staticModifier != null) { | 1499 if (staticModifier != null) { |
| 1414 listener.reportError( | 1500 listener.reportError( |
| 1415 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, | 1501 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, |
| 1416 {'modifier': staticModifier}); | 1502 {'modifier': staticModifier}); |
| 1417 } | 1503 } |
| 1418 } else { | 1504 } else { |
| 1419 token = parseIdentifier(name); | 1505 token = parseIdentifier(name); |
| 1420 } | 1506 } |
| 1421 | 1507 |
| 1422 token = parseQualifiedRestOpt(token); | 1508 token = parseQualifiedRestOpt(token); |
| 1509 if (enableGenericMethodSyntax && getOrSet == null) { | |
| 1510 token = parseTypeVariablesOpt(token); | |
| 1511 } else { | |
| 1512 listener.handleNoTypeVariables(token); | |
| 1513 } | |
| 1423 token = parseFormalParametersOpt(token); | 1514 token = parseFormalParametersOpt(token); |
| 1424 token = parseInitializersOpt(token); | 1515 token = parseInitializersOpt(token); |
| 1425 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1516 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1426 token = parseAsyncModifier(token); | 1517 token = parseAsyncModifier(token); |
| 1427 if (optional('=', token)) { | 1518 if (optional('=', token)) { |
| 1428 token = parseRedirectingFactoryBody(token); | 1519 token = parseRedirectingFactoryBody(token); |
| 1429 } else { | 1520 } else { |
| 1430 token = parseFunctionBody( | 1521 token = parseFunctionBody( |
| 1431 token, false, staticModifier == null || externalModifier != null); | 1522 token, false, staticModifier == null || externalModifier != null); |
| 1432 } | 1523 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1499 } | 1590 } |
| 1500 listener.beginFunctionName(token); | 1591 listener.beginFunctionName(token); |
| 1501 if (optional('operator', token)) { | 1592 if (optional('operator', token)) { |
| 1502 token = parseOperatorName(token); | 1593 token = parseOperatorName(token); |
| 1503 } else { | 1594 } else { |
| 1504 token = parseIdentifier(token); | 1595 token = parseIdentifier(token); |
| 1505 } | 1596 } |
| 1506 } | 1597 } |
| 1507 token = parseQualifiedRestOpt(token); | 1598 token = parseQualifiedRestOpt(token); |
| 1508 listener.endFunctionName(token); | 1599 listener.endFunctionName(token); |
| 1600 if (enableGenericMethodSyntax && getOrSet == null) { | |
| 1601 token = parseTypeVariablesOpt(token); | |
| 1602 } else { | |
| 1603 listener.handleNoTypeVariables(token); | |
| 1604 } | |
| 1509 token = parseFormalParametersOpt(token); | 1605 token = parseFormalParametersOpt(token); |
| 1510 token = parseInitializersOpt(token); | 1606 token = parseInitializersOpt(token); |
| 1511 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1607 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1512 token = parseAsyncModifier(token); | 1608 token = parseAsyncModifier(token); |
| 1513 if (optional('=', token)) { | 1609 if (optional('=', token)) { |
| 1514 token = parseRedirectingFactoryBody(token); | 1610 token = parseRedirectingFactoryBody(token); |
| 1515 } else { | 1611 } else { |
| 1516 token = parseFunctionBody(token, false, true); | 1612 token = parseFunctionBody(token, false, true); |
| 1517 } | 1613 } |
| 1518 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1614 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1539 return token; | 1635 return token; |
| 1540 } | 1636 } |
| 1541 | 1637 |
| 1542 Token parseFunctionExpression(Token token) { | 1638 Token parseFunctionExpression(Token token) { |
| 1543 listener.beginFunction(token); | 1639 listener.beginFunction(token); |
| 1544 listener.handleModifiers(0); | 1640 listener.handleModifiers(0); |
| 1545 token = parseReturnTypeOpt(token); | 1641 token = parseReturnTypeOpt(token); |
| 1546 listener.beginFunctionName(token); | 1642 listener.beginFunctionName(token); |
| 1547 token = parseIdentifier(token); | 1643 token = parseIdentifier(token); |
| 1548 listener.endFunctionName(token); | 1644 listener.endFunctionName(token); |
| 1645 if (enableGenericMethodSyntax) { | |
| 1646 token = parseTypeVariablesOpt(token); | |
| 1647 } else { | |
| 1648 listener.handleNoTypeVariables(token); | |
| 1649 } | |
| 1549 token = parseFormalParameters(token); | 1650 token = parseFormalParameters(token); |
| 1550 listener.handleNoInitializers(); | 1651 listener.handleNoInitializers(); |
| 1551 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1652 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1552 token = parseAsyncModifier(token); | 1653 token = parseAsyncModifier(token); |
| 1553 bool isBlock = optional('{', token); | 1654 bool isBlock = optional('{', token); |
| 1554 token = parseFunctionBody(token, true, false); | 1655 token = parseFunctionBody(token, true, false); |
| 1555 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1656 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1556 listener.endFunction(null, token); | 1657 listener.endFunction(null, token); |
| 1557 return isBlock ? token.next : token; | 1658 return isBlock ? token.next : token; |
| 1558 } | 1659 } |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2004 while (true) { | 2105 while (true) { |
| 2005 if (optional('[', token)) { | 2106 if (optional('[', token)) { |
| 2006 Token openSquareBracket = token; | 2107 Token openSquareBracket = token; |
| 2007 bool old = mayParseFunctionExpressions; | 2108 bool old = mayParseFunctionExpressions; |
| 2008 mayParseFunctionExpressions = true; | 2109 mayParseFunctionExpressions = true; |
| 2009 token = parseExpression(token.next); | 2110 token = parseExpression(token.next); |
| 2010 mayParseFunctionExpressions = old; | 2111 mayParseFunctionExpressions = old; |
| 2011 listener.handleIndexedExpression(openSquareBracket, token); | 2112 listener.handleIndexedExpression(openSquareBracket, token); |
| 2012 token = expect(']', token); | 2113 token = expect(']', token); |
| 2013 } else if (optional('(', token)) { | 2114 } else if (optional('(', token)) { |
| 2115 listener.handleNoTypeArguments(token); | |
| 2014 token = parseArguments(token); | 2116 token = parseArguments(token); |
| 2015 listener.endSend(token); | 2117 listener.endSend(token); |
| 2016 } else { | 2118 } else { |
| 2017 break; | 2119 break; |
| 2018 } | 2120 } |
| 2019 } | 2121 } |
| 2020 return token; | 2122 return token; |
| 2021 } | 2123 } |
| 2022 | 2124 |
| 2023 Token parsePrimary(Token token) { | 2125 Token parsePrimary(Token token) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2101 } | 2203 } |
| 2102 listener.handleParenthesizedExpression(begin); | 2204 listener.handleParenthesizedExpression(begin); |
| 2103 return expect(')', token); | 2205 return expect(')', token); |
| 2104 } | 2206 } |
| 2105 | 2207 |
| 2106 Token parseThisExpression(Token token) { | 2208 Token parseThisExpression(Token token) { |
| 2107 listener.handleThisExpression(token); | 2209 listener.handleThisExpression(token); |
| 2108 token = token.next; | 2210 token = token.next; |
| 2109 if (optional('(', token)) { | 2211 if (optional('(', token)) { |
| 2110 // Constructor forwarding. | 2212 // Constructor forwarding. |
| 2213 listener.handleNoTypeArguments(token); | |
| 2111 token = parseArguments(token); | 2214 token = parseArguments(token); |
| 2112 listener.endSend(token); | 2215 listener.endSend(token); |
| 2113 } | 2216 } |
| 2114 return token; | 2217 return token; |
| 2115 } | 2218 } |
| 2116 | 2219 |
| 2117 Token parseSuperExpression(Token token) { | 2220 Token parseSuperExpression(Token token) { |
| 2118 listener.handleSuperExpression(token); | 2221 listener.handleSuperExpression(token); |
| 2119 token = token.next; | 2222 token = token.next; |
| 2120 if (optional('(', token)) { | 2223 if (optional('(', token)) { |
| 2121 // Super constructor. | 2224 // Super constructor. |
| 2225 listener.handleNoTypeArguments(token); | |
| 2122 token = parseArguments(token); | 2226 token = parseArguments(token); |
| 2123 listener.endSend(token); | 2227 listener.endSend(token); |
| 2124 } | 2228 } |
| 2125 return token; | 2229 return token; |
| 2126 } | 2230 } |
| 2127 | 2231 |
| 2128 Token parseLiteralListOrMap(Token token) { | 2232 Token parseLiteralListOrMap(Token token) { |
| 2129 Token constKeyword = null; | 2233 Token constKeyword = null; |
| 2130 if (optional('const', token)) { | 2234 if (optional('const', token)) { |
| 2131 constKeyword = token; | 2235 constKeyword = token; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2328 } | 2432 } |
| 2329 | 2433 |
| 2330 Token parseLiteralNull(Token token) { | 2434 Token parseLiteralNull(Token token) { |
| 2331 listener.handleLiteralNull(token); | 2435 listener.handleLiteralNull(token); |
| 2332 return token.next; | 2436 return token.next; |
| 2333 } | 2437 } |
| 2334 | 2438 |
| 2335 Token parseSend(Token token) { | 2439 Token parseSend(Token token) { |
| 2336 listener.beginSend(token); | 2440 listener.beginSend(token); |
| 2337 token = parseIdentifier(token); | 2441 token = parseIdentifier(token); |
| 2442 if (enableGenericMethodSyntax && isValidMethodTypeArguments(token)) { | |
| 2443 token = parseTypeArgumentsOpt(token); | |
| 2444 } else { | |
| 2445 listener.handleNoTypeArguments(token); | |
| 2446 } | |
| 2338 token = parseArgumentsOpt(token); | 2447 token = parseArgumentsOpt(token); |
| 2339 listener.endSend(token); | 2448 listener.endSend(token); |
| 2340 return token; | 2449 return token; |
| 2341 } | 2450 } |
| 2342 | 2451 |
| 2343 Token parseArgumentsOpt(Token token) { | 2452 Token parseArgumentsOpt(Token token) { |
| 2344 if (!optional('(', token)) { | 2453 if (!optional('(', token)) { |
| 2345 listener.handleNoArguments(token); | 2454 listener.handleNoArguments(token); |
| 2346 return token; | 2455 return token; |
| 2347 } else { | 2456 } else { |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2779 } | 2888 } |
| 2780 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2889 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 2781 return expectSemicolon(token); | 2890 return expectSemicolon(token); |
| 2782 } | 2891 } |
| 2783 | 2892 |
| 2784 Token parseEmptyStatement(Token token) { | 2893 Token parseEmptyStatement(Token token) { |
| 2785 listener.handleEmptyStatement(token); | 2894 listener.handleEmptyStatement(token); |
| 2786 return expectSemicolon(token); | 2895 return expectSemicolon(token); |
| 2787 } | 2896 } |
| 2788 } | 2897 } |
| OLD | NEW |