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; |
|
ahe
2016/04/08 09:53:33
Please avoid private fields, a subclass outside th
eernst
2016/04/08 17:07:10
I'm not sure what the right approach would be here
| |
| 107 {this.asyncAwaitKeywordsEnabled: false}); | 109 |
| 110 Parser(this.listener, ParserOptions _parserOptions, | |
|
ahe
2016/04/08 09:53:32
Remove _ from parameter.
eernst
2016/04/08 17:07:10
Done.
| |
| 111 {this.asyncAwaitKeywordsEnabled: false}) : | |
| 112 parserOptions = _parserOptions, | |
|
ahe
2016/04/08 09:53:32
In:
parserOption = parserOptions
The left-hand
eernst
2016/04/08 17:07:10
Acknowledged.
| |
| 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 /// Checks for '<' type (',' type)* '>', returns null iff failing. | |
|
ahe
2016/04/08 09:53:32
Avoid using academic short-hand and notation in do
ahe
2016/04/08 09:53:33
How about:
Returns next token after match token i
eernst
2016/04/08 17:07:10
Done.
| |
| 535 /// Does not produce listener events. In this case the final '>' may be | |
| 536 /// the first character in a '>>' token, in which case the `endGroup` of | |
| 537 /// the initial '<' will be null, so we cannot rely on `endGroup`. | |
| 538 Token tryParseTypeArgumentsNested(Token token) { | |
|
ahe
2016/04/08 09:53:32
Below I question if this method is necessary. Howe
eernst
2016/04/08 17:07:10
The old (abandoned) CL did express the same distin
| |
| 539 final kind = token.kind; | |
|
ahe
2016/04/08 09:53:33
Remove this variable. It's confusing that token is
eernst
2016/04/08 17:07:11
Done.
| |
| 540 if (!identical(kind, LT_TOKEN)) return null; | |
| 541 token = token.next; | |
| 542 if (token == null) return null; | |
| 543 token = tryParseType(token); | |
| 544 while (token != null && identical(token.kind, COMMA_TOKEN)) { | |
| 545 token = token.next; | |
| 546 if (token == null) return null; | |
| 547 token = tryParseType(token); | |
| 548 } | |
| 549 if (token == null) return null; | |
| 550 if (identical(token.kind, GT_TOKEN)) return token.next; | |
| 551 if (!identical(token.kind, GT_GT_TOKEN)) return null; | |
| 552 // [token] is '>>' of which the final '>' that we are parsing is the first | |
| 553 // character. In order to keep the parsing process on track we must return | |
| 554 // a synthetic '>' corresponding to the second character of that '>>'. | |
| 555 Token syntheticToken = new SymbolToken(GT_INFO, token.charOffset + 1); | |
| 556 syntheticToken.next = token.next; | |
| 557 return syntheticToken; | |
| 558 } | |
| 559 | |
| 560 /// Checks for identifier ('.' identifier)?, returns null iff failing. | |
|
ahe
2016/04/08 09:53:33
iff -> if.
What does "failing" mean? How about:
eernst
2016/04/08 17:07:10
Rephrased in a similar manner as several earlier d
| |
| 561 /// Does not produce listener events. | |
| 562 Token tryParseQualified(Token token) { | |
|
ahe
2016/04/08 09:53:32
There's probably suboptimal error recovery here. F
eernst
2016/04/08 17:07:10
It would be nice if they _could_ do that. ;)
For
| |
| 563 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; | |
| 564 token = token.next; | |
| 565 if (!identical(token.kind, PERIOD_TOKEN)) return token; | |
| 566 token = token.next; | |
| 567 if (!identical(token.kind, IDENTIFIER_TOKEN)) return null; | |
| 568 return token.next; | |
| 569 } | |
| 570 | |
| 571 /// Checks for typeName typeArguments? and returns null iff failing. | |
|
ahe
2016/04/08 09:53:32
iff -> if, but what about:
Returns next token aft
eernst
2016/04/08 17:07:11
Rephrased in a similar manner as several earlier d
| |
| 572 /// Does not produce listener events. | |
| 573 Token tryParseType(Token token) { | |
| 574 token = tryParseQualified(token); | |
| 575 if (token == null) return null; | |
| 576 Token tokenAfterQualified = token; | |
| 577 token = tryParseTypeArgumentsNested(token); | |
| 578 return token == null ? tokenAfterQualified : token; | |
| 579 } | |
| 580 | |
| 581 /// Checks for '<' type (',' type)* '>' '(' and returns null iff failing. | |
|
ahe
2016/04/08 09:53:33
iff -> if, but what about:
Returns last token of
eernst
2016/04/08 17:07:10
Rephrased in a similar manner as several earlier d
| |
| 582 /// Does not produce listener events. With respect to the final '(', please | |
| 583 /// see the description of [isValidTypeArguments]. | |
| 584 Token tryParseTypeArguments(Token token) { | |
| 585 final kind = token.kind; | |
| 586 if (!identical(kind, LT_TOKEN)) return null; | |
| 587 BeginGroupToken beginToken = token; | |
| 588 Token endToken = beginToken.endGroup; | |
| 589 token = token.next; | |
| 590 if (token == null || endToken == null || | |
| 591 !identical(endToken.next?.kind, OPEN_PAREN_TOKEN)) return null; | |
| 592 token = tryParseType(token); | |
|
ahe
2016/04/08 09:53:32
Is this really necessary? If so, perhaps push back
| |
| 593 while (token != null && identical(token.kind, COMMA_TOKEN)) { | |
| 594 token = token.next; | |
| 595 if (token == null) return null; | |
| 596 token = tryParseType(token); | |
| 597 } | |
| 598 if (!identical(token?.kind, GT_TOKEN)) return null; | |
| 599 return token.next; | |
| 600 } | |
| 601 | |
| 602 /// Returns true iff the tokens starting from [token] match | |
|
ahe
2016/04/08 09:53:32
iff->if.
We normally emit "otherwise returns fals
eernst
2016/04/08 17:07:10
Rephrased in a similar manner as several earlier d
| |
| 603 /// '<' type (',' type)* '>' '('. The final '(' is not part of the | |
| 604 /// grammar construct `typeArguments`, but it is required here such that | |
| 605 /// type arguments in generic method invocations can be recognized, and | |
| 606 /// as few as possible other constructs will pass (e.g., 'a < C, D > 3'). | |
| 607 bool isValidTypeArguments(Token token) { | |
|
ahe
2016/04/08 09:53:32
Rename to "isValidMethodTypeArguments" to signal t
eernst
2016/04/08 17:07:10
Makes sense, done. (This deviates from the naming
floitsch
2016/04/11 11:00:13
Fwiw, this CL only adds syntactic support. The sem
| |
| 608 return tryParseTypeArguments(token) != null; | |
| 609 } | |
|
ahe
2016/04/08 09:53:32
Please reverse the order of all these methods. It'
eernst
2016/04/08 17:07:10
Ah, that's funny. The literate programming credo (
| |
| 610 | |
| 528 Token parseQualified(Token token) { | 611 Token parseQualified(Token token) { |
| 529 token = parseIdentifier(token); | 612 token = parseIdentifier(token); |
| 530 while (optional('.', token)) { | 613 while (optional('.', token)) { |
| 531 token = parseQualifiedRest(token); | 614 token = parseQualifiedRest(token); |
| 532 } | 615 } |
| 533 return token; | 616 return token; |
| 534 } | 617 } |
| 535 | 618 |
| 536 Token parseQualifiedRestOpt(Token token) { | 619 Token parseQualifiedRestOpt(Token token) { |
| 537 if (optional('.', token)) { | 620 if (optional('.', token)) { |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 listener.handleModifiers(0); | 1087 listener.handleModifiers(0); |
| 1005 } | 1088 } |
| 1006 | 1089 |
| 1007 if (type == null) { | 1090 if (type == null) { |
| 1008 listener.handleNoType(name); | 1091 listener.handleNoType(name); |
| 1009 } else { | 1092 } else { |
| 1010 parseReturnTypeOpt(type); | 1093 parseReturnTypeOpt(type); |
| 1011 } | 1094 } |
| 1012 Token token = parseIdentifier(name); | 1095 Token token = parseIdentifier(name); |
| 1013 | 1096 |
| 1097 if (_enableGenericMethodSyntax && getOrSet == null) { | |
| 1098 token = parseTypeVariablesOpt(token); | |
| 1099 } else { | |
| 1100 listener.handleNoTypeVariables(token); | |
| 1101 } | |
| 1014 token = parseFormalParametersOpt(token); | 1102 token = parseFormalParametersOpt(token); |
| 1015 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1103 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1016 token = parseAsyncModifier(token); | 1104 token = parseAsyncModifier(token); |
| 1017 token = parseFunctionBody(token, false, externalModifier != null); | 1105 token = parseFunctionBody(token, false, externalModifier != null); |
| 1018 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1106 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1019 Token endToken = token; | 1107 Token endToken = token; |
| 1020 token = token.next; | 1108 token = token.next; |
| 1021 if (token.kind == BAD_INPUT_TOKEN) { | 1109 if (token.kind == BAD_INPUT_TOKEN) { |
| 1022 token = listener.unexpected(token); | 1110 token = listener.unexpected(token); |
| 1023 } | 1111 } |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1312 } | 1400 } |
| 1313 } | 1401 } |
| 1314 | 1402 |
| 1315 token = afterName; | 1403 token = afterName; |
| 1316 bool isField; | 1404 bool isField; |
| 1317 while (true) { | 1405 while (true) { |
| 1318 // Loop to allow the listener to rewrite the token stream for | 1406 // Loop to allow the listener to rewrite the token stream for |
| 1319 // error handling. | 1407 // error handling. |
| 1320 final String value = token.stringValue; | 1408 final String value = token.stringValue; |
| 1321 if ((identical(value, '(')) || (identical(value, '.')) | 1409 if ((identical(value, '(')) || (identical(value, '.')) |
| 1322 || (identical(value, '{')) || (identical(value, '=>'))) { | 1410 || (identical(value, '{')) || (identical(value, '=>')) |
| 1411 || (_enableGenericMethodSyntax && identical(value, '<'))) { | |
| 1323 isField = false; | 1412 isField = false; |
| 1324 break; | 1413 break; |
| 1325 } else if (identical(value, ';')) { | 1414 } else if (identical(value, ';')) { |
| 1326 if (getOrSet != null) { | 1415 if (getOrSet != null) { |
| 1327 // If we found a "get" keyword, this must be an abstract | 1416 // If we found a "get" keyword, this must be an abstract |
| 1328 // getter. | 1417 // getter. |
| 1329 isField = (!identical(getOrSet.stringValue, 'get')); | 1418 isField = (!identical(getOrSet.stringValue, 'get')); |
| 1330 // TODO(ahe): This feels like a hack. | 1419 // TODO(ahe): This feels like a hack. |
| 1331 } else { | 1420 } else { |
| 1332 isField = true; | 1421 isField = true; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1413 if (staticModifier != null) { | 1502 if (staticModifier != null) { |
| 1414 listener.reportError( | 1503 listener.reportError( |
| 1415 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, | 1504 staticModifier, MessageKind.EXTRANEOUS_MODIFIER, |
| 1416 {'modifier': staticModifier}); | 1505 {'modifier': staticModifier}); |
| 1417 } | 1506 } |
| 1418 } else { | 1507 } else { |
| 1419 token = parseIdentifier(name); | 1508 token = parseIdentifier(name); |
| 1420 } | 1509 } |
| 1421 | 1510 |
| 1422 token = parseQualifiedRestOpt(token); | 1511 token = parseQualifiedRestOpt(token); |
| 1512 if (_enableGenericMethodSyntax && getOrSet == null) { | |
| 1513 token = parseTypeVariablesOpt(token); | |
| 1514 } else { | |
| 1515 listener.handleNoTypeVariables(token); | |
| 1516 } | |
| 1423 token = parseFormalParametersOpt(token); | 1517 token = parseFormalParametersOpt(token); |
| 1424 token = parseInitializersOpt(token); | 1518 token = parseInitializersOpt(token); |
| 1425 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1519 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1426 token = parseAsyncModifier(token); | 1520 token = parseAsyncModifier(token); |
| 1427 if (optional('=', token)) { | 1521 if (optional('=', token)) { |
| 1428 token = parseRedirectingFactoryBody(token); | 1522 token = parseRedirectingFactoryBody(token); |
| 1429 } else { | 1523 } else { |
| 1430 token = parseFunctionBody( | 1524 token = parseFunctionBody( |
| 1431 token, false, staticModifier == null || externalModifier != null); | 1525 token, false, staticModifier == null || externalModifier != null); |
| 1432 } | 1526 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1499 } | 1593 } |
| 1500 listener.beginFunctionName(token); | 1594 listener.beginFunctionName(token); |
| 1501 if (optional('operator', token)) { | 1595 if (optional('operator', token)) { |
| 1502 token = parseOperatorName(token); | 1596 token = parseOperatorName(token); |
| 1503 } else { | 1597 } else { |
| 1504 token = parseIdentifier(token); | 1598 token = parseIdentifier(token); |
| 1505 } | 1599 } |
| 1506 } | 1600 } |
| 1507 token = parseQualifiedRestOpt(token); | 1601 token = parseQualifiedRestOpt(token); |
| 1508 listener.endFunctionName(token); | 1602 listener.endFunctionName(token); |
| 1603 if (_enableGenericMethodSyntax && getOrSet == null) { | |
| 1604 token = parseTypeVariablesOpt(token); | |
| 1605 } else { | |
| 1606 listener.handleNoTypeVariables(token); | |
| 1607 } | |
| 1509 token = parseFormalParametersOpt(token); | 1608 token = parseFormalParametersOpt(token); |
| 1510 token = parseInitializersOpt(token); | 1609 token = parseInitializersOpt(token); |
| 1511 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1610 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1512 token = parseAsyncModifier(token); | 1611 token = parseAsyncModifier(token); |
| 1513 if (optional('=', token)) { | 1612 if (optional('=', token)) { |
| 1514 token = parseRedirectingFactoryBody(token); | 1613 token = parseRedirectingFactoryBody(token); |
| 1515 } else { | 1614 } else { |
| 1516 token = parseFunctionBody(token, false, true); | 1615 token = parseFunctionBody(token, false, true); |
| 1517 } | 1616 } |
| 1518 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1617 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1539 return token; | 1638 return token; |
| 1540 } | 1639 } |
| 1541 | 1640 |
| 1542 Token parseFunctionExpression(Token token) { | 1641 Token parseFunctionExpression(Token token) { |
| 1543 listener.beginFunction(token); | 1642 listener.beginFunction(token); |
| 1544 listener.handleModifiers(0); | 1643 listener.handleModifiers(0); |
| 1545 token = parseReturnTypeOpt(token); | 1644 token = parseReturnTypeOpt(token); |
| 1546 listener.beginFunctionName(token); | 1645 listener.beginFunctionName(token); |
| 1547 token = parseIdentifier(token); | 1646 token = parseIdentifier(token); |
| 1548 listener.endFunctionName(token); | 1647 listener.endFunctionName(token); |
| 1648 if (_enableGenericMethodSyntax) { | |
| 1649 token = parseTypeVariablesOpt(token); | |
| 1650 } else { | |
| 1651 listener.handleNoTypeVariables(token); | |
| 1652 } | |
| 1549 token = parseFormalParameters(token); | 1653 token = parseFormalParameters(token); |
| 1550 listener.handleNoInitializers(); | 1654 listener.handleNoInitializers(); |
| 1551 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; | 1655 bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled; |
| 1552 token = parseAsyncModifier(token); | 1656 token = parseAsyncModifier(token); |
| 1553 bool isBlock = optional('{', token); | 1657 bool isBlock = optional('{', token); |
| 1554 token = parseFunctionBody(token, true, false); | 1658 token = parseFunctionBody(token, true, false); |
| 1555 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; | 1659 asyncAwaitKeywordsEnabled = previousAsyncAwaitKeywordsEnabled; |
| 1556 listener.endFunction(null, token); | 1660 listener.endFunction(null, token); |
| 1557 return isBlock ? token.next : token; | 1661 return isBlock ? token.next : token; |
| 1558 } | 1662 } |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2004 while (true) { | 2108 while (true) { |
| 2005 if (optional('[', token)) { | 2109 if (optional('[', token)) { |
| 2006 Token openSquareBracket = token; | 2110 Token openSquareBracket = token; |
| 2007 bool old = mayParseFunctionExpressions; | 2111 bool old = mayParseFunctionExpressions; |
| 2008 mayParseFunctionExpressions = true; | 2112 mayParseFunctionExpressions = true; |
| 2009 token = parseExpression(token.next); | 2113 token = parseExpression(token.next); |
| 2010 mayParseFunctionExpressions = old; | 2114 mayParseFunctionExpressions = old; |
| 2011 listener.handleIndexedExpression(openSquareBracket, token); | 2115 listener.handleIndexedExpression(openSquareBracket, token); |
| 2012 token = expect(']', token); | 2116 token = expect(']', token); |
| 2013 } else if (optional('(', token)) { | 2117 } else if (optional('(', token)) { |
| 2118 listener.handleNoTypeArguments(token); | |
| 2014 token = parseArguments(token); | 2119 token = parseArguments(token); |
| 2015 listener.endSend(token); | 2120 listener.endSend(token); |
| 2016 } else { | 2121 } else { |
| 2017 break; | 2122 break; |
| 2018 } | 2123 } |
| 2019 } | 2124 } |
| 2020 return token; | 2125 return token; |
| 2021 } | 2126 } |
| 2022 | 2127 |
| 2023 Token parsePrimary(Token token) { | 2128 Token parsePrimary(Token token) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2101 } | 2206 } |
| 2102 listener.handleParenthesizedExpression(begin); | 2207 listener.handleParenthesizedExpression(begin); |
| 2103 return expect(')', token); | 2208 return expect(')', token); |
| 2104 } | 2209 } |
| 2105 | 2210 |
| 2106 Token parseThisExpression(Token token) { | 2211 Token parseThisExpression(Token token) { |
| 2107 listener.handleThisExpression(token); | 2212 listener.handleThisExpression(token); |
| 2108 token = token.next; | 2213 token = token.next; |
| 2109 if (optional('(', token)) { | 2214 if (optional('(', token)) { |
| 2110 // Constructor forwarding. | 2215 // Constructor forwarding. |
| 2216 listener.handleNoTypeArguments(token); | |
| 2111 token = parseArguments(token); | 2217 token = parseArguments(token); |
| 2112 listener.endSend(token); | 2218 listener.endSend(token); |
| 2113 } | 2219 } |
| 2114 return token; | 2220 return token; |
| 2115 } | 2221 } |
| 2116 | 2222 |
| 2117 Token parseSuperExpression(Token token) { | 2223 Token parseSuperExpression(Token token) { |
| 2118 listener.handleSuperExpression(token); | 2224 listener.handleSuperExpression(token); |
| 2119 token = token.next; | 2225 token = token.next; |
| 2120 if (optional('(', token)) { | 2226 if (optional('(', token)) { |
| 2121 // Super constructor. | 2227 // Super constructor. |
| 2228 listener.handleNoTypeArguments(token); | |
| 2122 token = parseArguments(token); | 2229 token = parseArguments(token); |
| 2123 listener.endSend(token); | 2230 listener.endSend(token); |
| 2124 } | 2231 } |
| 2125 return token; | 2232 return token; |
| 2126 } | 2233 } |
| 2127 | 2234 |
| 2128 Token parseLiteralListOrMap(Token token) { | 2235 Token parseLiteralListOrMap(Token token) { |
| 2129 Token constKeyword = null; | 2236 Token constKeyword = null; |
| 2130 if (optional('const', token)) { | 2237 if (optional('const', token)) { |
| 2131 constKeyword = token; | 2238 constKeyword = token; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2328 } | 2435 } |
| 2329 | 2436 |
| 2330 Token parseLiteralNull(Token token) { | 2437 Token parseLiteralNull(Token token) { |
| 2331 listener.handleLiteralNull(token); | 2438 listener.handleLiteralNull(token); |
| 2332 return token.next; | 2439 return token.next; |
| 2333 } | 2440 } |
| 2334 | 2441 |
| 2335 Token parseSend(Token token) { | 2442 Token parseSend(Token token) { |
| 2336 listener.beginSend(token); | 2443 listener.beginSend(token); |
| 2337 token = parseIdentifier(token); | 2444 token = parseIdentifier(token); |
| 2445 if (_enableGenericMethodSyntax && isValidTypeArguments(token)) { | |
| 2446 token = parseTypeArgumentsOpt(token); | |
| 2447 } else { | |
| 2448 listener.handleNoTypeArguments(token); | |
| 2449 } | |
| 2338 token = parseArgumentsOpt(token); | 2450 token = parseArgumentsOpt(token); |
| 2339 listener.endSend(token); | 2451 listener.endSend(token); |
| 2340 return token; | 2452 return token; |
| 2341 } | 2453 } |
| 2342 | 2454 |
| 2343 Token parseArgumentsOpt(Token token) { | 2455 Token parseArgumentsOpt(Token token) { |
| 2344 if (!optional('(', token)) { | 2456 if (!optional('(', token)) { |
| 2345 listener.handleNoArguments(token); | 2457 listener.handleNoArguments(token); |
| 2346 return token; | 2458 return token; |
| 2347 } else { | 2459 } else { |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2779 } | 2891 } |
| 2780 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2892 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 2781 return expectSemicolon(token); | 2893 return expectSemicolon(token); |
| 2782 } | 2894 } |
| 2783 | 2895 |
| 2784 Token parseEmptyStatement(Token token) { | 2896 Token parseEmptyStatement(Token token) { |
| 2785 listener.handleEmptyStatement(token); | 2897 listener.handleEmptyStatement(token); |
| 2786 return expectSemicolon(token); | 2898 return expectSemicolon(token); |
| 2787 } | 2899 } |
| 2788 } | 2900 } |
| OLD | NEW |