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

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

Issue 1878253002: Adds support for remaining generic method syntax constructs. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Review 2 response 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 0a8d68d77a76cdf7aefdbda26dade47234441bb1..f4fbd9d5c1d110c7d360c614075dde72a972a62b 100644
--- a/pkg/compiler/lib/src/parser/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -463,6 +463,11 @@ class Parser {
}
token = parseIdentifier(token);
if (optional('(', token)) {
+ listener.handleNoTypeVariables(token);
+ token = parseFormalParameters(token);
+ listener.handleFunctionTypedFormalParameter(token);
+ } else if (enableGenericMethodSyntax && optional('<', token)) {
+ token = parseTypeVariablesOpt(token);
token = parseFormalParameters(token);
listener.handleFunctionTypedFormalParameter(token);
}
@@ -767,12 +772,15 @@ class Parser {
Token parseTypeVariable(Token token) {
listener.beginTypeVariable(token);
token = parseIdentifier(token);
- if (optional('extends', token)) {
+ Token extendsOrSuper = null;
+ if (optional('extends', token) ||
+ (enableGenericMethodSyntax && optional('super', token))) {
+ extendsOrSuper = token;
token = parseType(token.next);
} else {
listener.handleNoType(token);
}
- listener.endTypeVariable(token);
+ listener.endTypeVariable(token, extendsOrSuper);
return token;
}
@@ -1845,15 +1853,37 @@ class Parser {
// We are looking at "type identifier '('".
BeginGroupToken beginParen = afterId;
Token endParen = beginParen.endGroup;
+ // TODO(eernst): Check for NPE as described in issue 26252.
Token afterParens = endParen.next;
if (optional('{', afterParens) ||
optional('=>', afterParens) ||
optional('async', afterParens) ||
optional('sync', afterParens)) {
// We are looking at "type identifier '(' ... ')'" followed
- // by '=>' or '{'.
+ // by '{', '=>', 'async', or 'sync'.
return parseFunctionDeclaration(token);
}
+ } else if (enableGenericMethodSyntax &&
+ identical(afterIdKind, LT_TOKEN)) {
+ // We are looking at "type identifier '<'".
+ BeginGroupToken beginAngle = afterId;
+ Token endAngle = beginAngle.endGroup;
+ if (endAngle != null &&
+ identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) {
+ BeginGroupToken beginParen = endAngle.next;
+ Token endParen = beginParen.endGroup;
+ if (endParen != null) {
+ Token afterParens = endParen.next;
+ if (optional('{', afterParens) ||
+ optional('=>', afterParens) ||
+ optional('async', afterParens) ||
+ optional('sync', afterParens)) {
+ // We are looking at "type identifier '<' ... '>' '(' ... ')'"
+ // followed by '{', '=>', 'async', or 'sync'.
+ return parseFunctionDeclaration(token);
+ }
+ }
+ }
}
// Fall-through to expression statement.
} else {
@@ -1861,6 +1891,7 @@ class Parser {
return parseLabeledStatement(token);
} else if (optional('(', token.next)) {
BeginGroupToken begin = token.next;
+ // TODO(eernst): Check for NPE as described in issue 26252.
String afterParens = begin.endGroup.next.stringValue;
if (identical(afterParens, '{') ||
identical(afterParens, '=>') ||
@@ -1868,6 +1899,24 @@ class Parser {
identical(afterParens, 'sync')) {
return parseFunctionDeclaration(token);
}
+ } else if (enableGenericMethodSyntax && optional('<', token.next)) {
+ BeginGroupToken beginAngle = token.next;
+ Token endAngle = beginAngle.endGroup;
+ if (endAngle != null &&
+ identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) {
+ BeginGroupToken beginParen = endAngle.next;
+ Token endParen = beginParen.endGroup;
+ if (endParen != null) {
+ String afterParens = endParen.next.stringValue;
+ if (identical(afterParens, '{') ||
+ identical(afterParens, '=>') ||
+ identical(afterParens, 'async') ||
+ identical(afterParens, 'sync')) {
+ return parseFunctionDeclaration(token);
+ }
+ }
+ }
+ // Fall through to expression statement.
}
}
return parseExpressionStatement(token);
@@ -2135,11 +2184,14 @@ class Parser {
}
} else if (kind == OPEN_PAREN_TOKEN) {
return parseParenthesizedExpressionOrFunctionLiteral(token);
- } else if ((kind == LT_TOKEN) ||
- (kind == OPEN_SQUARE_BRACKET_TOKEN) ||
- (kind == OPEN_CURLY_BRACKET_TOKEN) ||
- token.stringValue == '[]') {
- return parseLiteralListOrMap(token);
+ } else if (kind == OPEN_SQUARE_BRACKET_TOKEN || token.stringValue == '[]') {
+ listener.handleNoTypeArguments(token);
+ return parseLiteralListSuffix(token, null);
+ } else if (kind == OPEN_CURLY_BRACKET_TOKEN) {
+ listener.handleNoTypeArguments(token);
+ return parseLiteralMapSuffix(token, null);
+ } else if (kind == LT_TOKEN) {
+ return parseLiteralListOrMapOrFunction(token, null);
} else {
return listener.expectedExpression(token);
}
@@ -2147,6 +2199,7 @@ class Parser {
Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
BeginGroupToken beginGroup = token;
+ // TODO(eernst): Check for NPE as described in issue 26252.
Token nextToken = beginGroup.endGroup.next;
int kind = nextToken.kind;
if (mayParseFunctionExpressions &&
@@ -2154,6 +2207,7 @@ class Parser {
identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
(identical(kind, KEYWORD_TOKEN) &&
(nextToken.value == 'async' || nextToken.value == 'sync')))) {
+ listener.handleNoTypeVariables(token);
return parseUnnamedFunction(token);
} else {
bool old = mayParseFunctionExpressions;
@@ -2203,30 +2257,16 @@ class Parser {
return token;
}
- Token parseLiteralListOrMap(Token token) {
- Token constKeyword = null;
- if (optional('const', token)) {
- constKeyword = token;
- token = token.next;
- }
- token = parseTypeArgumentsOpt(token);
+ /// '[' (expressionList ','?)? ']'.
+ ///
+ /// Provide [constKeyword] if preceded by 'const', null if not.
+ /// This is a suffix parser because it is assumed that type arguments have
+ /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
+ Token parseLiteralListSuffix(Token token, Token constKeyword) {
+ assert(optional('[', token) || optional('[]', token));
Token beginToken = token;
int count = 0;
- if (optional('{', token)) {
- bool old = mayParseFunctionExpressions;
- mayParseFunctionExpressions = true;
- do {
- if (optional('}', token.next)) {
- token = token.next;
- break;
- }
- token = parseMapLiteralEntry(token.next);
- ++count;
- } while (optional(',', token));
- mayParseFunctionExpressions = old;
- listener.handleLiteralMap(count, beginToken, constKeyword, token);
- return expect('}', token);
- } else if (optional('[', token)) {
+ if (optional('[', token)) {
bool old = mayParseFunctionExpressions;
mayParseFunctionExpressions = true;
do {
@@ -2240,10 +2280,80 @@ class Parser {
mayParseFunctionExpressions = old;
listener.handleLiteralList(count, beginToken, constKeyword, token);
return expect(']', token);
- } else if (optional('[]', token)) {
- listener.handleLiteralList(0, token, constKeyword, token);
- return token.next;
+ }
+ // Looking at '[]'.
+ listener.handleLiteralList(0, token, constKeyword, token);
+ return token.next;
+ }
+
+ /// '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'.
+ ///
+ /// Provide token for [constKeyword] if preceded by 'const', null if not.
+ /// This is a suffix parser because it is assumed that type arguments have
+ /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
+ Token parseLiteralMapSuffix(Token token, Token constKeyword) {
+ assert(optional('{', token));
+ Token beginToken = token;
+ int count = 0;
+ bool old = mayParseFunctionExpressions;
+ mayParseFunctionExpressions = true;
+ do {
+ if (optional('}', token.next)) {
+ token = token.next;
+ break;
+ }
+ token = parseMapLiteralEntry(token.next);
+ ++count;
+ } while (optional(',', token));
+ mayParseFunctionExpressions = old;
+ listener.handleLiteralMap(count, beginToken, constKeyword, token);
+ return expect('}', token);
+ }
+
+ /// formalParameterList functionBody.
+ ///
+ /// This is a suffix parser because it is assumed that type arguments have
+ /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
+ Token parseLiteralFunctionSuffix(Token token) {
+ assert(optional('(',token));
+ BeginGroupToken beginGroup = token;
+ if (beginGroup.endGroup != null) {
+ Token nextToken = beginGroup.endGroup.next;
+ int kind = nextToken.kind;
+ if (identical(kind, FUNCTION_TOKEN) ||
+ identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
+ (identical(kind, KEYWORD_TOKEN) &&
+ (nextToken.value == 'async' || nextToken.value == 'sync'))) {
+ return parseUnnamedFunction(token);
+ }
+ // Fall through.
+ }
+ listener.unexpected(token);
+ return null;
+ }
+
+ /// (typeArguments (
+ /// '[' (expressionList ','?)? ']' |
+ /// '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}')) |
+ /// typeParameters formalParameterList functionBody.
+ ///
+ /// Provide token for [constKeyword] if preceded by 'const', null if not.
+ Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) {
+ assert(optional('<', token));
+ BeginGroupToken begin = token;
+ if (enableGenericMethodSyntax &&
+ constKeyword == null &&
+ begin.endGroup != null &&
+ identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) {
+ token = parseTypeVariablesOpt(token);
+ return parseLiteralFunctionSuffix(token);
} else {
+ token = parseTypeArgumentsOpt(token);
+ if (optional('{', token)) {
+ return parseLiteralMapSuffix(token, constKeyword);
+ } else if ((optional('[', token)) || (optional('[]', token))) {
+ return parseLiteralListSuffix(token, constKeyword);
+ }
listener.unexpected(token);
return null;
}
@@ -2275,8 +2385,14 @@ class Parser {
}
bool isFunctionDeclaration(Token token) {
+ if (enableGenericMethodSyntax && optional('<', token)) {
+ BeginGroupToken begin = token;
+ if (begin.endGroup == null) return false;
+ token = begin.endGroup.next;
+ }
if (optional('(', token)) {
BeginGroupToken begin = token;
+ // TODO(eernst): Check for NPE as described in issue 26252.
String afterParens = begin.endGroup.next.stringValue;
if (identical(afterParens, '{') ||
identical(afterParens, '=>') ||
@@ -2311,11 +2427,16 @@ class Parser {
Token constKeyword = token;
token = expect('const', token);
final String value = token.stringValue;
- if ((identical(value, '<')) ||
- (identical(value, '[')) ||
- (identical(value, '[]')) ||
- (identical(value, '{'))) {
- return parseLiteralListOrMap(constKeyword);
+ if ((identical(value, '[')) || (identical(value, '[]'))) {
+ listener.handleNoTypeArguments(token);
+ return parseLiteralListSuffix(token, constKeyword);
+ }
+ if (identical(value, '{')) {
+ listener.handleNoTypeArguments(token);
+ return parseLiteralMapSuffix(token, constKeyword);
+ }
+ if (identical(value, '<')) {
+ return parseLiteralListOrMapOrFunction(token, constKeyword);
}
token = parseConstructorReference(token);
token = parseRequiredArguments(token);
« no previous file with comments | « pkg/compiler/lib/src/parser/node_listener.dart ('k') | pkg/compiler/lib/src/scanner/array_based_scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698