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

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

Issue 3001993002: improve fasta export directive recovery (Closed)
Patch Set: rebase Created 3 years, 4 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/element_listener.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 365b7979d7573c7375bccbbc8cb521435273c237..d3bcceae05a50ab1bdd7ec486e4fa479814c7fa3 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -20,6 +20,8 @@ import '../../scanner/token.dart'
EQUALITY_PRECEDENCE,
POSTFIX_PRECEDENCE,
RELATIONAL_PRECEDENCE,
+ SyntheticStringToken,
+ SyntheticToken,
TokenType;
import '../scanner/token.dart' show isUserDefinableOperator;
@@ -68,6 +70,8 @@ import 'listener.dart' show Listener;
import 'member_kind.dart' show MemberKind;
+import 'token_stream_rewriter.dart';
+
import 'type_continuation.dart'
show TypeContinuation, typeContiunationFromFormalParameterKind;
@@ -208,6 +212,24 @@ class Parser {
/// external clients, for example, to parse an expression outside a function.
AsyncModifier asyncState = AsyncModifier.Sync;
+ /// The first token in the parse stream and used during parser recovery.
+ /// This is automatically set by the [parseUnit] method,
+ /// but must be manually set when any other parse method is called.
+ /// If not set, then the parser will call [handleUnrecoverableError]
+ /// rather than rewriting the token stream
+ /// and calling [handleRecoverableError].
+ Token firstToken;
+
+ /// A rewriter for inserting synthetic tokens.
+ /// Access using [rewriter] for lazy initialization.
+ TokenStreamRewriter cachedRewriter;
+
+ TokenStreamRewriter get rewriter {
+ assert(firstToken != null, 'firstToken must be set for parser recovery');
+ cachedRewriter ??= new TokenStreamRewriter(firstToken);
+ return cachedRewriter;
+ }
+
Parser(this.listener);
bool get inGenerator {
@@ -223,6 +245,7 @@ class Parser {
bool get inPlainSync => asyncState == AsyncModifier.Sync;
Token parseUnit(Token token) {
+ firstToken = token;
listener.beginCompilationUnit(token);
int count = 0;
while (!identical(token.kind, EOF_TOKEN)) {
@@ -230,6 +253,9 @@ class Parser {
count++;
}
listener.endCompilationUnit(count, token);
+ // Clear fields that could lead to memory leak.
+ firstToken = null;
+ cachedRewriter = null;
return token;
}
@@ -356,13 +382,12 @@ class Parser {
Token exportKeyword = token;
listener.beginExport(exportKeyword);
assert(optional('export', token));
- token = parseLiteralStringOrRecoverExpression(token.next);
+ token = ensureParseLiteralString(token.next);
token = parseConditionalUris(token);
token = parseCombinators(token);
- Token semicolon = token;
- token = expect(';', token);
+ Token semicolon = ensureSemicolon(token);
listener.endExport(exportKeyword, semicolon);
- return token;
+ return semicolon.next;
}
Token parseCombinators(Token token) {
@@ -909,6 +934,8 @@ class Parser {
}
Token expect(String string, Token token) {
+ // TODO(danrubel) update all uses of expect(';'...) to ensureSemicolon
+ // then add assert(!identical(';', string));
if (!identical(string, token.stringValue)) {
return reportUnrecoverableError(
token, fasta.templateExpectedButGot.withArguments(string))
@@ -1927,6 +1954,33 @@ class Parser {
return token;
}
+ Token ensureParseLiteralString(Token token) {
+ if (!identical(token.kind, STRING_TOKEN)) {
+ Message message = fasta.templateExpectedString.withArguments(token);
+ Token newToken =
+ new SyntheticStringToken(TokenType.STRING, '""', token.charOffset, 0);
+ token = rewriteAndRecover(token, message, newToken);
+ }
+ return parseLiteralString(token);
+ }
+
+ Token ensureSemicolon(Token token) {
+ // TODO(danrubel): Once all expect(';'...) call sites have been converted
+ // to use this method, remove similar semicolon recovery code
+ // from the handleError method in element_listener.dart.
+ if (optional(';', token)) return token;
+ Message message = fasta.templateExpectedButGot.withArguments(';');
+ Token newToken = new SyntheticToken(TokenType.SEMICOLON, token.charOffset);
+ return rewriteAndRecover(token, message, newToken);
+ }
+
+ Token rewriteAndRecover(Token token, Message message, Token newToken) {
+ if (firstToken == null) return reportUnrecoverableError(token, message);
+ reportRecoverableError(token, message);
+ token = rewriter.insertTokenBefore(newToken, token);
+ return token;
+ }
+
Token parseLiteralStringOrRecoverExpression(Token token) {
if (identical(token.kind, STRING_TOKEN)) {
return parseLiteralString(token);
« no previous file with comments | « pkg/compiler/lib/src/parser/element_listener.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698