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

Unified Diff: pkg/compiler/lib/src/parser/parser.dart

Issue 1863053003: Adds support for --generic-method-syntax (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Added support for parsing generic methods (buggy, will upload again when fixed) Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/parser/node_listener.dart ('k') | tests/compiler/dart2js/options_helper.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/parser/parser.dart
diff --git a/pkg/compiler/lib/src/parser/parser.dart b/pkg/compiler/lib/src/parser/parser.dart
index 80e6de224e45c5fdb06da3c0743ddd3477add81b..93a696552f27493e427c54a2f4aa00287d7fc62b 100644
--- a/pkg/compiler/lib/src/parser/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -41,6 +41,8 @@ import '../tokens/token_constants.dart' show
EOF_TOKEN,
EQ_TOKEN,
FUNCTION_TOKEN,
+ GT_TOKEN,
+ GT_GT_TOKEN,
HASH_TOKEN,
HEXADECIMAL_TOKEN,
IDENTIFIER_TOKEN,
@@ -103,8 +105,12 @@ class Parser {
bool mayParseFunctionExpressions = true;
bool asyncAwaitKeywordsEnabled;
- Parser(this.listener, this.parserOptions,
- {this.asyncAwaitKeywordsEnabled: false});
+ 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
+
+ Parser(this.listener, ParserOptions _parserOptions,
ahe 2016/04/08 09:53:32 Remove _ from parameter.
eernst 2016/04/08 17:07:10 Done.
+ {this.asyncAwaitKeywordsEnabled: false}) :
+ parserOptions = _parserOptions,
ahe 2016/04/08 09:53:32 In: parserOption = parserOptions The left-hand
eernst 2016/04/08 17:07:10 Acknowledged.
+ _enableGenericMethodSyntax = _parserOptions.enableGenericMethodSyntax;
Token parseUnit(Token token) {
listener.beginCompilationUnit(token);
@@ -525,6 +531,83 @@ class Parser {
return false;
}
+ /// 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.
+ /// Does not produce listener events. In this case the final '>' may be
+ /// the first character in a '>>' token, in which case the `endGroup` of
+ /// the initial '<' will be null, so we cannot rely on `endGroup`.
+ 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
+ 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.
+ if (!identical(kind, LT_TOKEN)) return null;
+ token = token.next;
+ if (token == null) return null;
+ token = tryParseType(token);
+ while (token != null && identical(token.kind, COMMA_TOKEN)) {
+ token = token.next;
+ if (token == null) return null;
+ token = tryParseType(token);
+ }
+ if (token == null) return null;
+ if (identical(token.kind, GT_TOKEN)) return token.next;
+ if (!identical(token.kind, GT_GT_TOKEN)) return null;
+ // [token] is '>>' of which the final '>' that we are parsing is the first
+ // character. In order to keep the parsing process on track we must return
+ // a synthetic '>' corresponding to the second character of that '>>'.
+ Token syntheticToken = new SymbolToken(GT_INFO, token.charOffset + 1);
+ syntheticToken.next = token.next;
+ return syntheticToken;
+ }
+
+ /// 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
+ /// Does not produce listener events.
+ 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
+ if (!identical(token.kind, IDENTIFIER_TOKEN)) return null;
+ token = token.next;
+ if (!identical(token.kind, PERIOD_TOKEN)) return token;
+ token = token.next;
+ if (!identical(token.kind, IDENTIFIER_TOKEN)) return null;
+ return token.next;
+ }
+
+ /// 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
+ /// Does not produce listener events.
+ Token tryParseType(Token token) {
+ token = tryParseQualified(token);
+ if (token == null) return null;
+ Token tokenAfterQualified = token;
+ token = tryParseTypeArgumentsNested(token);
+ return token == null ? tokenAfterQualified : token;
+ }
+
+ /// 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
+ /// Does not produce listener events. With respect to the final '(', please
+ /// see the description of [isValidTypeArguments].
+ Token tryParseTypeArguments(Token token) {
+ final kind = token.kind;
+ if (!identical(kind, LT_TOKEN)) return null;
+ BeginGroupToken beginToken = token;
+ Token endToken = beginToken.endGroup;
+ token = token.next;
+ if (token == null || endToken == null ||
+ !identical(endToken.next?.kind, OPEN_PAREN_TOKEN)) return null;
+ token = tryParseType(token);
ahe 2016/04/08 09:53:32 Is this really necessary? If so, perhaps push back
+ while (token != null && identical(token.kind, COMMA_TOKEN)) {
+ token = token.next;
+ if (token == null) return null;
+ token = tryParseType(token);
+ }
+ if (!identical(token?.kind, GT_TOKEN)) return null;
+ return token.next;
+ }
+
+ /// 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
+ /// '<' type (',' type)* '>' '('. The final '(' is not part of the
+ /// grammar construct `typeArguments`, but it is required here such that
+ /// type arguments in generic method invocations can be recognized, and
+ /// as few as possible other constructs will pass (e.g., 'a < C, D > 3').
+ 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
+ return tryParseTypeArguments(token) != null;
+ }
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 (
+
Token parseQualified(Token token) {
token = parseIdentifier(token);
while (optional('.', token)) {
@@ -1011,6 +1094,11 @@ class Parser {
}
Token token = parseIdentifier(name);
+ if (_enableGenericMethodSyntax && getOrSet == null) {
+ token = parseTypeVariablesOpt(token);
+ } else {
+ listener.handleNoTypeVariables(token);
+ }
token = parseFormalParametersOpt(token);
bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
token = parseAsyncModifier(token);
@@ -1319,7 +1407,8 @@ class Parser {
// error handling.
final String value = token.stringValue;
if ((identical(value, '(')) || (identical(value, '.'))
- || (identical(value, '{')) || (identical(value, '=>'))) {
+ || (identical(value, '{')) || (identical(value, '=>'))
+ || (_enableGenericMethodSyntax && identical(value, '<'))) {
isField = false;
break;
} else if (identical(value, ';')) {
@@ -1420,6 +1509,11 @@ class Parser {
}
token = parseQualifiedRestOpt(token);
+ if (_enableGenericMethodSyntax && getOrSet == null) {
+ token = parseTypeVariablesOpt(token);
+ } else {
+ listener.handleNoTypeVariables(token);
+ }
token = parseFormalParametersOpt(token);
token = parseInitializersOpt(token);
bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
@@ -1506,6 +1600,11 @@ class Parser {
}
token = parseQualifiedRestOpt(token);
listener.endFunctionName(token);
+ if (_enableGenericMethodSyntax && getOrSet == null) {
+ token = parseTypeVariablesOpt(token);
+ } else {
+ listener.handleNoTypeVariables(token);
+ }
token = parseFormalParametersOpt(token);
token = parseInitializersOpt(token);
bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
@@ -1546,6 +1645,11 @@ class Parser {
listener.beginFunctionName(token);
token = parseIdentifier(token);
listener.endFunctionName(token);
+ if (_enableGenericMethodSyntax) {
+ token = parseTypeVariablesOpt(token);
+ } else {
+ listener.handleNoTypeVariables(token);
+ }
token = parseFormalParameters(token);
listener.handleNoInitializers();
bool previousAsyncAwaitKeywordsEnabled = asyncAwaitKeywordsEnabled;
@@ -2011,6 +2115,7 @@ class Parser {
listener.handleIndexedExpression(openSquareBracket, token);
token = expect(']', token);
} else if (optional('(', token)) {
+ listener.handleNoTypeArguments(token);
token = parseArguments(token);
listener.endSend(token);
} else {
@@ -2108,6 +2213,7 @@ class Parser {
token = token.next;
if (optional('(', token)) {
// Constructor forwarding.
+ listener.handleNoTypeArguments(token);
token = parseArguments(token);
listener.endSend(token);
}
@@ -2119,6 +2225,7 @@ class Parser {
token = token.next;
if (optional('(', token)) {
// Super constructor.
+ listener.handleNoTypeArguments(token);
token = parseArguments(token);
listener.endSend(token);
}
@@ -2335,6 +2442,11 @@ class Parser {
Token parseSend(Token token) {
listener.beginSend(token);
token = parseIdentifier(token);
+ if (_enableGenericMethodSyntax && isValidTypeArguments(token)) {
+ token = parseTypeArgumentsOpt(token);
+ } else {
+ listener.handleNoTypeArguments(token);
+ }
token = parseArgumentsOpt(token);
listener.endSend(token);
return token;
« no previous file with comments | « pkg/compiler/lib/src/parser/node_listener.dart ('k') | tests/compiler/dart2js/options_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698