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

Unified Diff: pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart

Issue 2981343002: improve fasta closing brace recovery (Closed)
Patch Set: rebase Created 3 years, 5 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_test.dart ('k') | pkg/front_end/test/scanner_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
diff --git a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
index 43159a580a7d1846560494432beb8c246720ea9f..a5d7b09fe6e530e0e916e2975d237970694f92e8 100644
--- a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
@@ -139,16 +139,17 @@ abstract class ArrayBasedScanner extends AbstractScanner {
/**
* Appends a token that begins an end group, represented by [type].
* It handles the group end tokens '}', ')' and ']'. The tokens '>' and
- * '>>' are handled separately bo [appendGt] and [appendGtGt].
+ * '>>' are handled separately by [appendGt] and [appendGtGt].
*/
int appendEndGroup(TokenType type, int openKind) {
assert(!identical(openKind, LT_TOKEN)); // openKind is < for > and >>
- discardBeginGroupUntil(openKind);
- appendPrecedenceToken(type);
- Token close = tail;
- if (groupingStack.isEmpty) {
+ if (!discardBeginGroupUntil(openKind)) {
+ // No begin group found. Just continue.
+ appendPrecedenceToken(type);
return advance();
}
+ appendPrecedenceToken(type);
+ Token close = tail;
BeginToken begin = groupingStack.head;
if (!identical(begin.kind, openKind)) {
assert(begin.kind == STRING_INTERPOLATION_TOKEN &&
@@ -166,21 +167,52 @@ abstract class ArrayBasedScanner extends AbstractScanner {
}
/**
- * Discards begin group tokens until a match with [openKind] is found.
- * This recovers nicely from from a situation like "{[}".
+ * If a begin group token matches [openKind],
+ * then discard begin group tokens up to that match and return `true`,
+ * otherwise return `false`.
+ * This recovers nicely from from situations like "{[}" and "{foo());}",
+ * but not "foo(() {bar());});
*/
- void discardBeginGroupUntil(int openKind) {
- while (!groupingStack.isEmpty) {
+ bool discardBeginGroupUntil(int openKind) {
+ Link<BeginToken> originalStack = groupingStack;
+
+ bool first = true;
+ do {
// Don't report unmatched errors for <; it is also the less-than operator.
discardOpenLt();
- if (groupingStack.isEmpty) return;
+ if (groupingStack.isEmpty) break; // recover
BeginToken begin = groupingStack.head;
- if (openKind == begin.kind) return;
- if (openKind == OPEN_CURLY_BRACKET_TOKEN &&
- begin.kind == STRING_INTERPOLATION_TOKEN) return;
- unmatchedBeginGroup(begin);
+ if (openKind == begin.kind ||
+ (openKind == OPEN_CURLY_BRACKET_TOKEN &&
+ begin.kind == STRING_INTERPOLATION_TOKEN)) {
+ if (first) {
+ // If the expected opener has been found on the first pass
+ // then no recovery necessary.
+ return true;
+ }
+ break; // recover
+ }
+ first = false;
groupingStack = groupingStack.tail;
+ } while (!groupingStack.isEmpty);
+
+ // If the stack does not have any opener of the given type,
+ // then return without discarding anything.
+ // This recovers nicely from from situations like "{foo());}".
+ if (groupingStack.isEmpty) {
+ groupingStack = originalStack;
+ return false;
+ }
+
+ // Insert synthetic closers and report errors for any unbalanced openers.
+ // This recovers nicely from from situations like "{[}".
+ while (!identical(originalStack, groupingStack)) {
+ // Don't report unmatched errors for <; it is also the less-than operator.
+ if (!identical(groupingStack.head.kind, LT_TOKEN))
+ unmatchedBeginGroup(originalStack.head);
+ originalStack = originalStack.tail;
}
+ return true;
}
/**
« no previous file with comments | « pkg/analyzer/test/generated/parser_test.dart ('k') | pkg/front_end/test/scanner_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698