add parser listener handleErrorToken event

Change-Id: I11ae5f8d25248b9cc3586edbc6e49037d99bb5a4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97555
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 32bfec5..c0c6e03 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2099,6 +2099,11 @@
     push(ast.emptyStatement(semicolon));
   }
 
+  @override
+  void handleErrorToken(ErrorToken token) {
+    translateErrorToken(token, errorReporter.reportScannerError);
+  }
+
   void handleExpressionFunctionBody(Token arrowToken, Token semicolon) {
     assert(optional('=>', arrowToken) || optional('=', arrowToken));
     assert(optionalOrNull(';', semicolon));
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 399fff8..4c51e12 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -3000,11 +3000,8 @@
   }
 
   void test_expectedInterpolationIdentifier() {
-    StringLiteral literal = parseExpression("'\$x\$'", errors: [
-      usingFastaParser
-          ? expectedError(ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING, 4, 1)
-          : expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 4, 1)
-    ]);
+    StringLiteral literal = parseExpression("'\$x\$'",
+        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 4, 1)]);
     expectNotNullIfNoErrors(literal);
   }
 
@@ -3012,11 +3009,8 @@
     // The scanner inserts an empty string token between the two $'s; we need to
     // make sure that the MISSING_IDENTIFIER error that is generated has a
     // nonzero width so that it will show up in the editor UI.
-    StringLiteral literal = parseExpression("'\$\$foo'", errors: [
-      usingFastaParser
-          ? expectedError(ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING, 2, 1)
-          : expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)
-    ]);
+    StringLiteral literal = parseExpression("'\$\$foo'",
+        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)]);
     expectNotNullIfNoErrors(literal);
   }
 
@@ -3949,11 +3943,8 @@
   }
 
   void test_invalidInterpolationIdentifier_startWithDigit() {
-    StringLiteral literal = parseExpression("'\$1'", errors: [
-      usingFastaParser
-          ? expectedError(ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING, 2, 1)
-          : expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)
-    ]);
+    StringLiteral literal = parseExpression("'\$1'",
+        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)]);
     expectNotNullIfNoErrors(literal);
   }
 
@@ -4707,18 +4698,16 @@
     createParser('(a, {b: 0)');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]
-        : [expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1)]);
+    listener
+        .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1)]);
   }
 
   void test_missingTerminatorForParameterGroup_optional() {
     createParser('(a, [b = 0)');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]
-        : [expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)]);
+    listener
+        .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)]);
   }
 
   void test_missingTypedefParameters_nonVoid() {
@@ -5708,7 +5697,7 @@
     if (usingFastaParser) {
       listener.assertErrors([
         expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)
+        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
       ]);
     } else {
       listener.assertErrors([
@@ -5727,7 +5716,7 @@
     if (usingFastaParser) {
       listener.assertErrors([
         expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)
+        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
       ]);
     } else {
       listener.assertErrors([
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 10f0a20..ed8f7b2 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -1027,6 +1027,11 @@
   }
 
   @override
+  void handleErrorToken(ErrorToken token) {
+    listener?.handleErrorToken(token);
+  }
+
+  @override
   void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
     listener?.handleExpressionFunctionBody(arrowToken, endToken);
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 91ff7bf..8a24cdf 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -10,6 +10,8 @@
 
 import '../quote.dart' show UnescapeErrorListener;
 
+import '../scanner/error_token.dart' show ErrorToken;
+
 import 'assert.dart' show Assert;
 
 import 'formal_parameter_kind.dart' show FormalParameterKind;
@@ -1373,6 +1375,14 @@
   void handleRecoverableError(
       Message message, Token startToken, Token endToken) {}
 
+  /// The parser encountered an [ErrorToken] representing an error
+  /// from the scanner but recovered from it. By default, the error is reported
+  /// by calling [handleRecoverableError] with the message associated
+  /// with the error [token].
+  void handleErrorToken(ErrorToken token) {
+    handleRecoverableError(token.assertionMessage, token, token);
+  }
+
   @override
   void handleUnescapeError(
       Message message, Token location, int stringOffset, int length) {
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index afe9a91..6ec8e5a 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -258,11 +258,6 @@
 /// doesn't matter how we got there, only that we've identified that it's
 /// easier if the parser reports as many errors it can, but informs the
 /// listener if the error is recoverable or not.
-///
-/// Currently, the parser is particularly lax when it comes to the order of
-/// modifiers such as `abstract`, `final`, `static`, etc. Historically, dart2js
-/// would handle such errors in later phases. We hope that these cases will go
-/// away as Fasta matures.
 class Parser {
   Listener listener;
 
@@ -6181,7 +6176,7 @@
   }
 
   void reportErrorToken(ErrorToken token) {
-    listener.handleRecoverableError(token.assertionMessage, token, token);
+    listener.handleErrorToken(token);
   }
 
   Token parseInvalidTopLevelDeclaration(Token token) {
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
index b5cb240..952099d 100644
--- a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
@@ -25,8 +25,7 @@
   /** The current offset in [string]. */
   int scanOffset = -1;
 
-  StringScanner(String string,
-      {bool includeComments: false, bool scanLazyAssignmentOperators: false})
+  StringScanner(String string, {bool includeComments: false})
       : string = ensureZeroTermination(string),
         super(includeComments);