Improve parse literal string recovery

This fixes another fasta parser exception
and improves recovery when parsing string literals.

Change-Id: I704b7fcb9dcb2cd01e75623a179f95e6097ccec4
Reviewed-on: https://dart-review.googlesource.com/63000
Commit-Queue: Dan Rubel <danrubel@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
danrubel
2018-07-02 14:58:45 +00:00
committed by commit-bot@chromium.org
parent 771454a1cf
commit 5953e62c69
5 changed files with 72 additions and 20 deletions
+19 -10
View File
@@ -1843,18 +1843,27 @@ class Parser {
}
Token parseStringPart(Token token) {
token = token.next;
while (token.kind != STRING_TOKEN) {
if (token is ErrorToken) {
reportErrorToken(token, true);
} else {
token = reportUnrecoverableErrorWithToken(
token, fasta.templateExpectedString);
Token next = token.next;
if (next.kind != STRING_TOKEN) {
bool errorReported = false;
while (next is ErrorToken) {
errorReported = true;
reportErrorToken(next, true);
token = next;
next = token.next;
}
if (next.kind != STRING_TOKEN) {
if (!errorReported) {
reportRecoverableErrorWithToken(next, fasta.templateExpectedString);
}
next = rewriter
.insertTokenAfter(token,
new SyntheticStringToken(TokenType.STRING, '', next.charOffset))
.next;
}
token = token.next;
}
listener.handleStringPart(token);
return token;
listener.handleStringPart(next);
return next;
}
/// Insert a synthetic identifier after the given [token] and create an error
@@ -1,8 +1,21 @@
library;
import self as self;
import "dart:core" as core;
static method #main() → dynamic {
throw "pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected a String, but got ')'.
static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/regress/issue_29976.dart:7:14: Error: The non-ASCII character '\u0233' (U+00E9) can't be used in identifiers, only in strings and comments.
Try using an US-ASCII letter, a digit, '_' (an underscore), or '\$' (a dollar sign).
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:7:15: Error: String starting with ' must end with '.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:7:7: Error: Can't find '}' to match '\${'.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:10:1: Error: String starting with \" must end with \".", "pkg/front_end/testcases/regress/issue_29976.dart:10:1: Error: Expected a declaration, but got ''.", "pkg/front_end/testcases/regress/issue_29976.dart:7:14: Error: Expected '}' before this.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected a String, but got ')'.
)
^";
^", "pkg/front_end/testcases/regress/issue_29976.dart:9:1: Error: Expected ';' before this.
}
^"]/* from null */;
static method main() → void {
throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#f, 32, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>["x${(let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#x, 33, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})))).*("'")}"]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
@@ -1,8 +1,21 @@
library;
import self as self;
import "dart:core" as core;
static method #main() → dynamic {
throw "pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected a String, but got ')'.
static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/regress/issue_29976.dart:7:14: Error: The non-ASCII character '\u0233' (U+00E9) can't be used in identifiers, only in strings and comments.
Try using an US-ASCII letter, a digit, '_' (an underscore), or '\$' (a dollar sign).
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:7:15: Error: String starting with ' must end with '.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:7:7: Error: Can't find '}' to match '\${'.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:10:1: Error: String starting with \" must end with \".", "pkg/front_end/testcases/regress/issue_29976.dart:10:1: Error: Expected a declaration, but got ''.", "pkg/front_end/testcases/regress/issue_29976.dart:7:14: Error: Expected '}' before this.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected a String, but got ')'.
)
^";
^", "pkg/front_end/testcases/regress/issue_29976.dart:9:1: Error: Expected ';' before this.
}
^"]/* from null */;
static method main() → void {
throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#f, 32, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>["x${(let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#x, 33, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})))).*("'")}"]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
@@ -1,8 +1,25 @@
library;
import self as self;
import "dart:core" as core;
static method #main() → dynamic {
throw "pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected a String, but got ')'.
static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/regress/issue_29976.dart:7:14: Error: The non-ASCII character '\u0233' (U+00E9) can't be used in identifiers, only in strings and comments.
Try using an US-ASCII letter, a digit, '_' (an underscore), or '\$' (a dollar sign).
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:7:15: Error: String starting with ' must end with '.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:7:7: Error: Can't find '}' to match '\${'.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:10:1: Error: String starting with \" must end with \".", "pkg/front_end/testcases/regress/issue_29976.dart:10:1: Error: Expected a declaration, but got ''.", "pkg/front_end/testcases/regress/issue_29976.dart:7:9: Error: Getter not found: 'x'.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:7:14: Error: Expected '}' before this.
\"x\${x*\"'\"\u0233'}x
^", "pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected a String, but got ')'.
)
^";
^", "pkg/front_end/testcases/regress/issue_29976.dart:6:3: Error: Method not found: 'f'.
f(
^", "pkg/front_end/testcases/regress/issue_29976.dart:9:1: Error: Expected ';' before this.
}
^"]/* from null */;
static method main() → void {
throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#f, 32, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>["x${(let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#x, 33, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})))).*("'")}"]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+1 -1
View File
@@ -196,7 +196,7 @@ rasta/unresolved_recovery: Fail
rasta/unsupported_platform_library: Fail
regress/issue_29975: Fail # Issue 29975.
regress/issue_29976: RuntimeError # Issue 29976.
regress/issue_29976: TypeCheckError # Issue 29976.
regress/issue_29982: Fail # Issue 29982.
regress/issue_30836: RuntimeError # Issue 30836.
regress/issue_31184: TypeCheckError