Convert more identifier contexts
Change-Id: I0ead9e15da9d477b26deb13c6880dbfeea4d7724
Reviewed-on: https://dart-review.googlesource.com/56401
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index 284159d..6098a0e 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -176,20 +176,16 @@
/// Identifier is the declaration of a label (i.e. it is followed by `:` and
/// then a statement).
- static const labelDeclaration =
- const IdentifierContext('labelDeclaration', inDeclaration: true);
+ static const labelDeclaration = const LabelDeclarationIdentifierContext();
/// Identifier is the start of a reference occurring in a literal symbol (e.g.
/// `foo` in `#foo`).
- static const literalSymbol =
- const IdentifierContext('literalSymbol', inSymbol: true);
+ static const literalSymbol = const LiteralSymbolIdentifierContext();
/// Identifier is part of a reference occurring in a literal symbol, but it's
/// not the first identifier of the reference (e.g. `foo` in `#prefix.foo`).
- static const literalSymbolContinuation = const IdentifierContext(
- 'literalSymbolContinuation',
- inSymbol: true,
- isContinuation: true);
+ static const literalSymbolContinuation =
+ const LiteralSymbolIdentifierContext.continuation();
/// Identifier appears in an expression, and it does not immediately follow a
/// `.`.
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index f2fc57b..c8409ef 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -402,6 +402,28 @@
}
}
+class LiteralSymbolIdentifierContext extends IdentifierContext {
+ const LiteralSymbolIdentifierContext()
+ : super('literalSymbol', inSymbol: true);
+
+ const LiteralSymbolIdentifierContext.continuation()
+ : super('literalSymbolContinuation',
+ inSymbol: true, isContinuation: true);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ return identifier;
+ }
+
+ // Recovery
+ return parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ }
+}
+
/// See [IdentifierContext.localFunctionDeclaration]
/// and [IdentifierContext.localFunctionDeclarationContinuation].
class LocalFunctionDeclarationIdentifierContext extends IdentifierContext {
@@ -439,6 +461,37 @@
}
}
+/// See [IdentifierContext.labelDeclaration].
+class LabelDeclarationIdentifierContext extends IdentifierContext {
+ const LabelDeclarationIdentifierContext()
+ : super('labelDeclaration', inDeclaration: true);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ return identifier;
+ }
+
+ // Recovery
+ if (isOneOfOrEof(identifier, const [':']) ||
+ looksLikeStartOfNextStatement(identifier)) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ identifier, fasta.templateExpectedIdentifier);
+ if (!identifier.isKeywordOrIdentifier) {
+ // When in doubt, consume the token to ensure we make progress
+ // but insert a synthetic identifier to satisfy listeners.
+ identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+ }
+ }
+ return identifier;
+ }
+}
+
/// See [IdentifierContext.libraryName],
/// and [IdentifierContext.libraryNameContinuation]
/// and [IdentifierContext.partName],
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 726c840..c8429fc 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -2023,11 +2023,6 @@
followingValues = [';'];
} else if (context == IdentifierContext.constructorReferenceContinuation) {
followingValues = ['.', ',', '(', ')', '[', ']', '}', ';'];
- } else if (context == IdentifierContext.labelDeclaration) {
- followingValues = [':'];
- } else if (context == IdentifierContext.literalSymbol ||
- context == IdentifierContext.literalSymbolContinuation) {
- followingValues = ['.', ';'];
} else {
return false;
}
@@ -2065,10 +2060,7 @@
// could create a method to test whether a given token matches one of the
// patterns.
List<String> initialKeywords;
- if (context == IdentifierContext.labelDeclaration) {
- initialKeywords = statementKeywords();
- } else if (context ==
- IdentifierContext.localFunctionDeclarationContinuation) {
+ if (context == IdentifierContext.localFunctionDeclarationContinuation) {
initialKeywords = statementKeywords();
} else {
return false;
@@ -3871,12 +3863,9 @@
/// ;
/// ```
Token parseLabel(Token token) {
- // TODO(brianwilkerson): Enable this assert.
- // `parseType` is allowing `void` to be a label.
-// assert(token.next.isIdentifier);
- assert(optional(':', token.next.next));
+ assert(token.next.isIdentifier);
token = ensureIdentifier(token, IdentifierContext.labelDeclaration).next;
- expect(':', token);
+ assert(optional(':', token));
listener.handleLabel(token);
return token;
}