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

Unified Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2795063002: Add support for parsing comments with generic parameters /*<K, V>*/ with Fasta. (Closed)
Patch Set: Created 3 years, 9 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/analyzer/test/generated/parser_fasta_test.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/front_end/lib/src/fasta/parser/parser.dart
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index e6dba6a39dc1d8cd5fc6c8321fba028110f6bda5..ecf6fc15339d4f334ec5a4e9a6b0bb794b508bf3 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -65,7 +65,10 @@ import '../scanner/precedence.dart'
ASSIGNMENT_PRECEDENCE,
AS_INFO,
CASCADE_PRECEDENCE,
+ EOF_INFO,
EQUALITY_PRECEDENCE,
+ GENERIC_METHOD_TYPE_ASSIGN,
+ GENERIC_METHOD_TYPE_LIST,
GT_INFO,
IS_INFO,
MINUS_MINUS_INFO,
@@ -83,6 +86,7 @@ import '../scanner/precedence.dart'
import '../scanner/token.dart'
show
BeginGroupToken,
+ CommentToken,
KeywordToken,
SymbolToken,
Token,
@@ -113,6 +117,7 @@ import '../scanner/token_constants.dart'
STRING_TOKEN;
import '../scanner/characters.dart' show $CLOSE_CURLY_BRACKET;
+import '../scanner/string_scanner.dart';
ahe 2017/04/04 08:10:45 The parser shouldn't be importing as specific scan
scheglov 2017/04/04 15:33:47 Why? The parser knows what it wants to parse and h
import '../util/link.dart' show Link;
@@ -184,6 +189,8 @@ class Parser {
bool mayParseFunctionExpressions = true;
+ bool parseGenericMethodComments = false;
+
/// Represents parser state: what asynchronous syntax is allowed in the
/// function being currently parsed. In rare situations, this can be set by
/// external clients, for example, to parse an expression outside a function.
@@ -633,6 +640,7 @@ class Parser {
}
}
+ token = _injectGenericCommentTypeList(token);
ahe 2017/04/04 08:10:45 This method should be public and overridden in a s
scheglov 2017/04/04 15:33:47 In which subclass?
if (optional('(', token)) {
Token inlineFunctionTypeStart = token;
listener.beginFunctionTypedFormalParameter(token);
@@ -1107,9 +1115,10 @@ class Parser {
(t) => listener.handleNoTypeVariables(t));
}
- // TODO(ahe): Clean this up.
+ /// TODO(ahe): Clean this up.
ahe 2017/04/04 08:10:45 This isn't a documentation comment.
scheglov 2017/04/04 15:33:47 Well, I think any comment before a method, and whi
Token parseStuff(Token token, Function beginStuff, Function stuffParser,
Function endStuff, Function handleNoStuff) {
+ token = _injectGenericCommentTypeList(token);
if (optional('<', token)) {
Token begin = token;
beginStuff(begin);
@@ -2788,6 +2797,7 @@ class Parser {
}
Token parsePrimary(Token token, IdentifierContext context) {
+ token = _injectGenericCommentTypeList(token);
final kind = token.kind;
if (kind == IDENTIFIER_TOKEN) {
return parseSendOrFunctionLiteral(token, context);
@@ -3080,6 +3090,7 @@ class Parser {
Token parseConstExpression(Token token) {
Token constKeyword = token;
token = expect('const', token);
+ token = _injectGenericCommentTypeList(token);
final String value = token.stringValue;
if ((identical(value, '[')) || (identical(value, '[]'))) {
listener.handleNoTypeArguments(token);
@@ -3193,6 +3204,7 @@ class Parser {
Token beginToken = token;
listener.beginSend(token);
token = parseIdentifier(token, context);
+ token = _injectGenericCommentTypeList(token);
if (isValidMethodTypeArguments(token)) {
token = parseTypeArgumentsOpt(token);
} else {
@@ -3789,6 +3801,60 @@ class Parser {
return reportUnrecoverableError(
token, () => code.format(uri, token.charOffset, string));
}
+
+ /// Matches a generic comment type parameters or type arguments and injects
+ /// them into the token stream before the given [token].
+ Token _injectGenericCommentTypeList(Token token) {
+ return _injectGenericComment(token, GENERIC_METHOD_TYPE_LIST, 2);
+ }
+
+ /// Check if the given [token] has a comment token with the given [info],
+ /// which should be either [GENERIC_METHOD_TYPE_ASSIGN] or
+ /// [GENERIC_METHOD_TYPE_LIST]. If found, parse the comment into tokens and
+ /// inject into the token stream before the [token].
+ Token _injectGenericComment(Token token, PrecedenceInfo info, int prefixLen) {
+ if (parseGenericMethodComments) {
+ CommentToken t = token.precedingCommentTokens;
+ for (; t != null; t = t.next) {
+ if (t.info == info) {
+ String code = t.lexeme.substring(prefixLen, t.lexeme.length - 2);
+ Token tokens = _scanGenericMethodComment(code, t.offset + prefixLen);
+ if (tokens != null) {
+ // Remove the token from the comment stream.
+ t.remove();
+ // Insert the tokens into the stream.
+ _injectTokenList(token, tokens);
+ return tokens;
+ }
+ }
+ }
+ }
+ return token;
+ }
+
+ /// Scans the given [code], and returns the tokens, otherwise returns `null`.
+ Token _scanGenericMethodComment(String code, int offset) {
+ // TODO(scheglov) Let StringScanner to specify the string offset.
+ var scanner = new StringScanner(' ' * offset + code);
ahe 2017/04/04 08:10:45 The listener should be asked how to create a scann
scheglov 2017/04/04 15:33:47 What do we want to extend? These comments are part
+ Token firstToken = scanner.tokenize();
+ if (scanner.hasErrors) {
+ return null;
+ }
+ return firstToken;
+ }
+
+ void _injectTokenList(Token beforeToken, Token firstToken) {
+ // Scanner creates a cyclic EOF token.
+ Token lastToken = firstToken;
+ while (lastToken.next.info != EOF_INFO) {
+ lastToken = lastToken.next;
+ }
+ // Inject these new tokens into the stream.
+ Token previous = beforeToken.previous;
+ lastToken.setNext(beforeToken);
+ previous.setNext(firstToken);
+ beforeToken = firstToken;
+ }
}
typedef FastaMessage NoArgument(Uri uri, int charOffset);
« no previous file with comments | « pkg/analyzer/test/generated/parser_fasta_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698