Chromium Code Reviews| 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..df576076fd9251eb0154b935c569e8079be4ba8b 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,9 +772,12 @@ class Parser { |
| Token parseTypeVariable(Token token) { |
| listener.beginTypeVariable(token); |
| token = parseIdentifier(token); |
| - if (optional('extends', token)) { |
| + if (optional('extends', token) || |
| + (enableGenericMethodSyntax && optional('super', token))) { |
| + listener.handleExtendsOrSuper(token); |
| token = parseType(token.next); |
| } else { |
| + listener.handleNoExtendsNorSuper(token); |
| listener.handleNoType(token); |
| } |
| listener.endTypeVariable(token); |
|
Johnni Winther
2016/04/13 11:50:19
Remove 'handleExtendsOrSuper' and 'handleNoExtends
eernst
2016/04/13 17:08:26
Done.
|
| @@ -1845,15 +1853,37 @@ class Parser { |
| // We are looking at "type identifier '('". |
| BeginGroupToken beginParen = afterId; |
| Token endParen = beginParen.endGroup; |
|
karlklose
2016/04/13 12:26:55
Consider creating an issue for this and change the
eernst
2016/04/13 17:08:26
Done.
|
| + // TODO(eernst): Check this, looks like an NPE with unbalanced parens. |
|
Johnni Winther
2016/04/13 11:50:19
Do you have examples that trigger this (and others
eernst
2016/04/13 17:08:26
No, I hoped to get a quick confirmation like "That
|
| 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 this, looks like an NPE with unbalanced parens. |
| 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); |
| @@ -2139,7 +2188,7 @@ class Parser { |
| (kind == OPEN_SQUARE_BRACKET_TOKEN) || |
| (kind == OPEN_CURLY_BRACKET_TOKEN) || |
| token.stringValue == '[]') { |
| - return parseLiteralListOrMap(token); |
| + return parseLiteralListOrMapOrFunction(token); |
| } else { |
| return listener.expectedExpression(token); |
| } |
| @@ -2147,6 +2196,7 @@ class Parser { |
| Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { |
| BeginGroupToken beginGroup = token; |
| + // TODO(eernst): Check this, looks like an NPE with unbalanced parens. |
| Token nextToken = beginGroup.endGroup.next; |
| int kind = nextToken.kind; |
| if (mayParseFunctionExpressions && |
| @@ -2154,6 +2204,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,13 +2254,27 @@ class Parser { |
| return token; |
| } |
| - Token parseLiteralListOrMap(Token token) { |
| + Token parseLiteralListOrMapOrFunction(Token token) { |
| Token constKeyword = null; |
| if (optional('const', token)) { |
| constKeyword = token; |
| token = token.next; |
| } |
| - token = parseTypeArgumentsOpt(token); |
| + if (enableGenericMethodSyntax && |
| + constKeyword == null && |
| + optional('<', token) && |
| + token is BeginGroupToken && |
| + token.endGroup != null && |
| + identical(token.endGroup.next.kind, OPEN_PAREN_TOKEN)) { |
| + token = parseTypeVariablesOpt(token); |
| + } else { |
| + // [parseLiteralListOrMapOrFunction] is only called when [token] is one |
| + // of `<`, '{', `[`, so we are not looking at a non-generic literal |
| + // function, so we are looking at a map or list literal, and they may |
| + // or may not have a `<..>` part, but if it is present it contains type |
| + // arguments. |
| + token = parseTypeArgumentsOpt(token); |
| + } |
| Token beginToken = token; |
| int count = 0; |
| if (optional('{', token)) { |
| @@ -2243,10 +2308,22 @@ class Parser { |
| } else if (optional('[]', token)) { |
| listener.handleLiteralList(0, token, constKeyword, token); |
| return token.next; |
| - } else { |
| - listener.unexpected(token); |
| - return null; |
| + } else if (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; |
| } |
| Token parseMapLiteralEntry(Token token) { |
| @@ -2275,8 +2352,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 this, looks like an NPE with unbalanced parens. |
| String afterParens = begin.endGroup.next.stringValue; |
| if (identical(afterParens, '{') || |
| identical(afterParens, '=>') || |
| @@ -2315,7 +2398,7 @@ class Parser { |
| (identical(value, '[')) || |
| (identical(value, '[]')) || |
| (identical(value, '{'))) { |
| - return parseLiteralListOrMap(constKeyword); |
| + return parseLiteralListOrMapOrFunction(constKeyword); |
| } |
| token = parseConstructorReference(token); |
| token = parseRequiredArguments(token); |