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

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: 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
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..ef7d6ed032a5e31d9e4fb72a18a0e796c91bdbe0 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;
+
+ Parser(this.listener, ParserOptions parserOptions,
+ {this.asyncAwaitKeywordsEnabled: false}) :
+ parserOptions = parserOptions,
+ enableGenericMethodSyntax = parserOptions.enableGenericMethodSyntax;
Token parseUnit(Token token) {
listener.beginCompilationUnit(token);
@@ -525,6 +531,80 @@ class Parser {
return false;
}
+ /// Returns true if [token] matches '<' type (',' type)* '>' '(', and
+ /// otherwise returns false. 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 isValidMethodTypeArguments(Token token) {
+ return tryParseMethodTypeArguments(token) != null;
+ }
+
+ /// Returns token after match if [token] matches '<' type (',' type)* '>' '(',
+ /// and otherwise returns null. Does not produce listener events. With respect
+ /// to the final '(', please see the description of
+ /// [isValidMethodTypeArguments].
+ Token tryParseMethodTypeArguments(Token token) {
+ if (!identical(token.kind, LT_TOKEN)) return null;
+ BeginGroupToken beginToken = token;
+ Token endToken = beginToken.endGroup;
+ if (endToken == null ||
+ !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.
+ token = tryParseType(token.next);
+ while (token != null && identical(token.kind, COMMA_TOKEN)) {
+ token = tryParseType(token.next);
+ }
+ if (token == null || !identical(token.kind, GT_TOKEN)) return null;
+ return token.next;
+ }
+
+ /// Returns token after match if [token] matches typeName typeArguments?, and
+ /// otherwise returns null. Does not produce listener events.
+ Token tryParseType(Token token) {
+ token = tryParseQualified(token);
+ if (token == null) return null;
+ Token tokenAfterQualified = token;
+ token = tryParseNestedTypeArguments(token);
+ return token == null ? tokenAfterQualified : token;
+ }
+
+ /// Returns token after match if [token] matches identifier ('.' identifier)?,
+ /// and otherwise returns null. Does not produce listener events.
+ Token tryParseQualified(Token token) {
+ 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;
+ }
+
+ /// Returns token after match if [token] matches '<' type (',' type)* '>',
+ /// and otherwise returns null. Does not produce listener events. The final
+ /// '>' may be the first character in a '>>' token, in which case a synthetic
+ /// '>' token is created and returned, representing the second '>' in the
+ /// '>>' token.
+ Token tryParseNestedTypeArguments(Token token) {
+ if (!identical(token.kind, LT_TOKEN)) return null;
+ // If the initial '<' matches the first '>' in a '>>' token, we will have
+ // `token.endGroup == null`, so we cannot rely on `token.endGroup == null`
+ // to imply that the match must fail. Hence no `token.endGroup == null`
+ // test here.
+ token = tryParseType(token.next);
+ while (token != null && identical(token.kind, COMMA_TOKEN)) {
+ token = tryParseType(token.next);
+ }
+ 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;
+ }
+
Token parseQualified(Token token) {
token = parseIdentifier(token);
while (optional('.', token)) {
@@ -1011,6 +1091,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 +1404,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 +1506,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 +1597,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 +1642,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 +2112,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 +2210,7 @@ class Parser {
token = token.next;
if (optional('(', token)) {
// Constructor forwarding.
+ listener.handleNoTypeArguments(token);
token = parseArguments(token);
listener.endSend(token);
}
@@ -2119,6 +2222,7 @@ class Parser {
token = token.next;
if (optional('(', token)) {
// Super constructor.
+ listener.handleNoTypeArguments(token);
token = parseArguments(token);
listener.endSend(token);
}
@@ -2335,6 +2439,11 @@ class Parser {
Token parseSend(Token token) {
listener.beginSend(token);
token = parseIdentifier(token);
+ if (enableGenericMethodSyntax && isValidMethodTypeArguments(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/backend_dart/dart_printer_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698