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

Unified Diff: pkg/dart_parser/lib/src/listener.dart

Issue 2650813002: Restructure parser error handling and recovery. (Closed)
Patch Set: Address comments. Created 3 years, 11 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/dart_parser/lib/src/error_kind.dart ('k') | pkg/dart_parser/lib/src/parser.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/dart_parser/lib/src/listener.dart
diff --git a/pkg/dart_parser/lib/src/listener.dart b/pkg/dart_parser/lib/src/listener.dart
index 9d656bbcf94dd29adb6d08d793bf9ed2e8dfaf18..63d0188d6f021a7f083afb978300b04a372429f8 100644
--- a/pkg/dart_parser/lib/src/listener.dart
+++ b/pkg/dart_parser/lib/src/listener.dart
@@ -4,18 +4,9 @@
library dart_parser.listener;
-import 'package:dart_scanner/src/precedence.dart' show
- EOF_INFO,
- IDENTIFIER_INFO;
-
import 'package:dart_scanner/src/token.dart' show
- BadInputToken,
BeginGroupToken,
- ErrorToken,
- StringToken,
- Token,
- UnmatchedToken,
- UnterminatedToken;
+ Token;
import 'error_kind.dart' show
ErrorKind;
@@ -760,216 +751,28 @@ class Listener {
logEvent("YieldStatement");
}
- // TODO(ahe): Rename to `handleUnexpected`.
- Token expected(String string, Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected '$string', but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Move away from this class.
- Token synthesizeIdentifier(Token token) {
- Token synthesizedToken = new StringToken.fromString(
- IDENTIFIER_INFO, '?', token.charOffset);
- synthesizedToken.next = token.next;
- return synthesizedToken;
- }
-
- // TODO(ahe): Rename to `handleIdentifierExpected`.
- Token expectedIdentifier(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected identifier, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleTypeExpected`.
- Token expectedType(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a type, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleExpressionExpected`.
- Token expectedExpression(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected an expression, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Merge with `handleUnexpected` (nee `expected`).
- Token unexpected(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("unexpected token '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleBlockToSkipExpected`.
- Token expectedBlockToSkip(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a block, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleFunctionBodyExpected`.
- Token expectedFunctionBody(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a function body, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleClassBodyExpected`.
- Token expectedClassBody(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a class body, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleClassBodyToSkipExpected`.
- Token expectedClassBodyToSkip(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a class body, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleDeclarationExpected`.
- Token expectedDeclaration(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a declaration, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Rename to `handleUnmatched`.
- Token unmatched(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("unmatched '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- // TODO(ahe): Move away from this class.
- Token skipToEof(Token token) {
- while (!identical(token.info, EOF_INFO)) {
- token = token.next;
- }
- return token;
- }
-
- // TODO(ahe): Merge with `handleError` (nee `reportError`).
- void error(String message, Token token) {
- throw new ParserError.fromTokens(
- token, token, ErrorKind.Unspecified, {'text': message});
- }
-
- // TODO(ahe): Rename to `handleError`.
- void reportError(Token token, ErrorKind kind, [Map arguments = const {}]) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- reportErrorHelper(token, kind, arguments);
- }
- }
-
- // TODO(ahe): Move away from this class.
- void reportErrorHelper(Token token, ErrorKind kind, Map arguments) {
- recoverableErrors.add(
- new ParserError.fromTokens(token, token, kind, arguments));
+ /// An unrecoverable error is an error that the parser can't recover from
+ /// itself, and recovery is left to the listener. If the listener can
+ /// recover, it should return a non-null continuation token. Error recovery
+ /// is tightly coupled to the parser implementation, so to recover from an
+ /// error, one must carefully examine the code in the parser that generates
+ /// the error.
+ ///
+ /// If the listener can't recover, it can throw an exception or return
+ /// `null`. In the latter case, the parser simply skips to EOF which will
+ /// often result in additional parser errors as the parser returns from its
+ /// recursive state.
+ Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
+ throw new ParserError.fromTokens(token, token, kind, arguments);
}
- // TODO(ahe): Move away from this class.
- void reportErrorToken(ErrorToken token) {
- if (token is BadInputToken) {
- String hex = token.character.toRadixString(16);
- if (hex.length < 4) {
- String padding = "0000".substring(hex.length);
- hex = "$padding$hex";
- }
- reportErrorHelper(
- token, ErrorKind.InvalidInputCharacter, {'characterHex': hex});
- } else if (token is UnterminatedToken) {
- ErrorKind kind;
- var arguments = const {};
- switch (token.start) {
- case '1e':
- kind = ErrorKind.MissingExponent;
- break;
- case '"':
- case "'":
- case '"""':
- case "'''":
- case 'r"':
- case "r'":
- case 'r"""':
- case "r'''":
- kind = ErrorKind.UnterminatedString;
- arguments = {'quote': token.start};
- break;
- case '0x':
- kind = ErrorKind.ExpectedHexDigit;
- break;
- case r'$':
- kind = ErrorKind.MalformedStringLiteral;
- break;
- case '/*':
- kind = ErrorKind.UnterminatedComment;
- break;
- default:
- kind = ErrorKind.UnterminatedToken;
- break;
- }
- reportErrorHelper(token, kind, arguments);
- } else if (token is UnmatchedToken) {
- String begin = token.begin.value;
- String end = closeBraceFor(begin);
- reportErrorHelper(
- token, ErrorKind.UnmatchedToken, {'begin': begin, 'end': end});
- } else {
- error(token.assertionMessage, token);
- }
+ /// The parser noticed a syntax error, but was able to recover from it.
+ void handleRecoverableError(Token token, ErrorKind kind, Map arguments) {
+ recoverableErrors.add(
+ new ParserError.fromTokens(token, token, kind, arguments));
}
}
-String closeBraceFor(String openBrace) {
- return const {
- '(': ')',
- '[': ']',
- '{': '}',
- '<': '>',
- r'${': '}',
- }[openBrace];
-}
-
class ParserError {
/// Character offset from the beginning of file where this error starts.
final int beginOffset;
« no previous file with comments | « pkg/dart_parser/lib/src/error_kind.dart ('k') | pkg/dart_parser/lib/src/parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698