Version 2.12.0-145.0.dev

Merge commit 'b16c212776da8dd65921f8cd858b9997cc385fbe' into 'dev'
diff --git a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
index f9e05e7..5cade7b 100644
--- a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
@@ -4,6 +4,8 @@
 
 // ignore_for_file: avoid_function_literals_in_foreach_calls
 
+import 'dart:math' show pow;
+
 import 'package:benchmark_harness/benchmark_harness.dart';
 import 'package:fixnum/fixnum.dart';
 
@@ -103,6 +105,41 @@
   }
 }
 
+class ParseIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final int seed;
+  final List<String> strings = [];
+
+  ParseIntBenchmark(String name, this.bits)
+      : seed = (pow(2, bits) as int) - 1,
+        super(name);
+
+  @override
+  void setup() {
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (b.bitLength < bits) {
+        b = seed;
+      }
+      final string = b.toString();
+      strings.add(string);
+      totalLength += string.length;
+      b = b - b ~/ 256;
+    }
+  }
+
+  @override
+  void run() {
+    for (final s in strings) {
+      final b = int.parse(s);
+      sink1 = s;
+      sink2 = b;
+    }
+    check(sink2.isEven);
+  }
+}
+
 class ParseJsBigIntBenchmark extends BenchmarkBase {
   final int bits;
   final Object seed;
@@ -181,6 +218,45 @@
   }
 }
 
+class FormatIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final int seed;
+  final List<int> values = [];
+
+  FormatIntBenchmark(String name, this.bits)
+      : seed = (pow(2, bits) as int) - 1,
+        super(name);
+
+  @override
+  void setup() {
+    var b = seed;
+    var totalLength = 0;
+    int kk = b ~/ 100000;
+    while (totalLength < requiredDigits) {
+      if (b.bitLength < bits) {
+        b = seed - ++kk;
+      }
+      final string = b.toString();
+      values.add(b - 4096); // We add 'one' back later.
+      totalLength += string.length;
+      b = b - (b ~/ 256);
+    }
+  }
+
+  @override
+  void run() {
+    for (final b0 in values) {
+      // Instances might cache `toString()`, so use arithmetic to create a new
+      // instance to try to protect against measuring a cached string.
+      final b = b0 + 4096;
+      final s = b.toString();
+      sink1 = s;
+      sink2 = b;
+    }
+    check(sink2.isEven);
+  }
+}
+
 class FormatInt64Benchmark extends BenchmarkBase {
   final int bits;
   final Int64 seed;
@@ -293,6 +369,9 @@
 
 void main() {
   final benchmarks = [
+    () => ParseIntBenchmark('Int.parse.0009.bits', 9),
+    () => ParseIntBenchmark('Int.parse.0032.bits', 32),
+    () => ParseIntBenchmark('Int.parse.0064.bits', 63),
     () => ParseInt64Benchmark('Int64.parse.0009.bits', 9),
     () => ParseInt64Benchmark('Int64.parse.0032.bits', 32),
     () => ParseInt64Benchmark('Int64.parse.0064.bits', 64),
@@ -308,6 +387,9 @@
     selectParseNativeBigIntBenchmark('JsBigInt.parse.0256.bits', 256),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.1024.bits', 1024),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.4096.bits', 4096),
+    () => FormatIntBenchmark('Int.toString.0009.bits', 9),
+    () => FormatIntBenchmark('Int.toString.0032.bits', 32),
+    () => FormatIntBenchmark('Int.toString.0064.bits', 63),
     () => FormatInt64Benchmark('Int64.toString.0009.bits', 9),
     () => FormatInt64Benchmark('Int64.toString.0032.bits', 32),
     () => FormatInt64Benchmark('Int64.toString.0064.bits', 64),
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
index 3ddef42..00bed8c 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
@@ -27,8 +27,8 @@
             ? (_fromDouble ? "'''" : '"""')
             : (_fromDouble ? "'" : '"');
         var quoteLength = literal.isMultiline ? 3 : 1;
-        var lexeme = literal.literal.lexeme;
-        if (!lexeme.contains(newQuote)) {
+        var token = literal.literal;
+        if (!token.isSynthetic && !token.lexeme.contains(newQuote)) {
           await builder.addDartFileEdit(file, (builder) {
             builder.addSimpleReplacement(
                 SourceRange(
@@ -53,8 +53,8 @@
         for (var i = 0; i < elements.length; i++) {
           var element = elements[i];
           if (element is InterpolationString) {
-            var lexeme = element.contents.lexeme;
-            if (lexeme.contains(newQuote)) {
+            var token = element.contents;
+            if (token.isSynthetic || token.lexeme.contains(newQuote)) {
               return null;
             }
           }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
index 15a289f..e394659 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
@@ -21,7 +21,7 @@
     }
     if (node is SingleStringLiteral) {
       var literal = node;
-      if (!literal.isMultiline) {
+      if (!literal.isSynthetic && !literal.isMultiline) {
         await builder.addDartFileEdit(file, (builder) {
           var newQuote = literal.isSingleQuoted ? "'''" : '"""';
           builder.addReplacement(
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
index 080bc4f9..8802226 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
@@ -60,27 +60,36 @@
       }
     } else if (parent is IfStatement) {
       if (parent.elseStatement == null && _conditionIsTrue) {
-        var body = _extractBody(parent);
-        body = utils.indentSourceLeftRight(body);
-        await builder.addDartFileEdit(file, (builder) {
-          builder.addSimpleReplacement(
-              range.startOffsetEndOffset(
-                  parent.offset, utils.getLineContentEnd(parent.end)),
-              body);
-        });
+        await _ifStatement(parent, builder);
       }
     }
   }
 
-  String _extractBody(IfStatement statement) {
-    var body = statement.thenStatement;
-    if (body is Block) {
-      var statements = body.statements;
-      return utils.getRangeText(range.startOffsetEndOffset(
-          statements.first.offset,
-          utils.getLineContentEnd(statements.last.end)));
-    }
-    return utils.getNodeText(body);
+  Future<void> _ifStatement(IfStatement node, ChangeBuilder builder) async {
+    await builder.addDartFileEdit(file, (builder) {
+      var nodeRange = utils.getLinesRangeStatements([node]);
+
+      String bodyCode;
+      var body = node.thenStatement;
+      if (body is Block) {
+        var statements = body.statements;
+        if (statements.isEmpty) {
+          builder.addDeletion(nodeRange);
+          return;
+        } else {
+          bodyCode = utils.getRangeText(
+            utils.getLinesRangeStatements(statements),
+          );
+        }
+      } else {
+        bodyCode = utils.getRangeText(
+          utils.getLinesRangeStatements([body]),
+        );
+      }
+
+      bodyCode = utils.indentSourceLeftRight(bodyCode);
+      builder.addSimpleReplacement(nodeRange, bodyCode);
+    });
   }
 
   /// Use the [builder] to add an edit to delete the operator and given
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 63573c1..89353f4 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -13,7 +13,6 @@
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
-import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
 import 'package:test/test.dart';
@@ -96,7 +95,7 @@
   /// where there is no `new` or `const` keyword.
   bool get suggestConstructorsWithoutNew => true;
 
-  bool get usingFastaParser => analyzer.Parser.useFasta;
+  bool get usingFastaParser => true;
 
   void addTestSource(String content) {
     expect(completionOffset, isNull, reason: 'Call addTestUnit exactly once');
diff --git a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
index 2235fe2..510843f 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
@@ -6,6 +6,7 @@
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
+import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/instrumentation/service.dart';
 import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
@@ -193,7 +194,7 @@
 
   Future<List<Assist>> _computeAssists() async {
     var context = DartAssistContextImpl(
-      InstrumentationService.NULL_SERVICE,
+      _TestInstrumentationService(),
       workspace,
       testAnalysisResult,
       _offset,
@@ -212,3 +213,19 @@
     return positions;
   }
 }
+
+class _TestInstrumentationService implements InstrumentationService {
+  @override
+  void logException(
+    exception, [
+    StackTrace stackTrace,
+    List<InstrumentationServiceAttachment> attachments,
+  ]) {
+    throw CaughtException(exception, stackTrace);
+  }
+
+  @override
+  dynamic noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart
index 6f8f3d2..813e4bc 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart
@@ -54,6 +54,16 @@
 ''');
   }
 
+  Future<void> test_one_interpolation_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode(r'''
+void f(int a) {
+  '$a
+}
+''');
+    await assertNoAssistAt("'");
+  }
+
   Future<void> test_one_raw() async {
     await resolveTestCode('''
 main() {
@@ -80,6 +90,16 @@
 ''');
   }
 
+  Future<void> test_one_simple_unterminated_empty() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  '
+}
+''');
+    await assertNoAssistAt("'");
+  }
+
   Future<void> test_three_embeddedTarget() async {
     await resolveTestCode("""
 main() {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart
index 316515d..c7f2b1e 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart
@@ -103,6 +103,16 @@
 ''');
   }
 
+  Future<void> test_doubleQuoted_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  "
+}
+''');
+    await assertNoAssistAt('"');
+  }
+
   Future<void> test_singleQuoted() async {
     await resolveTestCode('''
 main() {
@@ -177,4 +187,14 @@
 }
 """);
   }
+
+  Future<void> test_singleQuoted_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  '
+}
+''');
+    await assertNoAssistAt("'");
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart
index 9e925c0..4214de8 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart
@@ -55,6 +55,16 @@
 ''');
   }
 
+  Future<void> test_one_interpolation_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode(r'''
+void f(int a) {
+  "$a
+}
+''');
+    await assertNoAssistAt('"');
+  }
+
   Future<void> test_one_raw() async {
     await resolveTestCode('''
 main() {
@@ -92,6 +102,16 @@
     await assertNoAssist();
   }
 
+  Future<void> test_one_simple_unterminated_empty() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  "
+}
+''');
+    await assertNoAssistAt('"');
+  }
+
   Future<void> test_three_embeddedTarget() async {
     await resolveTestCode('''
 main() {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
index 356d591..5494406 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
@@ -146,7 +146,7 @@
 ''');
   }
 
-  Future<void> test_ifStatement() async {
+  Future<void> test_ifStatement_thenBlock() async {
     await resolveTestCode('''
 void f(String s) {
   if (s != null) {
@@ -160,4 +160,31 @@
 }
 ''');
   }
+
+  Future<void> test_ifStatement_thenBlock_empty() async {
+    await resolveTestCode('''
+void f(String s) {
+  if (s != null) {
+  }
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+}
+''');
+  }
+
+  Future<void> test_ifStatement_thenStatement() async {
+    await resolveTestCode('''
+void f(String s) {
+  if (s != null)
+    print(s);
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s);
+}
+''');
+  }
 }
diff --git a/pkg/analysis_server/test/utils/test_support.dart b/pkg/analysis_server/test/utils/test_support.dart
index 959be9b..2d176d5 100644
--- a/pkg/analysis_server/test/utils/test_support.dart
+++ b/pkg/analysis_server/test/utils/test_support.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 
@@ -119,7 +118,7 @@
   final Map<Source, LineInfo> _lineInfoMap = <Source, LineInfo>{};
 
   /// Initialize a newly created error listener to collect errors.
-  GatheringErrorListener({this.checkRanges = Parser.useFasta});
+  GatheringErrorListener({this.checkRanges = true});
 
   /// Return the errors that were collected.
   List<AnalysisError> get errors => _errors;
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index a37f6a7..942e449 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -592,7 +592,6 @@
   }
 
   CompilationUnit _parse(AnalysisErrorListener errorListener) {
-    AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
     if (source == null) {
       return _createEmptyCompilationUnit();
     }
@@ -608,12 +607,10 @@
     Token token = scanner.tokenize(reportScannerErrors: false);
     LineInfo lineInfo = LineInfo(scanner.lineStarts);
 
-    bool useFasta = analysisOptions.useFastaParser;
     Parser parser = Parser(
       source,
       errorListener,
       featureSet: scanner.featureSet,
-      useFasta: useFasta,
     );
     parser.enableOptionalNewAndConst = true;
 
@@ -755,7 +752,6 @@
   final FileContentOverlay _contentOverlay;
   final SourceFactory _sourceFactory;
   final Workspace _workspace;
-  final AnalysisOptions _analysisOptions;
   final DeclaredVariables _declaredVariables;
   final Uint32List _saltForUnlinked;
   final Uint32List _saltForElements;
@@ -820,7 +816,8 @@
     this.contextName,
     this._sourceFactory,
     this._workspace,
-    this._analysisOptions,
+    @Deprecated('No longer used; will be removed')
+        AnalysisOptions analysisOptions,
     this._declaredVariables,
     this._saltForUnlinked,
     this._saltForElements,
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index 26887ce..971bc79 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -177,8 +177,6 @@
   }
 
   CompilationUnit parse(AnalysisErrorListener errorListener, String content) {
-    AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
-
     CharSequenceReader reader = CharSequenceReader(content);
     Scanner scanner = Scanner(source, reader, errorListener)
       ..configureFeatures(
@@ -190,7 +188,6 @@
     Token token = scanner.tokenize(reportScannerErrors: false);
     LineInfo lineInfo = LineInfo(scanner.lineStarts);
 
-    bool useFasta = analysisOptions.useFastaParser;
     // Pass the feature set from the scanner to the parser
     // because the scanner may have detected a language version comment
     // and downgraded the feature set it holds.
@@ -198,7 +195,6 @@
       source,
       errorListener,
       featureSet: scanner.featureSet,
-      useFasta: useFasta,
     );
     parser.enableOptionalNewAndConst = true;
     CompilationUnit unit = parser.parseCompilationUnit(token);
@@ -460,7 +456,6 @@
   final CiderByteStore _byteStore;
   final SourceFactory _sourceFactory;
   final Workspace _workspace;
-  final AnalysisOptions _analysisOptions;
   final Uint32List _linkedSalt;
 
   /// A function that returns the digest for a file as a String. The function
@@ -486,7 +481,8 @@
     this._byteStore,
     this._sourceFactory,
     this._workspace,
-    this._analysisOptions,
+    @Deprecated('No longer used; will be removed')
+        AnalysisOptions analysisOptions,
     this._linkedSalt,
     this.featureSetProvider,
     this.getFileDigest,
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 89c2ca2..a76eef9 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -4,40 +4,25 @@
 
 library analyzer.parser;
 
-import 'dart:collection';
-import "dart:math" as math;
-
 import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'
     as fasta;
 import 'package:_fe_analyzer_shared/src/parser/member_kind.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/parser/type_info.dart' as fasta;
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/fasta/ast_builder.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
-import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:meta/meta.dart';
 
 export 'package:analyzer/src/dart/ast/utilities.dart' show ResolutionCopier;
 export 'package:analyzer/src/dart/error/syntactic_errors.dart';
 
-part 'parser_fasta.dart';
-
 /// A simple data-holder for a method that needs to return multiple values.
 class CommentAndMetadata {
   /// The documentation comment that was parsed, or `null` if none was given.
@@ -129,7873 +114,261 @@
 
 /// A parser used to parse tokens into an AST structure.
 class Parser {
-  static String ASYNC = Keyword.ASYNC.lexeme;
+  Token currentToken;
 
-  static final String _AWAIT = Keyword.AWAIT.lexeme;
+  /// The fasta parser being wrapped.
+  final fasta.Parser fastaParser;
 
-  static final String _HIDE = Keyword.HIDE.lexeme;
+  /// The builder which creates the analyzer AST data structures
+  /// based on the Fasta parser.
+  final AstBuilder astBuilder;
 
-  static final String _SHOW = Keyword.SHOW.lexeme;
-
-  static final String SYNC = Keyword.SYNC.lexeme;
-
-  static final String _YIELD = Keyword.YIELD.lexeme;
-
-  static const int _MAX_TREE_DEPTH = 300;
-
-  /// A flag indicating whether the analyzer [Parser] factory method
-  /// will return a fasta based parser or an analyzer based parser.
-  static const bool useFasta = true;
-
-  /// The source being parsed.
-  final Source _source;
-
-  /// The error listener that will be informed of any errors that are found
-  /// during the parse.
-  final AnalysisErrorListener _errorListener;
-
-  /// An [_errorListener] lock, if more than `0`, then errors are not reported.
-  int _errorListenerLock = 0;
-
-  /// A flag indicating whether the parser should parse instance creation
-  /// expressions that lack either the `new` or `const` keyword.
-  bool _enableOptionalNewAndConst = true;
-
-  /// A flag indicating whether parser is to parse function bodies.
-  bool _parseFunctionBodies = true;
-
-  /// The next token to be parsed.
-  Token _currentToken;
-
-  /// The depth of the current AST. When this depth is too high, so we're at the
-  /// risk of overflowing the stack, we stop parsing and report an error.
-  int _treeDepth = 0;
-
-  /// A flag indicating whether the parser is currently in a function body
-  /// marked as being 'async'.
-  bool _inAsync = false;
-
-  /// A flag indicating whether the parser is currently in a function body
-  ///  marked(by a star) as being a generator.
-  bool _inGenerator = false;
-
-  /// A flag indicating whether the parser is currently in the body of a loop.
-  bool _inLoop = false;
-
-  /// A flag indicating whether the parser is currently in a switch statement.
-  bool _inSwitch = false;
-
-  /// A flag indicating whether the parser is currently in a constructor field
-  /// initializer, with no intervening parentheses, braces, or brackets.
-  bool _inInitializer = false;
-
-  /// A flag indicating whether the parser is to parse generic method syntax.
-  @deprecated
-  bool parseGenericMethods = false;
-
-  bool allowNativeClause;
-
-  FeatureSet _featureSet;
-
-  /// Initialize a newly created parser to parse tokens in the given [_source]
-  /// and to report any errors that are found to the given [_errorListener].
-  factory Parser(Source source, AnalysisErrorListener errorListener,
-      {bool useFasta, @required FeatureSet featureSet}) {
-    featureSet ??= FeatureSet.latestLanguageVersion();
-    if (useFasta ?? Parser.useFasta) {
-      return _Parser2(source, errorListener, featureSet,
-          allowNativeClause: true);
-    } else {
-      return Parser.withoutFasta(source, errorListener, featureSet: featureSet);
-    }
+  Parser(Source source, AnalysisErrorListener errorListener,
+      {@required FeatureSet featureSet, bool allowNativeClause = true})
+      : fastaParser = fasta.Parser(null),
+        astBuilder = AstBuilder(
+            ErrorReporter(
+              errorListener,
+              source,
+              isNonNullableByDefault:
+                  featureSet.isEnabled(Feature.non_nullable),
+            ),
+            source.uri,
+            true,
+            featureSet) {
+    fastaParser.listener = astBuilder;
+    astBuilder.parser = fastaParser;
+    astBuilder.allowNativeClause = allowNativeClause;
   }
 
-  /// Creates a parser using the old (legacy) analyzer parsing logic.
-  ///
-  /// In a future major version release of the analyzer, the [featureSet]
-  /// argument will be required.
-  Parser.withoutFasta(this._source, this._errorListener,
-      {FeatureSet featureSet}) {
-    if (featureSet != null) {
-      _configureFeatures(featureSet);
-    }
+  set allowNativeClause(bool value) {
+    astBuilder.allowNativeClause = value;
   }
 
-  /// Return the current token.
-  Token get currentToken => _currentToken;
+  bool get enableOptionalNewAndConst => false;
 
-  /// Set the token with which the parse is to begin to the given [token].
-  set currentToken(Token token) {
-    _currentToken = token;
-  }
+  set enableOptionalNewAndConst(bool enable) {}
 
-  /// Return `true` if the parser is to parse asserts in the initializer list of
-  /// a constructor.
-  @deprecated
-  bool get enableAssertInitializer => true;
-
-  /// Set whether the parser is to parse asserts in the initializer list of a
-  /// constructor to match the given [enable] flag.
-  @deprecated
-  set enableAssertInitializer(bool enable) {}
-
-  /// Return `true` if the parser should parse instance creation expressions
-  /// that lack either the `new` or `const` keyword.
-  bool get enableOptionalNewAndConst => _enableOptionalNewAndConst;
-
-  /// Set whether the parser should parse instance creation expressions that
-  /// lack either the `new` or `const` keyword.
-  set enableOptionalNewAndConst(bool enable) {
-    _enableOptionalNewAndConst = enable;
-  }
-
-  /// Enables or disables parsing of set literals.
   set enableSetLiterals(bool value) {
     // TODO(danrubel): Remove this method once the reference to this flag
     // has been removed from dartfmt.
   }
 
-  /// Return `true` if the parser is to allow URI's in part-of directives.
-  @deprecated
-  bool get enableUriInPartOf => true;
-
-  /// Set whether the parser is to allow URI's in part-of directives to the
-  /// given [enable] flag.
-  @deprecated
-  set enableUriInPartOf(bool enable) {}
-
-  /// Return `true` if the current token is the first token of a return type
-  /// that is followed by an identifier, possibly followed by a list of type
-  /// parameters, followed by a left-parenthesis. This is used by
-  /// [parseTypeAlias] to determine whether or not to parse a return type.
-  bool get hasReturnTypeInTypeAlias {
-    // TODO(brianwilkerson) This is too expensive as implemented and needs to be
-    // re-implemented or removed.
-    Token next = skipTypeAnnotation(_currentToken);
-    if (next == null) {
-      return false;
-    }
-    return _tokenMatchesIdentifier(next);
-  }
-
-  /// Set whether the parser is to parse the async support.
-  ///
-  /// Support for removing the 'async' library has been removed.
-  @deprecated
-  set parseAsync(bool parseAsync) {}
-
-  @deprecated
-  bool get parseConditionalDirectives => true;
-
-  @deprecated
-  set parseConditionalDirectives(bool value) {}
-
-  /// Set whether parser is to parse function bodies.
   set parseFunctionBodies(bool parseFunctionBodies) {
-    _parseFunctionBodies = parseFunctionBodies;
+    astBuilder.parseFunctionBodies = parseFunctionBodies;
   }
 
-  /// Return the content of a string with the given literal representation. The
-  /// [lexeme] is the literal representation of the string. The flag [isFirst]
-  /// is `true` if this is the first token in a string literal. The flag
-  /// [isLast] is `true` if this is the last token in a string literal.
-  String computeStringValue(String lexeme, bool isFirst, bool isLast) {
-    StringLexemeHelper helper = StringLexemeHelper(lexeme, isFirst, isLast);
-    int start = helper.start;
-    int end = helper.end;
-    bool stringEndsAfterStart = end >= start;
-    assert(stringEndsAfterStart);
-    if (!stringEndsAfterStart) {
-      AnalysisEngine.instance.instrumentationService.logError(
-          "Internal error: computeStringValue($lexeme, $isFirst, $isLast)");
-      return "";
+  /// Append the given token to the end of the token stream,
+  /// and update the token's offset.
+  void appendToken(Token token, Token newToken) {
+    while (!token.next.isEof) {
+      token = token.next;
     }
-    if (helper.isRaw) {
-      return lexeme.substring(start, end);
-    }
-    StringBuffer buffer = StringBuffer();
-    int index = start;
-    while (index < end) {
-      index = _translateCharacter(buffer, lexeme, index);
-    }
-    return buffer.toString();
+    newToken
+      ..offset = token.end
+      ..setNext(token.next);
+    token.setNext(newToken);
   }
 
-  /// Return a synthetic identifier.
-  SimpleIdentifier createSyntheticIdentifier({bool isDeclaration = false}) {
-    Token syntheticToken;
-    if (_currentToken.type.isKeyword) {
-      // Consider current keyword token as an identifier.
-      // It is not always true, e.g. "^is T" where "^" is place the place for
-      // synthetic identifier. By creating SyntheticStringToken we can
-      // distinguish a real identifier from synthetic. In the code completion
-      // behavior will depend on a cursor position - before or on "is".
-      syntheticToken = _injectToken(SyntheticStringToken(
-          TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset));
-    } else {
-      syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER);
-    }
-    return astFactory.simpleIdentifier(syntheticToken,
-        isDeclaration: isDeclaration);
-  }
+  Expression parseAdditiveExpression() => parseExpression2();
 
-  /// Return a synthetic string literal.
-  SimpleStringLiteral createSyntheticStringLiteral() => astFactory
-      .simpleStringLiteral(_createSyntheticToken(TokenType.STRING), "");
-
-  /// Advance to the next token in the token stream, making it the new current
-  /// token and return the token that was current before this method was
-  /// invoked.
-  Token getAndAdvance() {
-    Token token = _currentToken;
-    _currentToken = _currentToken.next;
-    return token;
-  }
-
-  /// Return `true` if the current token appears to be the beginning of a
-  /// function declaration.
-  bool isFunctionDeclaration() {
-    Keyword keyword = _currentToken.keyword;
-    Token afterReturnType = skipTypeWithoutFunction(_currentToken);
-    if (afterReturnType != null &&
-        _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) {
-      afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType);
-    }
-    // If there was no return type, because it was optional, go back
-    // to where we started.
-    afterReturnType ??= _currentToken;
-    Token afterIdentifier = skipSimpleIdentifier(afterReturnType);
-
-    // It's possible that we parsed the function name as if it were a type
-    // name, so see whether it makes sense if we assume that there is no type.
-    afterIdentifier ??= skipSimpleIdentifier(_currentToken);
-    if (afterIdentifier == null) {
-      return false;
-    }
-    if (isFunctionExpression(afterIdentifier)) {
-      return true;
-    }
-    // It's possible that we have found a getter. While this isn't valid at this
-    // point we test for it in order to recover better.
-    if (keyword == Keyword.GET) {
-      Token afterName = skipSimpleIdentifier(_currentToken.next);
-      if (afterName == null) {
-        return false;
-      }
-      TokenType type = afterName.type;
-      return type == TokenType.FUNCTION || type == TokenType.OPEN_CURLY_BRACKET;
-    } else if (_tokenMatchesKeyword(afterReturnType, Keyword.GET)) {
-      Token afterName = skipSimpleIdentifier(afterReturnType.next);
-      if (afterName == null) {
-        return false;
-      }
-      TokenType type = afterName.type;
-      return type == TokenType.FUNCTION || type == TokenType.OPEN_CURLY_BRACKET;
-    }
-    return false;
-  }
-
-  /// Return `true` if the given [token] appears to be the beginning of a
-  /// function expression.
-  bool isFunctionExpression(Token token) {
-    // Function expressions aren't allowed in initializer lists.
-    if (_inInitializer) {
-      return false;
-    }
-    Token afterTypeParameters = _skipTypeParameterList(token);
-    afterTypeParameters ??= token;
-    Token afterParameters = _skipFormalParameterList(afterTypeParameters);
-    if (afterParameters == null) {
-      return false;
-    }
-    if (afterParameters.matchesAny(
-        const <TokenType>[TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
-      return true;
-    }
-    String lexeme = afterParameters.lexeme;
-    return lexeme == ASYNC || lexeme == SYNC;
-  }
-
-  /// Return `true` if the current token is the first token in an initialized
-  /// variable declaration rather than an expression. This method assumes that
-  /// we have already skipped past any metadata that might be associated with
-  /// the declaration.
-  ///
-  ///     initializedVariableDeclaration ::=
-  ///         declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
-  ///
-  ///     declaredIdentifier ::=
-  ///         metadata finalConstVarOrType identifier
-  ///
-  ///     finalConstVarOrType ::=
-  ///         'final' type?
-  ///       | 'const' type?
-  ///       | 'var'
-  ///       | type
-  ///
-  ///     type ::=
-  ///         qualified typeArguments?
-  ///
-  ///     initializedIdentifier ::=
-  ///         identifier ('=' expression)?
-  bool isInitializedVariableDeclaration() {
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.FINAL ||
-        keyword == Keyword.VAR ||
-        keyword == Keyword.VOID) {
-      // An expression cannot start with a keyword other than 'const',
-      // 'rethrow', or 'throw'.
-      return true;
-    }
-    if (keyword == Keyword.CONST) {
-      // Look to see whether we might be at the start of a list or map literal,
-      // otherwise this should be the start of a variable declaration.
-      return !_peek().matchesAny(const <TokenType>[
-        TokenType.LT,
-        TokenType.OPEN_CURLY_BRACKET,
-        TokenType.OPEN_SQUARE_BRACKET,
-        TokenType.INDEX
-      ]);
-    }
-    bool allowAdditionalTokens = true;
-    // We know that we have an identifier, and need to see whether it might be
-    // a type name.
-    if (_currentToken.type != TokenType.IDENTIFIER) {
-      allowAdditionalTokens = false;
-    }
-    Token token = skipTypeName(_currentToken);
-    if (token == null) {
-      // There was no type name, so this can't be a declaration.
-      return false;
-    }
-    while (_atGenericFunctionTypeAfterReturnType(token)) {
-      token = skipGenericFunctionTypeAfterReturnType(token);
-      if (token == null) {
-        // There was no type name, so this can't be a declaration.
-        return false;
-      }
-    }
-    if (token.type != TokenType.IDENTIFIER) {
-      allowAdditionalTokens = false;
-    }
-    token = skipSimpleIdentifier(token);
-    if (token == null) {
-      return false;
-    }
-    TokenType type = token.type;
-    // Usual cases in valid code:
-    //     String v = '';
-    //     String v, v2;
-    //     String v;
-    //     for (String item in items) {}
-    if (type == TokenType.EQ ||
-        type == TokenType.COMMA ||
-        type == TokenType.SEMICOLON ||
-        token.keyword == Keyword.IN) {
-      return true;
-    }
-    // It is OK to parse as a variable declaration in these cases:
-    //     String v }
-    //     String v if (true) print('OK');
-    //     String v { print(42); }
-    // ...but not in these cases:
-    //     get getterName {
-    //     String get getterName
-    if (allowAdditionalTokens) {
-      if (type == TokenType.CLOSE_CURLY_BRACKET ||
-          type.isKeyword ||
-          type == TokenType.IDENTIFIER ||
-          type == TokenType.OPEN_CURLY_BRACKET) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Return `true` if the current token appears to be the beginning of a switch
-  /// member.
-  bool isSwitchMember() {
-    Token token = _currentToken;
-    while (_tokenMatches(token, TokenType.IDENTIFIER) &&
-        _tokenMatches(token.next, TokenType.COLON)) {
-      token = token.next.next;
-    }
-    Keyword keyword = token.keyword;
-    return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
-  }
-
-  /// Parse an additive expression. Return the additive expression that was
-  /// parsed.
-  ///
-  ///     additiveExpression ::=
-  ///         multiplicativeExpression (additiveOperator multiplicativeExpression)*
-  ///       | 'super' (additiveOperator multiplicativeExpression)+
-  Expression parseAdditiveExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isAdditiveOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseMultiplicativeExpression();
-    }
-    while (_currentToken.type.isAdditiveOperator) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseMultiplicativeExpression());
-    }
-    return expression;
-  }
-
-  /// Parse an annotation. Return the annotation that was parsed.
-  ///
-  /// This method assumes that the current token matches [TokenType.AT].
-  ///
-  ///     annotation ::=
-  ///         '@' qualified ('.' identifier)? arguments?
-  Annotation parseAnnotation() {
-    Token atSign = getAndAdvance();
-    Identifier name = parsePrefixedIdentifier();
-    Token period;
-    SimpleIdentifier constructorName;
-    if (_matches(TokenType.PERIOD)) {
-      period = getAndAdvance();
-      constructorName = parseSimpleIdentifier();
-    }
-    ArgumentList arguments;
-    if (_matches(TokenType.OPEN_PAREN)) {
-      arguments = parseArgumentList();
-    }
-    return astFactory.annotation(
-        atSign, name, period, constructorName, arguments);
-  }
-
-  /// Parse an argument. Return the argument that was parsed.
-  ///
-  ///     argument ::=
-  ///         namedArgument
-  ///       | expression
-  ///
-  ///     namedArgument ::=
-  ///         label expression
   Expression parseArgument() {
-    // TODO(brianwilkerson) Consider returning a wrapper indicating whether the
-    // expression is a named expression in order to remove the 'is' check in
-    // 'parseArgumentList'.
-    //
-    // Both namedArgument and expression can start with an identifier, but only
-    // namedArgument can have an identifier followed by a colon.
-    //
-    if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
-      return astFactory.namedExpression(parseLabel(), parseExpression2());
-    } else {
-      return parseExpression2();
-    }
+    currentToken = SimpleToken(TokenType.OPEN_PAREN, 0)..setNext(currentToken);
+    appendToken(currentToken, SimpleToken(TokenType.CLOSE_PAREN, 0));
+    currentToken = fastaParser
+        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    var invocation = astBuilder.pop() as MethodInvocation;
+    return invocation.argumentList.arguments[0];
   }
 
-  /// Parse a list of arguments. Return the argument list that was parsed.
-  ///
-  /// This method assumes that the current token matches [TokenType.OPEN_PAREN].
-  ///
-  ///     arguments ::=
-  ///         '(' argumentList? ')'
-  ///
-  ///     argumentList ::=
-  ///         namedArgument (',' namedArgument)*
-  ///       | expressionList (',' namedArgument)*
-  ArgumentList parseArgumentList() {
-    Token leftParenthesis = getAndAdvance();
-    if (_matches(TokenType.CLOSE_PAREN)) {
-      return astFactory.argumentList(leftParenthesis, null, getAndAdvance());
-    }
+  Expression parseAssignableExpression(bool primaryAllowed) =>
+      parseExpression2();
 
-    /// Return `true` if the parser appears to be at the beginning of an
-    /// argument even though there was no comma. This is a special case of the
-    /// more general recovery technique described below.
-    bool isLikelyMissingComma() {
-      if (_matchesIdentifier() &&
-          _tokenMatches(_currentToken.next, TokenType.COLON) &&
-          leftParenthesis is BeginToken &&
-          leftParenthesis.endToken != null) {
-        _reportErrorForToken(
-            ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [',']);
-        return true;
-      }
-      return false;
-    }
+  Expression parseBitwiseAndExpression() => parseExpression2();
 
-    //
-    // Even though unnamed arguments must all appear before any named arguments,
-    // we allow them to appear in any order so that we can recover faster.
-    //
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = false;
-    try {
-      Token previousStartOfArgument = _currentToken;
-      Expression argument = parseArgument();
-      List<Expression> arguments = <Expression>[argument];
-      bool foundNamedArgument = argument is NamedExpression;
-      bool generatedError = false;
-      while (_optional(TokenType.COMMA) ||
-          (isLikelyMissingComma() &&
-              previousStartOfArgument != _currentToken)) {
-        if (_matches(TokenType.CLOSE_PAREN)) {
-          break;
-        }
-        previousStartOfArgument = _currentToken;
-        argument = parseArgument();
-        arguments.add(argument);
-        if (argument is NamedExpression) {
-          foundNamedArgument = true;
-        } else if (foundNamedArgument) {
-          if (!generatedError) {
-            if (!argument.isSynthetic) {
-              // Report the error, once, but allow the arguments to be in any
-              // order in the AST.
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT);
-              generatedError = true;
-            }
-          }
-        }
-      }
-      // Recovery: If the next token is not a right parenthesis, look at the
-      // left parenthesis to see whether there is a matching right parenthesis.
-      // If there is, then we're more likely missing a comma and should go back
-      // to parsing arguments.
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      return astFactory.argumentList(
-          leftParenthesis, arguments, rightParenthesis);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
+  Expression parseBitwiseOrExpression() => parseExpression2();
 
-  /// Parse an assert statement. Return the assert statement.
-  ///
-  /// This method assumes that the current token matches `Keyword.ASSERT`.
-  ///
-  ///     assertStatement ::=
-  ///         'assert' '(' expression [',' expression] ')' ';'
-  AssertStatement parseAssertStatement() {
-    Token keyword = getAndAdvance();
-    Token leftParen = _expect(TokenType.OPEN_PAREN);
-    Expression expression = parseExpression2();
-    Token comma;
-    Expression message;
-    if (_matches(TokenType.COMMA)) {
-      comma = getAndAdvance();
-      if (_matches(TokenType.CLOSE_PAREN)) {
-        comma;
-      } else {
-        message = parseExpression2();
-        if (_matches(TokenType.COMMA)) {
-          getAndAdvance();
-        }
-      }
-    }
-    Token rightParen = _expect(TokenType.CLOSE_PAREN);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    // TODO(brianwilkerson) We should capture the trailing comma in the AST, but
-    // that would be a breaking change, so we drop it for now.
-    return astFactory.assertStatement(
-        keyword, leftParen, expression, comma, message, rightParen, semicolon);
-  }
+  Expression parseBitwiseXorExpression() => parseExpression2();
 
-  /// Parse an assignable expression. The [primaryAllowed] is `true` if the
-  /// expression is allowed to be a primary without any assignable selector.
-  /// Return the assignable expression that was parsed.
-  ///
-  ///     assignableExpression ::=
-  ///         primary (arguments* assignableSelector)+
-  ///       | 'super' unconditionalAssignableSelector
-  ///       | identifier
-  Expression parseAssignableExpression(bool primaryAllowed) {
-    //
-    // A primary expression can start with an identifier. We resolve the
-    // ambiguity by determining whether the primary consists of anything other
-    // than an identifier and/or is followed by an assignableSelector.
-    //
-    Expression expression = parsePrimaryExpression();
-    bool isOptional =
-        primaryAllowed || _isValidAssignableExpression(expression);
-    while (true) {
-      while (_isLikelyArgumentList()) {
-        TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-        ArgumentList argumentList = parseArgumentList();
-        Expression currentExpression = expression;
-        if (currentExpression is SimpleIdentifier) {
-          expression = astFactory.methodInvocation(
-              null, null, currentExpression, typeArguments, argumentList);
-        } else if (currentExpression is PrefixedIdentifier) {
-          expression = astFactory.methodInvocation(
-              currentExpression.prefix,
-              currentExpression.period,
-              currentExpression.identifier,
-              typeArguments,
-              argumentList);
-        } else if (currentExpression is PropertyAccess) {
-          expression = astFactory.methodInvocation(
-              currentExpression.target,
-              currentExpression.operator,
-              currentExpression.propertyName,
-              typeArguments,
-              argumentList);
-        } else {
-          expression = astFactory.functionExpressionInvocation(
-              expression, typeArguments, argumentList);
-        }
-        if (!primaryAllowed) {
-          isOptional = false;
-        }
-      }
-      Expression selectorExpression = parseAssignableSelector(
-          expression, isOptional || (expression is PrefixedIdentifier));
-      if (identical(selectorExpression, expression)) {
-        return expression;
-      }
-      expression = selectorExpression;
-      isOptional = true;
-    }
-  }
-
-  /// Parse an assignable selector. The [prefix] is the expression preceding the
-  /// selector. The [optional] is `true` if the selector is optional. Return the
-  /// assignable selector that was parsed, or the original prefix if there was
-  /// no assignable selector.  If [allowConditional] is false, then the '?.'
-  /// operator will still be parsed, but a parse error will be generated.
-  ///
-  ///     unconditionalAssignableSelector ::=
-  ///         '[' expression ']'
-  ///       | '.' identifier
-  ///
-  ///     assignableSelector ::=
-  ///         unconditionalAssignableSelector
-  ///       | '?.' identifier
-  Expression parseAssignableSelector(Expression prefix, bool optional,
-      {bool allowConditional = true}) {
-    TokenType type = _currentToken.type;
-    if (type == TokenType.OPEN_SQUARE_BRACKET) {
-      Token leftBracket = getAndAdvance();
-      bool wasInInitializer = _inInitializer;
-      _inInitializer = false;
-      try {
-        Expression index = parseExpression2();
-        Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
-        return astFactory.indexExpressionForTarget2(
-            target: prefix,
-            leftBracket: leftBracket,
-            index: index,
-            rightBracket: rightBracket);
-      } finally {
-        _inInitializer = wasInInitializer;
-      }
-    } else {
-      bool isQuestionPeriod = type == TokenType.QUESTION_PERIOD;
-      if (type == TokenType.PERIOD || isQuestionPeriod) {
-        if (isQuestionPeriod && !allowConditional) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
-              [_currentToken.lexeme]);
-        }
-        Token operator = getAndAdvance();
-        return astFactory.propertyAccess(
-            prefix, operator, parseSimpleIdentifier());
-      } else if (type == TokenType.INDEX) {
-        _splitIndex();
-        Token leftBracket = getAndAdvance();
-        Expression index = parseSimpleIdentifier();
-        Token rightBracket = getAndAdvance();
-        return astFactory.indexExpressionForTarget2(
-            target: prefix,
-            leftBracket: leftBracket,
-            index: index,
-            rightBracket: rightBracket);
-      } else {
-        if (!optional) {
-          // Report the missing selector.
-          _reportErrorForCurrentToken(
-              ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR);
-        }
-        return prefix;
-      }
-    }
-  }
-
-  /// Parse a await expression. Return the await expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `_AWAIT`.
-  ///
-  ///     awaitExpression ::=
-  ///         'await' unaryExpression
-  AwaitExpression parseAwaitExpression() {
-    Token awaitToken = getAndAdvance();
-    Expression expression = parseUnaryExpression();
-    return astFactory.awaitExpression(awaitToken, expression);
-  }
-
-  /// Parse a bitwise and expression. Return the bitwise and expression that was
-  /// parsed.
-  ///
-  ///     bitwiseAndExpression ::=
-  ///         shiftExpression ('&' shiftExpression)*
-  ///       | 'super' ('&' shiftExpression)+
-  Expression parseBitwiseAndExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type == TokenType.AMPERSAND) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseShiftExpression();
-    }
-    while (_currentToken.type == TokenType.AMPERSAND) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseShiftExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a bitwise or expression. Return the bitwise or expression that was
-  /// parsed.
-  ///
-  ///     bitwiseOrExpression ::=
-  ///         bitwiseXorExpression ('|' bitwiseXorExpression)*
-  ///       | 'super' ('|' bitwiseXorExpression)+
-  Expression parseBitwiseOrExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type == TokenType.BAR) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseBitwiseXorExpression();
-    }
-    while (_currentToken.type == TokenType.BAR) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseBitwiseXorExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a bitwise exclusive-or expression. Return the bitwise exclusive-or
-  /// expression that was parsed.
-  ///
-  ///     bitwiseXorExpression ::=
-  ///         bitwiseAndExpression ('^' bitwiseAndExpression)*
-  ///       | 'super' ('^' bitwiseAndExpression)+
-  Expression parseBitwiseXorExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type == TokenType.CARET) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseBitwiseAndExpression();
-    }
-    while (_currentToken.type == TokenType.CARET) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseBitwiseAndExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a block. Return the block that was parsed.
-  ///
-  /// This method assumes that the current token matches
-  /// [TokenType.OPEN_CURLY_BRACKET].
-  ///
-  ///     block ::=
-  ///         '{' statements '}'
-  Block parseBlock() {
-    bool isEndOfBlock() {
-      TokenType type = _currentToken.type;
-      return type == TokenType.EOF || type == TokenType.CLOSE_CURLY_BRACKET;
-    }
-
-    Token leftBracket = getAndAdvance();
-    List<Statement> statements = <Statement>[];
-    Token statementStart = _currentToken;
-    while (!isEndOfBlock()) {
-      Statement statement = parseStatement2();
-      if (identical(_currentToken, statementStart)) {
-        // Ensure that we are making progress and report an error if we're not.
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      } else if (statement != null) {
-        statements.add(statement);
-      }
-      statementStart = _currentToken;
-    }
-    // Recovery: If the next token is not a right curly bracket, look at the
-    // left curly bracket to see whether there is a matching right bracket. If
-    // there is, then we're more likely missing a semi-colon and should go back
-    // to parsing statements.
-    Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-    return astFactory.block(leftBracket, statements, rightBracket);
-  }
-
-  /// Parse a break statement. Return the break statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.BREAK`.
-  ///
-  ///     breakStatement ::=
-  ///         'break' identifier? ';'
-  Statement parseBreakStatement() {
-    Token breakKeyword = getAndAdvance();
-    SimpleIdentifier label;
-    if (_matchesIdentifier()) {
-      label = _parseSimpleIdentifierUnchecked();
-    }
-    if (!_inLoop && !_inSwitch && label == null) {
-      _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword);
-    }
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.breakStatement(breakKeyword, label, semicolon);
-  }
-
-  /// Parse a cascade section. Return the expression representing the cascaded
-  /// method invocation.
-  ///
-  /// This method assumes that the current token matches
-  /// `TokenType.PERIOD_PERIOD`.
-  ///
-  ///     cascadeSection ::=
-  ///         '..' (cascadeSelector typeArguments? arguments*)
-  ///         (assignableSelector typeArguments? arguments*)* cascadeAssignment?
-  ///
-  ///     cascadeSelector ::=
-  ///         '[' expression ']'
-  ///       | identifier
-  ///
-  ///     cascadeAssignment ::=
-  ///         assignmentOperator expressionWithoutCascade
-  Expression parseCascadeSection() {
-    Token period = getAndAdvance();
-    Expression expression;
-    SimpleIdentifier functionName;
-    if (_matchesIdentifier()) {
-      functionName = _parseSimpleIdentifierUnchecked();
-    } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) {
-      Token leftBracket = getAndAdvance();
-      bool wasInInitializer = _inInitializer;
-      _inInitializer = false;
-      try {
-        Expression index = parseExpression2();
-        Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
-        expression = astFactory.indexExpressionForCascade2(
-            period: period,
-            leftBracket: leftBracket,
-            index: index,
-            rightBracket: rightBracket);
-        period;
-      } finally {
-        _inInitializer = wasInInitializer;
-      }
-    } else {
-      _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken,
-          [_currentToken.lexeme]);
-      functionName = createSyntheticIdentifier();
-    }
-    assert((expression == null && functionName != null) ||
-        (expression != null && functionName == null));
-    if (_isLikelyArgumentList()) {
-      do {
-        TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-        if (functionName != null) {
-          expression = astFactory.methodInvocation(expression, period,
-              functionName, typeArguments, parseArgumentList());
-          period;
-          functionName;
-        } else if (expression == null) {
-          // It should not be possible to get here.
-          expression = astFactory.methodInvocation(expression, period,
-              createSyntheticIdentifier(), typeArguments, parseArgumentList());
-        } else {
-          expression = astFactory.functionExpressionInvocation(
-              expression, typeArguments, parseArgumentList());
-        }
-      } while (_isLikelyArgumentList());
-    } else if (functionName != null) {
-      expression = astFactory.propertyAccess(expression, period, functionName);
-      period;
-    }
-    assert(expression != null);
-    bool progress = true;
-    while (progress) {
-      progress = false;
-      Expression selector = parseAssignableSelector(expression, true);
-      if (!identical(selector, expression)) {
-        expression = selector;
-        progress = true;
-        while (_isLikelyArgumentList()) {
-          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-          Expression currentExpression = expression;
-          if (currentExpression is PropertyAccess) {
-            expression = astFactory.methodInvocation(
-                currentExpression.target,
-                currentExpression.operator,
-                currentExpression.propertyName,
-                typeArguments,
-                parseArgumentList());
-          } else {
-            expression = astFactory.functionExpressionInvocation(
-                expression, typeArguments, parseArgumentList());
-          }
-        }
-      }
-    }
-    if (_currentToken.type.isAssignmentOperator) {
-      Token operator = getAndAdvance();
-      _ensureAssignable(expression);
-      expression = astFactory.assignmentExpression(
-          expression, operator, parseExpressionWithoutCascade());
-    }
-    return expression;
-  }
-
-  /// Parse a class declaration. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. The [abstractKeyword] is the token for the
-  /// keyword 'abstract', or `null` if the keyword was not given. Return the
-  /// class declaration that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.CLASS`.
-  ///
-  ///     classDeclaration ::=
-  ///         metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' |
-  ///         metadata 'abstract'? 'class' mixinApplicationClass
-  CompilationUnitMember parseClassDeclaration(
-      CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
-    //
-    // Parse the name and type parameters.
-    //
-    Token keyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    String className = name.name;
-    TypeParameterList typeParameters;
-    TokenType type = _currentToken.type;
-    if (type == TokenType.LT) {
-      typeParameters = parseTypeParameterList();
-      type = _currentToken.type;
-    }
-    //
-    // Check to see whether this might be a class type alias rather than a class
-    // declaration.
-    //
-    if (type == TokenType.EQ) {
-      return _parseClassTypeAliasAfterName(
-          commentAndMetadata, abstractKeyword, keyword, name, typeParameters);
-    }
-    //
-    // Parse the clauses. The parser accepts clauses in any order, but will
-    // generate errors if they are not in the order required by the
-    // specification.
-    //
-    ExtendsClause extendsClause;
-    WithClause withClause;
-    ImplementsClause implementsClause;
-    bool foundClause = true;
-    while (foundClause) {
-      Keyword keyword = _currentToken.keyword;
-      if (keyword == Keyword.EXTENDS) {
-        if (extendsClause == null) {
-          extendsClause = parseExtendsClause();
-          if (withClause != null) {
-            _reportErrorForToken(
-                ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKeyword);
-          } else if (implementsClause != null) {
-            _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS,
-                implementsClause.implementsKeyword);
-          }
-        } else {
-          _reportErrorForToken(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES,
-              extendsClause.extendsKeyword);
-          parseExtendsClause();
-        }
-      } else if (keyword == Keyword.WITH) {
-        if (withClause == null) {
-          withClause = parseWithClause();
-          if (implementsClause != null) {
-            _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_WITH,
-                implementsClause.implementsKeyword);
-          }
-        } else {
-          _reportErrorForToken(
-              ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause.withKeyword);
-          parseWithClause();
-          // TODO(brianwilkerson) Should we merge the list of applied mixins
-          // into a single list?
-        }
-      } else if (keyword == Keyword.IMPLEMENTS) {
-        if (implementsClause == null) {
-          implementsClause = parseImplementsClause();
-        } else {
-          _reportErrorForToken(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES,
-              implementsClause.implementsKeyword);
-          parseImplementsClause();
-          // TODO(brianwilkerson) Should we merge the list of implemented
-          // classes into a single list?
-        }
-      } else {
-        foundClause = false;
-      }
-    }
-    //
-    // Look for and skip over the extra-lingual 'native' specification.
-    //
-    NativeClause nativeClause;
-    if (_matchesKeyword(Keyword.NATIVE) &&
-        _tokenMatches(_peek(), TokenType.STRING)) {
-      nativeClause = _parseNativeClause();
-    }
-    //
-    // Parse the body of the class.
-    //
-    Token leftBracket;
-    List<ClassMember> members;
-    Token rightBracket;
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      leftBracket = getAndAdvance();
-      members = _parseClassMembers(className, _getEndToken(leftBracket));
-      rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-    } else {
-      // Recovery: Check for an unmatched closing curly bracket and parse
-      // members until it is reached.
-      leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
-      rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
-      _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_BODY);
-    }
-    ClassDeclaration classDeclaration = astFactory.classDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        abstractKeyword,
-        keyword,
-        name,
-        typeParameters,
-        extendsClause,
-        withClause,
-        implementsClause,
-        leftBracket,
-        members,
-        rightBracket);
-    classDeclaration.nativeClause = nativeClause;
-    return classDeclaration;
-  }
-
-  /// Parse a class member. The [className] is the name of the class containing
-  /// the member being parsed. Return the class member that was parsed, or
-  /// `null` if what was found was not a valid class member.
-  ///
-  ///     classMemberDefinition ::=
-  ///         declaration ';'
-  ///       | methodSignature functionBody
-  ClassMember parseClassMember(String className) {
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    Modifiers modifiers = parseModifiers();
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.VOID ||
-        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      TypeAnnotation returnType;
-      if (keyword == Keyword.VOID) {
-        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
-          returnType = parseTypeAnnotation(false);
-        } else {
-          returnType = astFactory.typeName(
-              astFactory.simpleIdentifier(getAndAdvance()), null);
-        }
-      } else {
-        returnType = parseTypeAnnotation(false);
-      }
-      keyword = _currentToken.keyword;
-      Token next = _peek();
-      bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
-      if (keyword == Keyword.GET && isFollowedByIdentifier) {
-        _validateModifiersForGetterOrSetterOrMethod(modifiers);
-        return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-            modifiers.staticKeyword, returnType);
-      } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
-        _validateModifiersForGetterOrSetterOrMethod(modifiers);
-        return parseSetter(commentAndMetadata, modifiers.externalKeyword,
-            modifiers.staticKeyword, returnType);
-      } else if (keyword == Keyword.OPERATOR &&
-          (_isOperator(next) || next.type == TokenType.EQ_EQ_EQ)) {
-        _validateModifiersForOperator(modifiers);
-        return _parseOperatorAfterKeyword(commentAndMetadata,
-            modifiers.externalKeyword, returnType, getAndAdvance());
-      } else if (_matchesIdentifier() &&
-          _peek().matchesAny(const <TokenType>[
-            TokenType.OPEN_PAREN,
-            TokenType.OPEN_CURLY_BRACKET,
-            TokenType.FUNCTION,
-            TokenType.LT
-          ])) {
-        _validateModifiersForGetterOrSetterOrMethod(modifiers);
-        return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
-            modifiers.externalKeyword, modifiers.staticKeyword, returnType);
-      } else if (_matchesIdentifier() &&
-          _peek().matchesAny(const <TokenType>[
-            TokenType.EQ,
-            TokenType.COMMA,
-            TokenType.SEMICOLON
-          ])) {
-        return parseInitializedIdentifierList(
-            commentAndMetadata,
-            modifiers.staticKeyword,
-            modifiers.covariantKeyword,
-            _validateModifiersForField(modifiers),
-            returnType);
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        if (_isOperator(_currentToken)) {
-          //
-          // We appear to have found an operator declaration without the
-          // 'operator' keyword.
-          //
-          _validateModifiersForOperator(modifiers);
-          return parseOperator(
-              commentAndMetadata, modifiers.externalKeyword, returnType);
-        }
-        _reportErrorForToken(
-            ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-        return null;
-      }
-    }
-    Token next = _peek();
-    bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
-    if (keyword == Keyword.GET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, null);
-    } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseSetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, null);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _validateModifiersForOperator(modifiers);
-      return _parseOperatorAfterKeyword(
-          commentAndMetadata, modifiers.externalKeyword, null, getAndAdvance());
-    } else if (!_matchesIdentifier()) {
-      //
-      // Recover from an error.
-      //
-      if (_matchesKeyword(Keyword.CLASS)) {
-        _reportErrorForCurrentToken(ParserErrorCode.CLASS_IN_CLASS);
-        // TODO(brianwilkerson) We don't currently have any way to capture the
-        // class that was parsed.
-        parseClassDeclaration(commentAndMetadata, null);
-        return null;
-      } else if (_matchesKeyword(Keyword.ABSTRACT) &&
-          _tokenMatchesKeyword(_peek(), Keyword.CLASS)) {
-        _reportErrorForToken(ParserErrorCode.CLASS_IN_CLASS, _peek());
-        // TODO(brianwilkerson) We don't currently have any way to capture the
-        // class that was parsed.
-        parseClassDeclaration(commentAndMetadata, getAndAdvance());
-        return null;
-      } else if (_matchesKeyword(Keyword.ENUM)) {
-        _reportErrorForToken(ParserErrorCode.ENUM_IN_CLASS, _peek());
-        // TODO(brianwilkerson) We don't currently have any way to capture the
-        // enum that was parsed.
-        parseEnumDeclaration(commentAndMetadata);
-        return null;
-      } else if (_isOperator(_currentToken)) {
-        //
-        // We appear to have found an operator declaration without the
-        // 'operator' keyword.
-        //
-        _validateModifiersForOperator(modifiers);
-        return parseOperator(
-            commentAndMetadata, modifiers.externalKeyword, null);
-      }
-      Token keyword = modifiers.varKeyword ??
-          modifiers.finalKeyword ??
-          modifiers.constKeyword;
-      if (keyword != null) {
-        //
-        // We appear to have found an incomplete field declaration.
-        //
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-        VariableDeclaration variable = astFactory.variableDeclaration(
-            createSyntheticIdentifier(), null, null);
-        List<VariableDeclaration> variables = <VariableDeclaration>[variable];
-        return astFactory.fieldDeclaration2(
-            comment: commentAndMetadata.comment,
-            metadata: commentAndMetadata.metadata,
-            covariantKeyword: modifiers.covariantKeyword,
-            fieldList: astFactory.variableDeclarationList(
-                null, null, keyword, null, variables),
-            semicolon: _expect(TokenType.SEMICOLON));
-      }
-      _reportErrorForToken(
-          ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
-      if (commentAndMetadata.comment != null ||
-          commentAndMetadata.hasMetadata) {
-        //
-        // We appear to have found an incomplete declaration at the end of the
-        // class. At this point it consists of a metadata, which we don't want
-        // to loose, so we'll treat it as a method declaration with a missing
-        // name, parameters and empty body.
-        //
-        return astFactory.methodDeclaration(
-            commentAndMetadata.comment,
-            commentAndMetadata.metadata,
-            null,
-            null,
-            null,
-            null,
-            null,
-            createSyntheticIdentifier(isDeclaration: true),
-            null,
-            astFactory.formalParameterList(
-                _createSyntheticToken(TokenType.OPEN_PAREN),
-                <FormalParameter>[],
-                null,
-                null,
-                _createSyntheticToken(TokenType.CLOSE_PAREN)),
-            astFactory
-                .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON)));
-      }
-      return null;
-    } else if (_tokenMatches(next, TokenType.PERIOD) &&
-        _tokenMatchesIdentifierOrKeyword(_peekAt(2)) &&
-        _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
-      if (!_tokenMatchesIdentifier(_peekAt(2))) {
-        _reportErrorForToken(ParserErrorCode.INVALID_CONSTRUCTOR_NAME,
-            _peekAt(2), [_peekAt(2).lexeme]);
-      }
-      return _parseConstructor(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          _validateModifiersForConstructor(modifiers),
-          modifiers.factoryKeyword,
-          parseSimpleIdentifier(),
-          getAndAdvance(),
-          parseSimpleIdentifier(allowKeyword: true, isDeclaration: true),
-          parseFormalParameterList());
-    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
-      TypeName returnType;
-      SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
-      TypeParameterList typeParameters;
-      FormalParameterList parameters = parseFormalParameterList();
-      if (_matches(TokenType.COLON) ||
-          modifiers.factoryKeyword != null ||
-          methodName.name == className) {
-        return _parseConstructor(
-            commentAndMetadata,
-            modifiers.externalKeyword,
-            _validateModifiersForConstructor(modifiers),
-            modifiers.factoryKeyword,
-            astFactory.simpleIdentifier(methodName.token, isDeclaration: false),
-            null,
-            null,
-            parameters);
-      }
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      _validateFormalParameterList(parameters);
-      return _parseMethodDeclarationAfterParameters(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          modifiers.staticKeyword,
-          returnType,
-          methodName,
-          typeParameters,
-          parameters);
-    } else if (next.matchesAny(const <TokenType>[
-      TokenType.EQ,
-      TokenType.COMMA,
-      TokenType.SEMICOLON
-    ])) {
-      if (modifiers.constKeyword == null &&
-          modifiers.finalKeyword == null &&
-          modifiers.varKeyword == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
-      }
-      return parseInitializedIdentifierList(
-          commentAndMetadata,
-          modifiers.staticKeyword,
-          modifiers.covariantKeyword,
-          _validateModifiersForField(modifiers),
-          null);
-    } else if (keyword == Keyword.TYPEDEF) {
-      _reportErrorForCurrentToken(ParserErrorCode.TYPEDEF_IN_CLASS);
-      // TODO(brianwilkerson) We don't currently have any way to capture the
-      // function type alias that was parsed.
-      _parseFunctionTypeAlias(commentAndMetadata, getAndAdvance());
-      return null;
-    } else {
-      Token token = _skipTypeParameterList(_peek());
-      if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
-        return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
-            modifiers.externalKeyword, modifiers.staticKeyword, null);
-      }
-    }
-    TypeAnnotation type = _parseTypeAnnotationAfterIdentifier();
-    keyword = _currentToken.keyword;
-    next = _peek();
-    isFollowedByIdentifier = _tokenMatchesIdentifier(next);
-    if (keyword == Keyword.GET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, type);
-    } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseSetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, type);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _validateModifiersForOperator(modifiers);
-      return _parseOperatorAfterKeyword(
-          commentAndMetadata, modifiers.externalKeyword, type, getAndAdvance());
-    } else if (!_matchesIdentifier()) {
-      if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-        //
-        // We appear to have found an incomplete declaration at the end of the
-        // class. At this point it consists of a type name, so we'll treat it as
-        // a field declaration with a missing field name and semicolon.
-        //
-        return parseInitializedIdentifierList(
-            commentAndMetadata,
-            modifiers.staticKeyword,
-            modifiers.covariantKeyword,
-            _validateModifiersForField(modifiers),
-            type);
-      }
-      if (_isOperator(_currentToken)) {
-        //
-        // We appear to have found an operator declaration without the
-        // 'operator' keyword.
-        //
-        _validateModifiersForOperator(modifiers);
-        return parseOperator(
-            commentAndMetadata, modifiers.externalKeyword, type);
-      }
-      //
-      // We appear to have found an incomplete declaration before another
-      // declaration. At this point it consists of a type name, so we'll treat
-      // it as a field declaration with a missing field name and semicolon.
-      //
-      _reportErrorForToken(
-          ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
-      try {
-        _lockErrorListener();
-        return parseInitializedIdentifierList(
-            commentAndMetadata,
-            modifiers.staticKeyword,
-            modifiers.covariantKeyword,
-            _validateModifiersForField(modifiers),
-            type);
-      } finally {
-        _unlockErrorListener();
-      }
-    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
-      SimpleIdentifier methodName =
-          _parseSimpleIdentifierUnchecked(isDeclaration: true);
-      TypeParameterList typeParameters;
-      FormalParameterList parameters = parseFormalParameterList();
-      if (methodName.name == className) {
-        _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type);
-        return _parseConstructor(
-            commentAndMetadata,
-            modifiers.externalKeyword,
-            _validateModifiersForConstructor(modifiers),
-            modifiers.factoryKeyword,
-            astFactory.simpleIdentifier(methodName.token, isDeclaration: true),
-            null,
-            null,
-            parameters);
-      }
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      _validateFormalParameterList(parameters);
-      return _parseMethodDeclarationAfterParameters(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          modifiers.staticKeyword,
-          type,
-          methodName,
-          typeParameters,
-          parameters);
-    } else if (_tokenMatches(next, TokenType.LT)) {
-      return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
-          modifiers.externalKeyword, modifiers.staticKeyword, type);
-    } else if (_tokenMatches(next, TokenType.OPEN_CURLY_BRACKET)) {
-      // We have found "TypeName identifier {", and are guessing that this is a
-      // getter without the keyword 'get'.
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET);
-      _currentToken = _injectToken(
-          SyntheticKeywordToken(Keyword.GET, _currentToken.offset));
-      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, type);
-    }
-    return parseInitializedIdentifierList(
-        commentAndMetadata,
-        modifiers.staticKeyword,
-        modifiers.covariantKeyword,
-        _validateModifiersForField(modifiers),
-        type);
-  }
-
-  /// Parse a single combinator. Return the combinator that was parsed, or
-  /// `null` if no combinator is found.
-  ///
-  ///     combinator ::=
-  ///         'show' identifier (',' identifier)*
-  ///       | 'hide' identifier (',' identifier)*
-  Combinator parseCombinator() {
-    if (_matchesKeyword(Keyword.SHOW)) {
-      return astFactory.showCombinator(getAndAdvance(), parseIdentifierList());
-    } else if (_matchesKeyword(Keyword.HIDE)) {
-      return astFactory.hideCombinator(getAndAdvance(), parseIdentifierList());
-    }
-    return null;
-  }
-
-  /// Parse a list of combinators in a directive. Return the combinators that
-  /// were parsed, or `null` if there are no combinators.
-  ///
-  ///     combinator ::=
-  ///         'show' identifier (',' identifier)*
-  ///       | 'hide' identifier (',' identifier)*
-  List<Combinator> parseCombinators() {
-    List<Combinator> combinators;
-    while (true) {
-      Combinator combinator = parseCombinator();
-      if (combinator == null) {
-        break;
-      }
-      combinators ??= <Combinator>[];
-      combinators.add(combinator);
-    }
-    return combinators;
-  }
-
-  /// Parse the documentation comment and metadata preceding a declaration. This
-  /// method allows any number of documentation comments to occur before, after
-  /// or between the metadata, but only returns the last (right-most)
-  /// documentation comment that is found. Return the documentation comment and
-  /// metadata that were parsed.
-  ///
-  ///     metadata ::=
-  ///         annotation*
-  CommentAndMetadata parseCommentAndMetadata() {
-    // TODO(brianwilkerson) Consider making the creation of documentation
-    // comments be lazy.
-    List<DocumentationCommentToken> tokens = parseDocumentationCommentTokens();
-    List<Annotation> metadata;
-    while (_matches(TokenType.AT)) {
-      metadata ??= <Annotation>[];
-      metadata.add(parseAnnotation());
-      List<DocumentationCommentToken> optionalTokens =
-          parseDocumentationCommentTokens();
-      if (optionalTokens != null) {
-        tokens = optionalTokens;
-      }
-    }
-    return CommentAndMetadata(parseDocumentationComment(tokens), metadata);
-  }
-
-  /// Parse a comment reference from the source between square brackets. The
-  /// [referenceSource] is the source occurring between the square brackets
-  /// within a documentation comment. The [sourceOffset] is the offset of the
-  /// first character of the reference source. Return the comment reference that
-  /// was parsed, or `null` if no reference could be found.
-  ///
-  ///     commentReference ::=
-  ///         'new'? prefixedIdentifier
-  CommentReference parseCommentReference(
-      String referenceSource, int sourceOffset) {
-    // TODO(brianwilkerson) The errors are not getting the right offset/length
-    // and are being duplicated.
-    try {
-      BooleanErrorListener listener = BooleanErrorListener();
-      Scanner scanner = Scanner(
-          null, SubSequenceReader(referenceSource, sourceOffset), listener)
-        ..configureFeatures(
-          featureSetForOverriding: _featureSet,
-          featureSet: _featureSet,
-        );
-      scanner.setSourceStart(1, 1);
-      Token firstToken = scanner.tokenize();
-      if (listener.errorReported) {
-        return null;
-      }
-      if (firstToken.type == TokenType.EOF) {
-        Token syntheticToken =
-            SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset);
-        syntheticToken.setNext(firstToken);
-        return astFactory.commentReference(
-            null, astFactory.simpleIdentifier(syntheticToken));
-      }
-      Token newKeyword;
-      if (_tokenMatchesKeyword(firstToken, Keyword.NEW)) {
-        newKeyword = firstToken;
-        firstToken = firstToken.next;
-      }
-      if (firstToken.isUserDefinableOperator) {
-        if (firstToken.next.type != TokenType.EOF) {
-          return null;
-        }
-        Identifier identifier = astFactory.simpleIdentifier(firstToken);
-        return astFactory.commentReference(null, identifier);
-      } else if (_tokenMatchesKeyword(firstToken, Keyword.OPERATOR)) {
-        Token secondToken = firstToken.next;
-        if (secondToken.isUserDefinableOperator) {
-          if (secondToken.next.type != TokenType.EOF) {
-            return null;
-          }
-          Identifier identifier = astFactory.simpleIdentifier(secondToken);
-          return astFactory.commentReference(null, identifier);
-        }
-        return null;
-      } else if (_tokenMatchesIdentifier(firstToken)) {
-        Token secondToken = firstToken.next;
-        Token thirdToken = secondToken.next;
-        Token nextToken;
-        Identifier identifier;
-        if (_tokenMatches(secondToken, TokenType.PERIOD)) {
-          if (thirdToken.isUserDefinableOperator) {
-            identifier = astFactory.prefixedIdentifier(
-                astFactory.simpleIdentifier(firstToken),
-                secondToken,
-                astFactory.simpleIdentifier(thirdToken));
-            nextToken = thirdToken.next;
-          } else if (_tokenMatchesKeyword(thirdToken, Keyword.OPERATOR)) {
-            Token fourthToken = thirdToken.next;
-            if (fourthToken.isUserDefinableOperator) {
-              identifier = astFactory.prefixedIdentifier(
-                  astFactory.simpleIdentifier(firstToken),
-                  secondToken,
-                  astFactory.simpleIdentifier(fourthToken));
-              nextToken = fourthToken.next;
-            } else {
-              return null;
-            }
-          } else if (_tokenMatchesIdentifier(thirdToken)) {
-            identifier = astFactory.prefixedIdentifier(
-                astFactory.simpleIdentifier(firstToken),
-                secondToken,
-                astFactory.simpleIdentifier(thirdToken));
-            nextToken = thirdToken.next;
-          }
-        } else {
-          identifier = astFactory.simpleIdentifier(firstToken);
-          nextToken = firstToken.next;
-        }
-        if (nextToken.type != TokenType.EOF) {
-          return null;
-        }
-        return astFactory.commentReference(newKeyword, identifier);
-      } else {
-        Keyword keyword = firstToken.keyword;
-        if (keyword == Keyword.THIS ||
-            keyword == Keyword.NULL ||
-            keyword == Keyword.TRUE ||
-            keyword == Keyword.FALSE) {
-          // TODO(brianwilkerson) If we want to support this we will need to
-          // extend the definition of CommentReference to take an expression
-          // rather than an identifier. For now we just ignore it to reduce the
-          // number of errors produced, but that's probably not a valid long term
-          // approach.
-          return null;
-        }
-      }
-    } catch (exception) {
-      // Ignored because we assume that it wasn't a real comment reference.
-    }
-    return null;
-  }
-
-  /// Parse all of the comment references occurring in the given array of
-  /// documentation comments. The [tokens] are the comment tokens representing
-  /// the documentation comments to be parsed. Return the comment references
-  /// that were parsed.
-  ///
-  ///     commentReference ::=
-  ///         '[' 'new'? qualified ']' libraryReference?
-  ///
-  ///     libraryReference ::=
-  ///          '(' stringLiteral ')'
-  List<CommentReference> parseCommentReferences(
-      List<DocumentationCommentToken> tokens) {
-    List<CommentReference> references = <CommentReference>[];
-    bool isInGitHubCodeBlock = false;
-    for (DocumentationCommentToken token in tokens) {
-      String comment = token.lexeme;
-      // Skip GitHub code blocks.
-      // https://help.github.com/articles/creating-and-highlighting-code-blocks/
-      if (tokens.length != 1) {
-        if (comment.contains('```')) {
-          isInGitHubCodeBlock = !isInGitHubCodeBlock;
-        }
-        if (isInGitHubCodeBlock) {
-          continue;
-        }
-      }
-      // Remove GitHub include code.
-      comment = _removeGitHubInlineCode(comment);
-      // Find references.
-      int length = comment.length;
-      List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment);
-      int leftIndex = comment.indexOf('[');
-      while (leftIndex >= 0 && leftIndex + 1 < length) {
-        List<int> range = _findRange(codeBlockRanges, leftIndex);
-        if (range == null) {
-          int nameOffset = token.offset + leftIndex + 1;
-          int rightIndex = comment.indexOf(']', leftIndex);
-          if (rightIndex >= 0) {
-            int firstChar = comment.codeUnitAt(leftIndex + 1);
-            if (firstChar != 0x27 && firstChar != 0x22) {
-              if (_isLinkText(comment, rightIndex)) {
-                // TODO(brianwilkerson) Handle the case where there's a library
-                // URI in the link text.
-              } else {
-                CommentReference reference = parseCommentReference(
-                    comment.substring(leftIndex + 1, rightIndex), nameOffset);
-                if (reference != null) {
-                  references.add(reference);
-                }
-              }
-            }
-          } else {
-            // terminating ']' is not typed yet
-            int charAfterLeft = comment.codeUnitAt(leftIndex + 1);
-            Token nameToken;
-            if (Character.isLetterOrDigit(charAfterLeft)) {
-              int nameEnd = StringUtilities.indexOfFirstNotLetterDigit(
-                  comment, leftIndex + 1);
-              String name = comment.substring(leftIndex + 1, nameEnd);
-              nameToken = StringToken(TokenType.IDENTIFIER, name, nameOffset);
-            } else {
-              nameToken =
-                  SyntheticStringToken(TokenType.IDENTIFIER, '', nameOffset);
-            }
-            nameToken.setNext(Token.eof(nameToken.end));
-            references.add(astFactory.commentReference(
-                null, astFactory.simpleIdentifier(nameToken)));
-            // next character
-            rightIndex = leftIndex + 1;
-          }
-          leftIndex = comment.indexOf('[', rightIndex);
-        } else {
-          leftIndex = comment.indexOf('[', range[1]);
-        }
-      }
-    }
-    return references;
-  }
-
-  /// Parse a compilation unit, starting with the given [token]. Return the
-  /// compilation unit that was parsed.
   CompilationUnit parseCompilationUnit(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseCompilationUnit2();
   }
 
-  /// Parse a compilation unit. Return the compilation unit that was parsed.
-  ///
-  /// Specified:
-  ///
-  ///     compilationUnit ::=
-  ///         scriptTag? directive* topLevelDeclaration*
-  ///
-  /// Actual:
-  ///
-  ///     compilationUnit ::=
-  ///         scriptTag? topLevelElement*
-  ///
-  ///     topLevelElement ::=
-  ///         directive
-  ///       | topLevelDeclaration
   CompilationUnit parseCompilationUnit2() {
-    Token firstToken = _currentToken;
-    ScriptTag scriptTag;
-    if (_matches(TokenType.SCRIPT_TAG)) {
-      scriptTag = astFactory.scriptTag(getAndAdvance());
-    }
-    //
-    // Even though all directives must appear before declarations and must occur
-    // in a given order, we allow directives and declarations to occur in any
-    // order so that we can recover better.
-    //
-    bool libraryDirectiveFound = false;
-    bool partOfDirectiveFound = false;
-    bool partDirectiveFound = false;
-    bool directiveFoundAfterDeclaration = false;
-    List<Directive> directives = <Directive>[];
-    List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
-    Token memberStart = _currentToken;
-    TokenType type = _currentToken.type;
-    while (type != TokenType.EOF) {
-      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-      Keyword keyword = _currentToken.keyword;
-      TokenType nextType = _currentToken.next.type;
-      if ((keyword == Keyword.IMPORT ||
-              keyword == Keyword.EXPORT ||
-              keyword == Keyword.LIBRARY ||
-              keyword == Keyword.PART) &&
-          nextType != TokenType.PERIOD &&
-          nextType != TokenType.LT &&
-          nextType != TokenType.OPEN_PAREN) {
-        Directive parseDirective() {
-          if (keyword == Keyword.IMPORT) {
-            if (partDirectiveFound) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
-            }
-            return parseImportDirective(commentAndMetadata);
-          } else if (keyword == Keyword.EXPORT) {
-            if (partDirectiveFound) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
-            }
-            return parseExportDirective(commentAndMetadata);
-          } else if (keyword == Keyword.LIBRARY) {
-            if (libraryDirectiveFound) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES);
-            } else {
-              if (directives.isNotEmpty) {
-                _reportErrorForCurrentToken(
-                    ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST);
-              }
-              libraryDirectiveFound = true;
-            }
-            return parseLibraryDirective(commentAndMetadata);
-          } else if (keyword == Keyword.PART) {
-            if (_tokenMatchesKeyword(_peek(), Keyword.OF)) {
-              partOfDirectiveFound = true;
-              return _parsePartOfDirective(commentAndMetadata);
-            } else {
-              partDirectiveFound = true;
-              return _parsePartDirective(commentAndMetadata);
-            }
-          } else {
-            // Internal error: this method should not have been invoked if the
-            // current token was something other than one of the above.
-            throw StateError(
-                "parseDirective invoked in an invalid state (currentToken = $_currentToken)");
-          }
-        }
-
-        Directive directive = parseDirective();
-        if (declarations.isNotEmpty && !directiveFoundAfterDeclaration) {
-          _reportErrorForToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION,
-              directive.beginToken);
-          directiveFoundAfterDeclaration = true;
-        }
-        directives.add(directive);
-      } else if (type == TokenType.SEMICOLON) {
-        // TODO(brianwilkerson) Consider moving this error detection into
-        // _parseCompilationUnitMember (in the places where EXPECTED_EXECUTABLE
-        // is being generated).
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      } else {
-        CompilationUnitMember member;
-        try {
-          member = parseCompilationUnitMember(commentAndMetadata);
-        } on _TooDeepTreeError {
-          _reportErrorForToken(ParserErrorCode.STACK_OVERFLOW, _currentToken);
-          Token eof = Token.eof(0);
-          return astFactory.compilationUnit(
-            beginToken: eof,
-            endToken: eof,
-            featureSet: _featureSet,
-          );
-        }
-        if (member != null) {
-          declarations.add(member);
-        }
-      }
-      if (identical(_currentToken, memberStart)) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-        while (!_matches(TokenType.EOF) &&
-            !_couldBeStartOfCompilationUnitMember()) {
-          _advance();
-        }
-      }
-      memberStart = _currentToken;
-      type = _currentToken.type;
-    }
-    if (partOfDirectiveFound && directives.length > 1) {
-      // TODO(brianwilkerson) Improve error reporting when both a library and
-      // part-of directive are found.
-//      if (libraryDirectiveFound) {
-//        int directiveCount = directives.length;
-//        for (int i = 0; i < directiveCount; i++) {
-//          Directive directive = directives[i];
-//          if (directive is PartOfDirective) {
-//            _reportErrorForToken(
-//                ParserErrorCode.PART_OF_IN_LIBRARY, directive.partKeyword);
-//          }
-//        }
-//      } else {
-      bool firstPartOf = true;
-      int directiveCount = directives.length;
-      for (int i = 0; i < directiveCount; i++) {
-        Directive directive = directives[i];
-        if (directive is PartOfDirective) {
-          if (firstPartOf) {
-            firstPartOf = false;
-          } else {
-            _reportErrorForToken(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES,
-                directive.partKeyword);
-          }
-        } else {
-          _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART,
-              directives[i].keyword);
-        }
-//        }
-      }
-    }
-    return astFactory.compilationUnit(
-      beginToken: firstToken,
-      scriptTag: scriptTag,
-      directives: directives,
-      declarations: declarations,
-      endToken: _currentToken,
-      featureSet: _featureSet,
-    );
+    currentToken = fastaParser.parseUnit(currentToken);
+    return astBuilder.pop() as CompilationUnit;
   }
 
-  /// Parse a compilation unit member. The [commentAndMetadata] is the metadata
-  /// to be associated with the member. Return the compilation unit member that
-  /// was parsed, or `null` if what was parsed could not be represented as a
-  /// compilation unit member.
-  ///
-  ///     compilationUnitMember ::=
-  ///         classDefinition
-  ///       | functionTypeAlias
-  ///       | external functionSignature
-  ///       | external getterSignature
-  ///       | external setterSignature
-  ///       | functionSignature functionBody
-  ///       | returnType? getOrSet identifier formalParameterList functionBody
-  ///       | (final | const) type? staticFinalDeclarationList ';'
-  ///       | variableDeclaration ';'
-  CompilationUnitMember parseCompilationUnitMember(
-      CommentAndMetadata commentAndMetadata) {
-    Modifiers modifiers = parseModifiers();
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.CLASS) {
-      return parseClassDeclaration(
-          commentAndMetadata, _validateModifiersForClass(modifiers));
-    }
-    Token next = _peek();
-    TokenType nextType = next.type;
-    if (keyword == Keyword.TYPEDEF &&
-        nextType != TokenType.PERIOD &&
-        nextType != TokenType.LT &&
-        nextType != TokenType.OPEN_PAREN) {
-      _validateModifiersForTypedef(modifiers);
-      return parseTypeAlias(commentAndMetadata);
-    } else if (keyword == Keyword.ENUM) {
-      _validateModifiersForEnum(modifiers);
-      return parseEnumDeclaration(commentAndMetadata);
-    } else if (keyword == Keyword.VOID ||
-        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      TypeAnnotation returnType;
-      if (keyword == Keyword.VOID) {
-        if (_atGenericFunctionTypeAfterReturnType(next)) {
-          returnType = parseTypeAnnotation(false);
-        } else {
-          returnType = astFactory.typeName(
-              astFactory.simpleIdentifier(getAndAdvance()), null);
-        }
-      } else {
-        returnType = parseTypeAnnotation(false);
-      }
-      keyword = _currentToken.keyword;
-      next = _peek();
-      if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-          _tokenMatchesIdentifier(next)) {
-        _validateModifiersForTopLevelFunction(modifiers);
-        return parseFunctionDeclaration(
-            commentAndMetadata, modifiers.externalKeyword, returnType);
-      } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-        _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
-        return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
-            commentAndMetadata,
-            modifiers.externalKeyword,
-            returnType,
-            getAndAdvance()));
-      } else if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.OPEN_PAREN,
-            TokenType.OPEN_CURLY_BRACKET,
-            TokenType.FUNCTION,
-            TokenType.LT
-          ])) {
-        _validateModifiersForTopLevelFunction(modifiers);
-        return parseFunctionDeclaration(
-            commentAndMetadata, modifiers.externalKeyword, returnType);
-      } else if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.EQ,
-            TokenType.COMMA,
-            TokenType.SEMICOLON
-          ])) {
-        return astFactory.topLevelVariableDeclaration(
-            commentAndMetadata.comment,
-            commentAndMetadata.metadata,
-            parseVariableDeclarationListAfterType(null,
-                _validateModifiersForTopLevelVariable(modifiers), returnType),
-            _expect(TokenType.SEMICOLON));
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        _reportErrorForToken(
-            ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-        return null;
-      }
-    } else if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-        _tokenMatchesIdentifier(next)) {
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, null);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
-      return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          null,
-          getAndAdvance()));
-    } else if (!_matchesIdentifier()) {
-      Token keyword = modifiers.varKeyword;
-      keyword ??= modifiers.finalKeyword;
-      keyword ??= modifiers.constKeyword;
-      if (keyword != null) {
-        //
-        // We appear to have found an incomplete top-level variable declaration.
-        //
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-        VariableDeclaration variable = astFactory.variableDeclaration(
-            createSyntheticIdentifier(), null, null);
-        List<VariableDeclaration> variables = <VariableDeclaration>[variable];
-        return astFactory.topLevelVariableDeclaration(
-            commentAndMetadata.comment,
-            commentAndMetadata.metadata,
-            astFactory.variableDeclarationList(
-                null, null, keyword, null, variables),
-            _expect(TokenType.SEMICOLON));
-      }
-      _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-      return null;
-    } else if (_isPeekGenericTypeParametersAndOpenParen()) {
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, null);
-    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
-      TypeName returnType;
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, returnType);
-    } else if (next.matchesAny(const <TokenType>[
-      TokenType.EQ,
-      TokenType.COMMA,
-      TokenType.SEMICOLON
-    ])) {
-      if (modifiers.constKeyword == null &&
-          modifiers.finalKeyword == null &&
-          modifiers.varKeyword == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
-      }
-      return astFactory.topLevelVariableDeclaration(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          parseVariableDeclarationListAfterType(
-              null, _validateModifiersForTopLevelVariable(modifiers), null),
-          _expect(TokenType.SEMICOLON));
-    }
-    TypeAnnotation returnType = parseTypeAnnotation(false);
-    keyword = _currentToken.keyword;
-    next = _peek();
-    if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-        _tokenMatchesIdentifier(next)) {
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, returnType);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
-      return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          returnType,
-          getAndAdvance()));
-    } else if (_matches(TokenType.AT)) {
-      return astFactory.topLevelVariableDeclaration(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          parseVariableDeclarationListAfterType(null,
-              _validateModifiersForTopLevelVariable(modifiers), returnType),
-          _expect(TokenType.SEMICOLON));
-    } else if (!_matchesIdentifier()) {
-      // TODO(brianwilkerson) Generalize this error. We could also be parsing a
-      // top-level variable at this point.
-      _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-      Token semicolon;
-      if (_matches(TokenType.SEMICOLON)) {
-        semicolon = getAndAdvance();
-      } else {
-        semicolon = _createSyntheticToken(TokenType.SEMICOLON);
-      }
-      VariableDeclaration variable = astFactory.variableDeclaration(
-          createSyntheticIdentifier(), null, null);
-      List<VariableDeclaration> variables = <VariableDeclaration>[variable];
-      return astFactory.topLevelVariableDeclaration(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          astFactory.variableDeclarationList(
-              null, null, null, returnType, variables),
-          semicolon);
-    } else if (next.matchesAny(const <TokenType>[
-      TokenType.OPEN_PAREN,
-      TokenType.FUNCTION,
-      TokenType.OPEN_CURLY_BRACKET,
-      TokenType.LT
-    ])) {
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, returnType);
-    }
-    return astFactory.topLevelVariableDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        parseVariableDeclarationListAfterType(
-            null, _validateModifiersForTopLevelVariable(modifiers), returnType),
-        _expect(TokenType.SEMICOLON));
-  }
+  Expression parseConditionalExpression() => parseExpression2();
 
-  /// Parse a conditional expression. Return the conditional expression that was
-  /// parsed.
-  ///
-  ///     conditionalExpression ::=
-  ///         ifNullExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)?
-  Expression parseConditionalExpression() {
-    Expression condition = parseIfNullExpression();
-    if (_currentToken.type != TokenType.QUESTION) {
-      return condition;
-    }
-    Token question = getAndAdvance();
-    Expression thenExpression = parseExpressionWithoutCascade();
-    Token colon = _expect(TokenType.COLON);
-    Expression elseExpression = parseExpressionWithoutCascade();
-    return astFactory.conditionalExpression(
-        condition, question, thenExpression, colon, elseExpression);
-  }
-
-  /// Parse a configuration in either an import or export directive.
-  ///
-  /// This method assumes that the current token matches `Keyword.IF`.
-  ///
-  ///     configuration ::=
-  ///         'if' '(' test ')' uri
-  ///
-  ///     test ::=
-  ///         dottedName ('==' stringLiteral)?
-  ///
-  ///     dottedName ::=
-  ///         identifier ('.' identifier)*
   Configuration parseConfiguration() {
-    Token ifKeyword = getAndAdvance();
-    Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-    DottedName name = parseDottedName();
-    Token equalToken;
-    StringLiteral value;
-    if (_matches(TokenType.EQ_EQ)) {
-      equalToken = getAndAdvance();
-      value = parseStringLiteral();
-      if (value is StringInterpolation) {
-        _reportErrorForNode(
-            ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, value);
-      }
-    }
-    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-    StringLiteral libraryUri = _parseUri();
-    return astFactory.configuration(ifKeyword, leftParenthesis, name,
-        equalToken, value, rightParenthesis, libraryUri);
+    currentToken = fastaParser
+        .parseConditionalUri(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as Configuration;
   }
 
-  /// Parse a const expression. Return the const expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.CONST`.
-  ///
-  ///     constExpression ::=
-  ///         instanceCreationExpression
-  ///       | listLiteral
-  ///       | mapLiteral
-  Expression parseConstExpression() {
-    Token keyword = getAndAdvance();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.LT) {
-      return parseListOrMapLiteral(keyword);
-    } else if (type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.INDEX) {
-      return parseListLiteral(keyword, null);
-    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-      return parseMapLiteral(keyword, null);
-    }
-    return parseInstanceCreationExpression(keyword);
-  }
+  Expression parseConstExpression() => parseExpression2();
 
-  /// Parse a field initializer within a constructor. The flag [hasThis] should
-  /// be true if the current token is `this`. Return the field initializer that
-  /// was parsed.
-  ///
-  ///     fieldInitializer:
-  ///         ('this' '.')? identifier '=' conditionalExpression cascadeSection*
-  ConstructorFieldInitializer parseConstructorFieldInitializer(bool hasThis) {
-    Token keywordToken;
-    Token period;
-    if (hasThis) {
-      keywordToken = getAndAdvance();
-      period = _expect(TokenType.PERIOD);
-    }
-    SimpleIdentifier fieldName = parseSimpleIdentifier();
-    Token equals;
-    TokenType type = _currentToken.type;
-    if (type == TokenType.EQ) {
-      equals = getAndAdvance();
-    } else {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER);
-      Keyword keyword = _currentToken.keyword;
-      if (keyword != Keyword.THIS &&
-          keyword != Keyword.SUPER &&
-          type != TokenType.OPEN_CURLY_BRACKET &&
-          type != TokenType.FUNCTION) {
-        equals = _createSyntheticToken(TokenType.EQ);
-      } else {
-        return astFactory.constructorFieldInitializer(
-            keywordToken,
-            period,
-            fieldName,
-            _createSyntheticToken(TokenType.EQ),
-            createSyntheticIdentifier());
-      }
-    }
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = true;
-    try {
-      Expression expression = parseConditionalExpression();
-      if (_matches(TokenType.PERIOD_PERIOD)) {
-        List<Expression> cascadeSections = <Expression>[];
-        do {
-          Expression section = parseCascadeSection();
-          if (section != null) {
-            cascadeSections.add(section);
-          }
-        } while (_matches(TokenType.PERIOD_PERIOD));
-        expression = astFactory.cascadeExpression(expression, cascadeSections);
-      }
-      return astFactory.constructorFieldInitializer(
-          keywordToken, period, fieldName, equals, expression);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
-
-  /// Parse the name of a constructor. Return the constructor name that was
-  /// parsed.
-  ///
-  ///     constructorName:
-  ///         type ('.' identifier)?
-  ConstructorName parseConstructorName() {
-    TypeName type = parseTypeName(false);
-    Token period;
-    SimpleIdentifier name;
-    if (_matches(TokenType.PERIOD)) {
-      period = getAndAdvance();
-      name = parseSimpleIdentifier();
-    }
-    return astFactory.constructorName(type, period, name);
-  }
-
-  /// Parse a continue statement. Return the continue statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.CONTINUE`.
-  ///
-  ///     continueStatement ::=
-  ///         'continue' identifier? ';'
-  Statement parseContinueStatement() {
-    Token continueKeyword = getAndAdvance();
-    if (!_inLoop && !_inSwitch) {
-      _reportErrorForToken(
-          ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword);
-    }
-    SimpleIdentifier label;
-    if (_matchesIdentifier()) {
-      label = _parseSimpleIdentifierUnchecked();
-    }
-    if (_inSwitch && !_inLoop && label == null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeyword);
-    }
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.continueStatement(continueKeyword, label, semicolon);
-  }
-
-  /// Parse a directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the directive that was parsed.
-  ///
-  ///     directive ::=
-  ///         exportDirective
-  ///       | libraryDirective
-  ///       | importDirective
-  ///       | partDirective
-  Directive parseDirective(CommentAndMetadata commentAndMetadata) {
-    if (_matchesKeyword(Keyword.IMPORT)) {
-      return parseImportDirective(commentAndMetadata);
-    } else if (_matchesKeyword(Keyword.EXPORT)) {
-      return parseExportDirective(commentAndMetadata);
-    } else if (_matchesKeyword(Keyword.LIBRARY)) {
-      return parseLibraryDirective(commentAndMetadata);
-    } else if (_matchesKeyword(Keyword.PART)) {
-      return parsePartOrPartOfDirective(commentAndMetadata);
-    } else {
-      // Internal error: this method should not have been invoked if the current
-      // token was something other than one of the above.
-      throw StateError(
-          "parseDirective invoked in an invalid state; currentToken = $_currentToken");
-    }
-  }
-
-  /// Parse the script tag and directives in a compilation unit, starting with
-  /// the given [token], until the first non-directive is encountered. The
-  /// remainder of the compilation unit will not be parsed. Specifically, if
-  /// there are directives later in the file, they will not be parsed. Return
-  /// the compilation unit that was parsed.
   CompilationUnit parseDirectives(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseDirectives2();
   }
 
-  /// Parse the script tag and directives in a compilation unit until the first
-  /// non-directive is encountered. Return the compilation unit that was parsed.
-  ///
-  ///     compilationUnit ::=
-  ///         scriptTag? directive*
   CompilationUnit parseDirectives2() {
-    Token firstToken = _currentToken;
-    ScriptTag scriptTag;
-    if (_matches(TokenType.SCRIPT_TAG)) {
-      scriptTag = astFactory.scriptTag(getAndAdvance());
-    }
-    List<Directive> directives = <Directive>[];
-    while (!_matches(TokenType.EOF)) {
-      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-      Keyword keyword = _currentToken.keyword;
-      TokenType type = _peek().type;
-      if ((keyword == Keyword.IMPORT ||
-              keyword == Keyword.EXPORT ||
-              keyword == Keyword.LIBRARY ||
-              keyword == Keyword.PART) &&
-          type != TokenType.PERIOD &&
-          type != TokenType.LT &&
-          type != TokenType.OPEN_PAREN) {
-        directives.add(parseDirective(commentAndMetadata));
-      } else if (_matches(TokenType.SEMICOLON)) {
-        _advance();
-      } else {
-        while (!_matches(TokenType.EOF)) {
-          _advance();
-        }
-        return astFactory.compilationUnit(
-          beginToken: firstToken,
-          scriptTag: scriptTag,
-          directives: directives,
-          endToken: _currentToken,
-          featureSet: _featureSet,
-        );
-      }
-    }
-    return astFactory.compilationUnit(
-      beginToken: firstToken,
-      scriptTag: scriptTag,
-      directives: directives,
-      endToken: _currentToken,
-      featureSet: _featureSet,
-    );
+    currentToken = fastaParser.parseDirectives(currentToken);
+    return astBuilder.pop() as CompilationUnit;
   }
 
-  /// Parse a documentation comment based on the given list of documentation
-  /// comment tokens. Return the documentation comment that was parsed, or
-  /// `null` if there was no comment.
-  ///
-  ///     documentationComment ::=
-  ///         multiLineComment?
-  ///       | singleLineComment*
-  Comment parseDocumentationComment(List<DocumentationCommentToken> tokens) {
-    if (tokens == null) {
-      return null;
-    }
-    List<CommentReference> references = parseCommentReferences(tokens);
-    return astFactory.documentationComment(tokens, references);
-  }
-
-  /// Parse a documentation comment. Return the documentation comment that was
-  /// parsed, or `null` if there was no comment.
-  ///
-  ///     documentationComment ::=
-  ///         multiLineComment?
-  ///       | singleLineComment*
-  List<DocumentationCommentToken> parseDocumentationCommentTokens() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[];
-    CommentToken commentToken = _currentToken.precedingComments;
-    while (commentToken != null) {
-      if (commentToken is DocumentationCommentToken) {
-        if (tokens.isNotEmpty) {
-          if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
-            if (tokens[0].type != TokenType.SINGLE_LINE_COMMENT) {
-              tokens.clear();
-            }
-          } else {
-            tokens.clear();
-          }
-        }
-        tokens.add(commentToken);
-      }
-      commentToken = commentToken.next;
-    }
-    return tokens.isEmpty ? null : tokens;
-  }
-
-  /// Parse a do statement. Return the do statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.DO`.
-  ///
-  ///     doStatement ::=
-  ///         'do' statement 'while' '(' expression ')' ';'
-  Statement parseDoStatement() {
-    bool wasInLoop = _inLoop;
-    _inLoop = true;
-    try {
-      Token doKeyword = getAndAdvance();
-      Statement body = parseStatement2();
-      Token whileKeyword = _expectKeyword(Keyword.WHILE);
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      Expression condition = parseExpression2();
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.doStatement(doKeyword, body, whileKeyword,
-          leftParenthesis, condition, rightParenthesis, semicolon);
-    } finally {
-      _inLoop = wasInLoop;
-    }
-  }
-
-  /// Parse a dotted name. Return the dotted name that was parsed.
-  ///
-  ///     dottedName ::=
-  ///         identifier ('.' identifier)*
   DottedName parseDottedName() {
-    List<SimpleIdentifier> components = <SimpleIdentifier>[
-      parseSimpleIdentifier()
-    ];
-    while (_optional(TokenType.PERIOD)) {
-      components.add(parseSimpleIdentifier());
-    }
-    return astFactory.dottedName(components);
+    currentToken = fastaParser
+        .parseDottedName(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as DottedName;
   }
 
-  /// Parse an empty statement. Return the empty statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.SEMICOLON`.
-  ///
-  ///     emptyStatement ::=
-  ///         ';'
-  Statement parseEmptyStatement() => astFactory.emptyStatement(getAndAdvance());
+  Expression parseEqualityExpression() => parseExpression2();
 
-  /// Parse an enum declaration. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. Return the enum declaration that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.ENUM`.
-  ///
-  ///     enumType ::=
-  ///         metadata 'enum' id '{' id (',' id)* (',')? '}'
-  EnumDeclaration parseEnumDeclaration(CommentAndMetadata commentAndMetadata) {
-    Token keyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    Token leftBracket;
-    List<EnumConstantDeclaration> constants = <EnumConstantDeclaration>[];
-    Token rightBracket;
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      leftBracket = getAndAdvance();
-      if (_matchesIdentifier() || _matches(TokenType.AT)) {
-        constants.add(_parseEnumConstantDeclaration());
-      } else if (_matches(TokenType.COMMA) &&
-          _tokenMatchesIdentifier(_peek())) {
-        constants.add(_parseEnumConstantDeclaration());
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      } else {
-        constants.add(_parseEnumConstantDeclaration());
-        _reportErrorForCurrentToken(ParserErrorCode.EMPTY_ENUM_BODY);
-      }
-      while (_optional(TokenType.COMMA)) {
-        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-          break;
-        }
-        constants.add(_parseEnumConstantDeclaration());
-      }
-      rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-    } else {
-      leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
-      rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY);
-    }
-    return astFactory.enumDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        keyword,
-        name,
-        leftBracket,
-        constants,
-        rightBracket);
-  }
-
-  /// Parse an equality expression. Return the equality expression that was
-  /// parsed.
-  ///
-  ///     equalityExpression ::=
-  ///         relationalExpression (equalityOperator relationalExpression)?
-  ///       | 'super' equalityOperator relationalExpression
-  Expression parseEqualityExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isEqualityOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseRelationalExpression();
-    }
-    bool leftEqualityExpression = false;
-    while (_currentToken.type.isEqualityOperator) {
-      if (leftEqualityExpression) {
-        _reportErrorForNode(
-            ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression);
-      }
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseRelationalExpression());
-      leftEqualityExpression = true;
-    }
-    return expression;
-  }
-
-  /// Parse an export directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the export directive that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.EXPORT`.
-  ///
-  ///     exportDirective ::=
-  ///         metadata 'export' stringLiteral configuration* combinator*';'
-  ExportDirective parseExportDirective(CommentAndMetadata commentAndMetadata) {
-    Token exportKeyword = getAndAdvance();
-    StringLiteral libraryUri = _parseUri();
-    List<Configuration> configurations = _parseConfigurations();
-    List<Combinator> combinators = parseCombinators();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.exportDirective(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        exportKeyword,
-        libraryUri,
-        configurations,
-        combinators,
-        semicolon);
-  }
-
-  /// Parse an expression, starting with the given [token]. Return the
-  /// expression that was parsed, or `null` if the tokens do not represent a
-  /// recognizable expression.
   Expression parseExpression(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseExpression2();
   }
 
-  /// Parse an expression that might contain a cascade. Return the expression
-  /// that was parsed.
-  ///
-  ///     expression ::=
-  ///         assignableExpression assignmentOperator expression
-  ///       | conditionalExpression cascadeSection*
-  ///       | throwExpression
   Expression parseExpression2() {
-    if (_treeDepth > _MAX_TREE_DEPTH) {
-      throw _TooDeepTreeError();
-    }
-    _treeDepth++;
-    try {
-      Keyword keyword = _currentToken.keyword;
-      if (keyword == Keyword.THROW) {
-        return parseThrowExpression();
-      } else if (keyword == Keyword.RETHROW) {
-        // TODO(brianwilkerson) Rethrow is a statement again.
-        return parseRethrowExpression();
-      }
-      //
-      // assignableExpression is a subset of conditionalExpression, so we can
-      // parse a conditional expression and then determine whether it is followed
-      // by an assignmentOperator, checking for conformance to the restricted
-      // grammar after making that determination.
-      //
-      Expression expression = parseConditionalExpression();
-      TokenType type = _currentToken.type;
-      if (type == TokenType.PERIOD_PERIOD) {
-        List<Expression> cascadeSections = <Expression>[];
-        do {
-          Expression section = parseCascadeSection();
-          if (section != null) {
-            cascadeSections.add(section);
-          }
-        } while (_currentToken.type == TokenType.PERIOD_PERIOD);
-        return astFactory.cascadeExpression(expression, cascadeSections);
-      } else if (type.isAssignmentOperator) {
-        Token operator = getAndAdvance();
-        _ensureAssignable(expression);
-        return astFactory.assignmentExpression(
-            expression, operator, parseExpression2());
-      }
-      return expression;
-    } finally {
-      _treeDepth--;
-    }
+    currentToken = fastaParser
+        .parseExpression(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as Expression;
   }
 
-  /// Parse a list of expressions. Return the expression that was parsed.
-  ///
-  ///     expressionList ::=
-  ///         expression (',' expression)*
-  List<Expression> parseExpressionList() {
-    List<Expression> expressions = <Expression>[parseExpression2()];
-    while (_optional(TokenType.COMMA)) {
-      expressions.add(parseExpression2());
-    }
-    return expressions;
-  }
+  Expression parseExpressionWithoutCascade() => parseExpression2();
 
-  /// Parse an expression that does not contain any cascades. Return the
-  /// expression that was parsed.
-  ///
-  ///     expressionWithoutCascade ::=
-  ///         assignableExpression assignmentOperator expressionWithoutCascade
-  ///       | conditionalExpression
-  ///       | throwExpressionWithoutCascade
-  Expression parseExpressionWithoutCascade() {
-    if (_matchesKeyword(Keyword.THROW)) {
-      return parseThrowExpressionWithoutCascade();
-    } else if (_matchesKeyword(Keyword.RETHROW)) {
-      return parseRethrowExpression();
-    }
-    //
-    // assignableExpression is a subset of conditionalExpression, so we can
-    // parse a conditional expression and then determine whether it is followed
-    // by an assignmentOperator, checking for conformance to the restricted
-    // grammar after making that determination.
-    //
-    Expression expression = parseConditionalExpression();
-    if (_currentToken.type.isAssignmentOperator) {
-      Token operator = getAndAdvance();
-      _ensureAssignable(expression);
-      expression = astFactory.assignmentExpression(
-          expression, operator, parseExpressionWithoutCascade());
-    }
-    return expression;
-  }
-
-  /// Parse a class extends clause. Return the class extends clause that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.EXTENDS`.
-  ///
-  ///     classExtendsClause ::=
-  ///         'extends' type
-  ExtendsClause parseExtendsClause() {
-    Token keyword = getAndAdvance();
-    TypeName superclass = parseTypeName(false);
-    return astFactory.extendsClause(keyword, superclass);
-  }
-
-  /// Parse the 'final', 'const', 'var' or type preceding a variable
-  /// declaration. The [optional] is `true` if the keyword and type are
-  /// optional. Return the 'final', 'const', 'var' or type that was parsed.
-  ///
-  ///     finalConstVarOrType ::=
-  ///         'final' type?
-  ///       | 'const' type?
-  ///       | 'var'
-  ///       | type
-  FinalConstVarOrType parseFinalConstVarOrType(bool optional,
-      {bool inFunctionType = false}) {
-    Token keywordToken;
-    TypeAnnotation type;
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
-      keywordToken = getAndAdvance();
-      if (_isTypedIdentifier(_currentToken)) {
-        type = parseTypeAnnotation(false);
-      }
-    } else if (keyword == Keyword.VAR) {
-      keywordToken = getAndAdvance();
-    } else if (_isTypedIdentifier(_currentToken)) {
-      type = parseTypeAnnotation(false);
-    } else if (inFunctionType && _matchesIdentifier()) {
-      type = parseTypeAnnotation(false);
-    } else if (!optional) {
-      // If there is a valid type immediately following an unexpected token,
-      // then report and skip the unexpected token.
-      Token next = _peek();
-      Keyword nextKeyword = next.keyword;
-      if (nextKeyword == Keyword.FINAL ||
-          nextKeyword == Keyword.CONST ||
-          nextKeyword == Keyword.VAR ||
-          _isTypedIdentifier(next) ||
-          inFunctionType && _tokenMatchesIdentifier(next)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-        _advance();
-        return parseFinalConstVarOrType(optional,
-            inFunctionType: inFunctionType);
-      }
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
-    } else {
-      // Support parameters such as `(/*=K*/ key, /*=V*/ value)`
-      // This is not supported if the type is required.
-      type;
-    }
-    return FinalConstVarOrType(keywordToken, type);
-  }
-
-  /// Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
-  /// `true`. The [kind] is the kind of parameter being expected based on the
-  /// presence or absence of group delimiters. Return the formal parameter that
-  /// was parsed.
-  ///
-  ///     defaultFormalParameter ::=
-  ///         normalFormalParameter ('=' expression)?
-  ///
-  ///     defaultNamedParameter ::=
-  ///         normalFormalParameter ('=' expression)?
-  ///         normalFormalParameter (':' expression)?
-  FormalParameter parseFormalParameter(ParameterKind kind,
-      {bool inFunctionType = false}) {
-    NormalFormalParameter parameter =
-        parseNormalFormalParameter(inFunctionType: inFunctionType);
-    TokenType type = _currentToken.type;
-    if (type == TokenType.EQ) {
-      if (inFunctionType) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE);
-      }
-      Token separator = getAndAdvance();
-      Expression defaultValue = parseExpression2();
-      if (kind == ParameterKind.REQUIRED) {
-        _reportErrorForNode(
-            ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter);
-        kind = ParameterKind.POSITIONAL;
-      } else if (kind == ParameterKind.NAMED &&
-          inFunctionType &&
-          parameter.identifier == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
-        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
-      }
-      return astFactory.defaultFormalParameter(
-          parameter, kind, separator, defaultValue);
-    } else if (type == TokenType.COLON) {
-      if (inFunctionType) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE);
-      }
-      Token separator = getAndAdvance();
-      Expression defaultValue = parseExpression2();
-      if (kind == ParameterKind.REQUIRED) {
-        _reportErrorForNode(
-            ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter);
-        kind = ParameterKind.NAMED;
-      } else if (kind == ParameterKind.POSITIONAL) {
-        _reportErrorForToken(
-            ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
-            separator);
-      } else if (kind == ParameterKind.NAMED &&
-          inFunctionType &&
-          parameter.identifier == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
-        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
-      }
-      return astFactory.defaultFormalParameter(
-          parameter, kind, separator, defaultValue);
-    } else if (kind != ParameterKind.REQUIRED) {
-      if (kind == ParameterKind.NAMED &&
-          inFunctionType &&
-          parameter.identifier == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
-        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
-      }
-      return astFactory.defaultFormalParameter(parameter, kind, null, null);
-    }
-    return parameter;
-  }
-
-  /// Parse a list of formal parameters. Return the formal parameters that were
-  /// parsed.
-  ///
-  ///     formalParameterList ::=
-  ///         '(' ')'
-  ///       | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
-  ///       | '(' optionalFormalParameters ')'
-  ///
-  ///     normalFormalParameters ::=
-  ///         normalFormalParameter (',' normalFormalParameter)*
-  ///
-  ///     optionalFormalParameters ::=
-  ///         optionalPositionalFormalParameters
-  ///       | namedFormalParameters
-  ///
-  ///     optionalPositionalFormalParameters ::=
-  ///         '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
-  ///
-  ///     namedFormalParameters ::=
-  ///         '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
   FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
-    if (_matches(TokenType.OPEN_PAREN)) {
-      return _parseFormalParameterListUnchecked(inFunctionType: inFunctionType);
-    }
-    // TODO(brianwilkerson) Improve the error message.
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_PAREN.lexeme]);
-    // Recovery: Check for an unmatched closing paren and parse parameters until
-    // it is reached.
-    return _parseFormalParameterListAfterParen(
-        _createSyntheticToken(TokenType.OPEN_PAREN));
+    currentToken = fastaParser
+        .parseFormalParametersRequiredOpt(
+            fastaParser.syntheticPreviousToken(currentToken),
+            inFunctionType
+                ? fasta.MemberKind.GeneralizedFunctionType
+                : fasta.MemberKind.NonStaticMethod)
+        .next;
+    return astBuilder.pop() as FormalParameterList;
   }
 
-  /// Parse a for statement. Return the for statement that was parsed.
-  ///
-  ///     forStatement ::=
-  ///         'for' '(' forLoopParts ')' statement
-  ///
-  ///     forLoopParts ::=
-  ///         forInitializerStatement expression? ';' expressionList?
-  ///       | declaredIdentifier 'in' expression
-  ///       | identifier 'in' expression
-  ///
-  ///     forInitializerStatement ::=
-  ///         localVariableDeclaration ';'
-  ///       | expression? ';'
-  Statement parseForStatement() {
-    bool wasInLoop = _inLoop;
-    _inLoop = true;
-    try {
-      Token awaitKeyword;
-      if (_matchesKeyword(Keyword.AWAIT)) {
-        awaitKeyword = getAndAdvance();
-      }
-      Token forKeyword = _expectKeyword(Keyword.FOR);
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      VariableDeclarationList variableList;
-      Expression initialization;
-      if (!_matches(TokenType.SEMICOLON)) {
-        CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-        if (_matchesIdentifier() &&
-            (_tokenMatchesKeyword(_peek(), Keyword.IN) ||
-                _tokenMatches(_peek(), TokenType.COLON))) {
-          SimpleIdentifier variableName = _parseSimpleIdentifierUnchecked();
-          variableList = astFactory.variableDeclarationList(
-              commentAndMetadata.comment,
-              commentAndMetadata.metadata,
-              null,
-              null, <VariableDeclaration>[
-            astFactory.variableDeclaration(variableName, null, null)
-          ]);
-        } else if (isInitializedVariableDeclaration()) {
-          variableList =
-              parseVariableDeclarationListAfterMetadata(commentAndMetadata);
-        } else {
-          initialization = parseExpression2();
-        }
-        TokenType type = _currentToken.type;
-        if (_matchesKeyword(Keyword.IN) || type == TokenType.COLON) {
-          if (type == TokenType.COLON) {
-            _reportErrorForCurrentToken(ParserErrorCode.COLON_IN_PLACE_OF_IN);
-          }
-          DeclaredIdentifier loopVariable;
-          SimpleIdentifier identifier;
-          if (variableList == null) {
-            // We found: <expression> 'in'
-            _reportErrorForCurrentToken(
-                ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH);
-          } else {
-            NodeList<VariableDeclaration> variables = variableList.variables;
-            if (variables.length > 1) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH,
-                  [variables.length.toString()]);
-            }
-            VariableDeclaration variable = variables[0];
-            if (variable.initializer != null) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH);
-            }
-            Token keyword = variableList.keyword;
-            TypeAnnotation type = variableList.type;
-            if (keyword != null || type != null) {
-              loopVariable = astFactory.declaredIdentifier(
-                  commentAndMetadata.comment,
-                  commentAndMetadata.metadata,
-                  keyword,
-                  type,
-                  astFactory.simpleIdentifier(variable.name.token,
-                      isDeclaration: true));
-            } else {
-              if (commentAndMetadata.hasMetadata) {
-                // TODO(jwren) metadata isn't allowed before the identifier in
-                // "identifier in expression", add warning if commentAndMetadata
-                // has content
-              }
-              identifier = variable.name;
-            }
-          }
-          Token inKeyword = getAndAdvance();
-          Expression iterator = parseExpression2();
-          Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-          Statement body = parseStatement2();
-          ForLoopParts forLoopParts;
-          if (loopVariable == null) {
-            forLoopParts = astFactory.forEachPartsWithIdentifier(
-                identifier: identifier,
-                inKeyword: inKeyword,
-                iterable: iterator);
-          } else {
-            forLoopParts = astFactory.forEachPartsWithDeclaration(
-                loopVariable: loopVariable,
-                inKeyword: inKeyword,
-                iterable: iterator);
-          }
-          return astFactory.forStatement(
-              forKeyword: forKeyword,
-              leftParenthesis: leftParenthesis,
-              forLoopParts: forLoopParts,
-              rightParenthesis: rightParenthesis,
-              body: body);
-        }
-      }
-      if (awaitKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword);
-      }
-      Token leftSeparator = _expect(TokenType.SEMICOLON);
-      Expression condition;
-      if (!_matches(TokenType.SEMICOLON)) {
-        condition = parseExpression2();
-      }
-      Token rightSeparator = _expect(TokenType.SEMICOLON);
-      List<Expression> updaters;
-      if (!_matches(TokenType.CLOSE_PAREN)) {
-        updaters = parseExpressionList();
-      }
-      ForLoopParts forLoopParts;
-      if (variableList != null) {
-        forLoopParts = astFactory.forPartsWithDeclarations(
-            variables: variableList,
-            leftSeparator: leftSeparator,
-            condition: condition,
-            rightSeparator: rightSeparator,
-            updaters: updaters);
-      } else {
-        forLoopParts = astFactory.forPartsWithExpression(
-            initialization: initialization,
-            leftSeparator: leftSeparator,
-            condition: condition,
-            rightSeparator: rightSeparator,
-            updaters: updaters);
-      }
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Statement body = parseStatement2();
-      return astFactory.forStatement(
-          forKeyword: forKeyword,
-          leftParenthesis: leftParenthesis,
-          forLoopParts: forLoopParts,
-          rightParenthesis: rightParenthesis,
-          body: body);
-    } finally {
-      _inLoop = wasInLoop;
-    }
-  }
-
-  /// Parse a function body. The [mayBeEmpty] is `true` if the function body is
-  /// allowed to be empty. The [emptyErrorCode] is the error code to report if
-  /// function body expected, but not found. The [inExpression] is `true` if the
-  /// function body is being parsed as part of an expression and therefore does
-  /// not have a terminating semicolon. Return the function body that was
-  /// parsed.
-  ///
-  ///     functionBody ::=
-  ///         '=>' expression ';'
-  ///       | block
-  ///
-  ///     functionExpressionBody ::=
-  ///         '=>' expression
-  ///       | block
   FunctionBody parseFunctionBody(
       bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
-    bool wasInAsync = _inAsync;
-    bool wasInGenerator = _inGenerator;
-    bool wasInLoop = _inLoop;
-    bool wasInSwitch = _inSwitch;
-    _inAsync = false;
-    _inGenerator = false;
-    _inLoop = false;
-    _inSwitch = false;
-    try {
-      TokenType type = _currentToken.type;
-      if (type == TokenType.SEMICOLON) {
-        if (!mayBeEmpty) {
-          _reportErrorForCurrentToken(emptyErrorCode);
-        }
-        return astFactory.emptyFunctionBody(getAndAdvance());
-      }
-      Token keyword;
-      Token star;
-      bool foundAsync = false;
-      bool foundSync = false;
-      if (type.isKeyword) {
-        String lexeme = _currentToken.lexeme;
-        if (lexeme == ASYNC) {
-          foundAsync = true;
-          keyword = getAndAdvance();
-          if (_matches(TokenType.STAR)) {
-            star = getAndAdvance();
-            _inGenerator = true;
-          }
-          type = _currentToken.type;
-          _inAsync = true;
-        } else if (lexeme == SYNC) {
-          foundSync = true;
-          keyword = getAndAdvance();
-          if (_matches(TokenType.STAR)) {
-            star = getAndAdvance();
-            _inGenerator = true;
-          }
-          type = _currentToken.type;
-        }
-      }
-      if (type == TokenType.FUNCTION) {
-        if (keyword != null) {
-          if (!foundAsync) {
-            _reportErrorForToken(ParserErrorCode.INVALID_SYNC, keyword);
-            keyword;
-          } else if (star != null) {
-            _reportErrorForToken(
-                ParserErrorCode.INVALID_STAR_AFTER_ASYNC, star);
-          }
-        }
-        Token functionDefinition = getAndAdvance();
-        if (_matchesKeyword(Keyword.RETURN)) {
-          _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-              [_currentToken.lexeme]);
-          _advance();
-        }
-        Expression expression = parseExpression2();
-        Token semicolon;
-        if (!inExpression) {
-          semicolon = _expect(TokenType.SEMICOLON);
-        }
-        if (!_parseFunctionBodies) {
-          return astFactory
-              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
-        }
-        return astFactory.expressionFunctionBody(
-            keyword, functionDefinition, expression, semicolon);
-      } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-        if (keyword != null) {
-          if (foundSync && star == null) {
-            _reportErrorForToken(
-                ParserErrorCode.MISSING_STAR_AFTER_SYNC, keyword);
-          }
-        }
-        if (!_parseFunctionBodies) {
-          _skipBlock();
-          return astFactory
-              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
-        }
-        return astFactory.blockFunctionBody(keyword, star, parseBlock());
-      } else if (_matchesKeyword(Keyword.NATIVE)) {
-        Token nativeToken = getAndAdvance();
-        StringLiteral stringLiteral;
-        if (_matches(TokenType.STRING)) {
-          stringLiteral = _parseStringLiteralUnchecked();
-        }
-        return astFactory.nativeFunctionBody(
-            nativeToken, stringLiteral, _expect(TokenType.SEMICOLON));
-      } else {
-        // Invalid function body
-        _reportErrorForCurrentToken(emptyErrorCode);
-        return astFactory
-            .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
-      }
-    } finally {
-      _inAsync = wasInAsync;
-      _inGenerator = wasInGenerator;
-      _inLoop = wasInLoop;
-      _inSwitch = wasInSwitch;
-    }
+    currentToken = fastaParser.parseAsyncModifierOpt(
+        fastaParser.syntheticPreviousToken(currentToken));
+    currentToken =
+        fastaParser.parseFunctionBody(currentToken, inExpression, mayBeEmpty);
+    return astBuilder.pop() as FunctionBody;
   }
 
-  /// Parse a function declaration. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [externalKeyword] is the 'external' keyword, or `null` if the
-  /// function is not external. The [returnType] is the return type, or `null`
-  /// if there is no return type. The [isStatement] is `true` if the function
-  /// declaration is being parsed as a statement. Return the function
-  /// declaration that was parsed.
-  ///
-  ///     functionDeclaration ::=
-  ///         functionSignature functionBody
-  ///       | returnType? getOrSet identifier formalParameterList functionBody
-  FunctionDeclaration parseFunctionDeclaration(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      TypeAnnotation returnType) {
-    Token keywordToken;
-    bool isGetter = false;
-    Keyword keyword = _currentToken.keyword;
-    SimpleIdentifier name;
-    if (keyword == Keyword.GET) {
-      keywordToken = getAndAdvance();
-      isGetter = true;
-    } else if (keyword == Keyword.SET) {
-      keywordToken = getAndAdvance();
-    }
-    if (keywordToken != null && _matches(TokenType.OPEN_PAREN)) {
-      name = astFactory.simpleIdentifier(keywordToken, isDeclaration: true);
-      keywordToken;
-      isGetter = false;
-    } else {
-      name = parseSimpleIdentifier(isDeclaration: true);
-    }
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    FormalParameterList parameters;
-    if (!isGetter) {
-      if (_matches(TokenType.OPEN_PAREN)) {
-        parameters = _parseFormalParameterListUnchecked();
-        _validateFormalParameterList(parameters);
-      } else {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_FUNCTION_PARAMETERS);
-        parameters = astFactory.formalParameterList(
-            _createSyntheticToken(TokenType.OPEN_PAREN),
-            null,
-            null,
-            null,
-            _createSyntheticToken(TokenType.CLOSE_PAREN));
-      }
-    } else if (_matches(TokenType.OPEN_PAREN)) {
-      _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
-      _parseFormalParameterListUnchecked();
-    }
-    FunctionBody body;
-    if (externalKeyword == null) {
-      body = parseFunctionBody(
-          false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-    } else {
-      body = astFactory.emptyFunctionBody(_expect(TokenType.SEMICOLON));
-    }
-//        if (!isStatement && matches(TokenType.SEMICOLON)) {
-//          // TODO(brianwilkerson) Improve this error message.
-//          reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme());
-//          advance();
-//        }
-    return astFactory.functionDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        returnType,
-        keywordToken,
-        name,
-        astFactory.functionExpression(typeParameters, parameters, body));
-  }
+  FunctionExpression parseFunctionExpression() =>
+      parseExpression2() as FunctionExpression;
 
-  /// Parse a function declaration statement. Return the function declaration
-  /// statement that was parsed.
-  ///
-  ///     functionDeclarationStatement ::=
-  ///         functionSignature functionBody
-  Statement parseFunctionDeclarationStatement() {
-    Modifiers modifiers = parseModifiers();
-    _validateModifiersForFunctionDeclarationStatement(modifiers);
-    return _parseFunctionDeclarationStatementAfterReturnType(
-        parseCommentAndMetadata(), _parseOptionalReturnType());
-  }
+  Expression parseLogicalAndExpression() => parseExpression2();
 
-  /// Parse a function expression. Return the function expression that was
-  /// parsed.
-  ///
-  ///     functionExpression ::=
-  ///         typeParameters? formalParameterList functionExpressionBody
-  FunctionExpression parseFunctionExpression() {
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    FormalParameterList parameters = parseFormalParameterList();
-    _validateFormalParameterList(parameters);
-    FunctionBody body =
-        parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
-    return astFactory.functionExpression(typeParameters, parameters, body);
-  }
+  Expression parseLogicalOrExpression() => parseExpression2();
 
-  /// Parse the portion of a generic function type following the [returnType].
-  ///
-  ///     functionType ::=
-  ///         returnType? 'Function' typeParameters? parameterTypeList
-  ///     parameterTypeList ::=
-  ///         '(' ')' |
-  ///       | '(' normalParameterTypes ','? ')' |
-  ///       | '(' normalParameterTypes ',' optionalParameterTypes ')' |
-  ///       | '(' optionalParameterTypes ')'
-  ///     normalParameterTypes ::=
-  ///         normalParameterType (',' normalParameterType)*
-  ///     normalParameterType ::=
-  ///         type | typedIdentifier
-  ///     optionalParameterTypes ::=
-  ///         optionalPositionalParameterTypes | namedParameterTypes
-  ///     optionalPositionalParameterTypes ::=
-  ///         '[' normalParameterTypes ','? ']'
-  ///     namedParameterTypes ::=
-  ///         '{' typedIdentifier (',' typedIdentifier)* ','? '}'
-  ///     typedIdentifier ::=
-  ///         type identifier
-  GenericFunctionType parseGenericFunctionTypeAfterReturnType(
-      TypeAnnotation returnType) {
-    Token functionKeyword;
-    if (_matchesKeyword(Keyword.FUNCTION)) {
-      functionKeyword = getAndAdvance();
-    } else if (_matchesIdentifier()) {
-      _reportErrorForCurrentToken(ParserErrorCode.NAMED_FUNCTION_TYPE);
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_FUNCTION_KEYWORD);
-    }
-    TypeParameterList typeParameters;
-    if (_matches(TokenType.LT)) {
-      typeParameters = parseTypeParameterList();
-    }
-    FormalParameterList parameters =
-        parseFormalParameterList(inFunctionType: true);
-    return astFactory.genericFunctionType(
-        returnType, functionKeyword, typeParameters, parameters);
-  }
+  Expression parseMultiplicativeExpression() => parseExpression2();
 
-  /// Parse a generic function type alias.
-  ///
-  /// This method assumes that the current token is an identifier.
-  ///
-  ///     genericTypeAlias ::=
-  ///         'typedef' identifier typeParameterList? '=' functionType ';'
-  GenericTypeAlias parseGenericTypeAlias(
-      CommentAndMetadata commentAndMetadata, Token keyword) {
-    Identifier name = _parseSimpleIdentifierUnchecked(isDeclaration: true);
-    TypeParameterList typeParameters;
-    if (_matches(TokenType.LT)) {
-      typeParameters = parseTypeParameterList();
-    }
-    Token equals = _expect(TokenType.EQ);
-    TypeAnnotation functionType = parseTypeAnnotation(false);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    if (functionType is! GenericFunctionType) {
-      // TODO(brianwilkerson) Generate a better error.
-      _reportErrorForToken(
-          ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, semicolon);
-      // TODO(brianwilkerson) Recover better than this.
-      return astFactory.genericTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          name,
-          typeParameters,
-          equals,
-          null,
-          semicolon);
-    }
-    return astFactory.genericTypeAlias(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        keyword,
-        name,
-        typeParameters,
-        equals,
-        functionType,
-        semicolon);
-  }
-
-  /// Parse a getter. The [commentAndMetadata] is the documentation comment and
-  /// metadata to be associated with the declaration. The externalKeyword] is
-  /// the 'external' token. The staticKeyword] is the static keyword, or `null`
-  /// if the getter is not static. The [returnType] the return type that has
-  /// already been parsed, or `null` if there was no return type. Return the
-  /// getter that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.GET`.
-  ///
-  ///     getter ::=
-  ///         getterSignature functionBody?
-  ///
-  ///     getterSignature ::=
-  ///         'external'? 'static'? returnType? 'get' identifier
-  MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata,
-      Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) {
-    Token propertyKeyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    if (_matches(TokenType.OPEN_PAREN) &&
-        _tokenMatches(_peek(), TokenType.CLOSE_PAREN)) {
-      _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
-      _advance();
-      _advance();
-    }
-    FunctionBody body = parseFunctionBody(
-        externalKeyword != null || staticKeyword == null,
-        ParserErrorCode.STATIC_GETTER_WITHOUT_BODY,
-        false);
-    if (externalKeyword != null && body is! EmptyFunctionBody) {
-      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY);
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        propertyKeyword,
-        null,
-        name,
-        null,
-        null,
-        body);
-  }
-
-  /// Parse a list of identifiers. Return the list of identifiers that were
-  /// parsed.
-  ///
-  ///     identifierList ::=
-  ///         identifier (',' identifier)*
-  List<SimpleIdentifier> parseIdentifierList() {
-    List<SimpleIdentifier> identifiers = <SimpleIdentifier>[
-      parseSimpleIdentifier()
-    ];
-    while (_optional(TokenType.COMMA)) {
-      identifiers.add(parseSimpleIdentifier());
-    }
-    return identifiers;
-  }
-
-  /// Parse an if-null expression.  Return the if-null expression that was
-  /// parsed.
-  ///
-  ///     ifNullExpression ::= logicalOrExpression ('??' logicalOrExpression)*
-  Expression parseIfNullExpression() {
-    Expression expression = parseLogicalOrExpression();
-    while (_currentToken.type == TokenType.QUESTION_QUESTION) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseLogicalOrExpression());
-    }
-    return expression;
-  }
-
-  /// Parse an if statement. Return the if statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.IF`.
-  ///
-  ///     ifStatement ::=
-  ///         'if' '(' expression ')' statement ('else' statement)?
-  Statement parseIfStatement() {
-    Token ifKeyword = getAndAdvance();
-    Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-    Expression condition = parseExpression2();
-    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-    Statement thenStatement = parseStatement2();
-    Token elseKeyword;
-    Statement elseStatement;
-    if (_matchesKeyword(Keyword.ELSE)) {
-      elseKeyword = getAndAdvance();
-      elseStatement = parseStatement2();
-    }
-    return astFactory.ifStatement(ifKeyword, leftParenthesis, condition,
-        rightParenthesis, thenStatement, elseKeyword, elseStatement);
-  }
-
-  /// Parse an implements clause. Return the implements clause that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.IMPLEMENTS`.
-  ///
-  ///     implementsClause ::=
-  ///         'implements' type (',' type)*
-  ImplementsClause parseImplementsClause() {
-    Token keyword = getAndAdvance();
-    List<TypeName> interfaces = <TypeName>[];
-    do {
-      TypeName typeName = parseTypeName(false);
-      interfaces.add(typeName);
-    } while (_optional(TokenType.COMMA));
-    return astFactory.implementsClause(keyword, interfaces);
-  }
-
-  /// Parse an import directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the import directive that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.IMPORT`.
-  ///
-  ///     importDirective ::=
-  ///         metadata 'import' stringLiteral configuration* (deferred)? ('as' identifier)? combinator*';'
-  ImportDirective parseImportDirective(CommentAndMetadata commentAndMetadata) {
-    Token importKeyword = getAndAdvance();
-    StringLiteral libraryUri = _parseUri();
-    List<Configuration> configurations = _parseConfigurations();
-    Token deferredToken;
-    Token asToken;
-    SimpleIdentifier prefix;
-    if (_matchesKeyword(Keyword.DEFERRED)) {
-      deferredToken = getAndAdvance();
-    }
-    if (_matchesKeyword(Keyword.AS)) {
-      asToken = getAndAdvance();
-      prefix = parseSimpleIdentifier(isDeclaration: true);
-    } else if (deferredToken != null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT);
-    } else if (!_matches(TokenType.SEMICOLON) &&
-        !_matchesKeyword(Keyword.SHOW) &&
-        !_matchesKeyword(Keyword.HIDE)) {
-      Token nextToken = _peek();
-      if (_tokenMatchesKeyword(nextToken, Keyword.AS) ||
-          _tokenMatchesKeyword(nextToken, Keyword.SHOW) ||
-          _tokenMatchesKeyword(nextToken, Keyword.HIDE)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken]);
-        _advance();
-        if (_matchesKeyword(Keyword.AS)) {
-          asToken = getAndAdvance();
-          prefix = parseSimpleIdentifier(isDeclaration: true);
-        }
-      }
-    }
-    List<Combinator> combinators = parseCombinators();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.importDirective(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        importKeyword,
-        libraryUri,
-        configurations,
-        deferredToken,
-        asToken,
-        prefix,
-        combinators,
-        semicolon);
-  }
-
-  /// Parse a list of initialized identifiers. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [staticKeyword] is the static keyword, or `null` if the getter is not
-  /// static. The [keyword] is the token representing the 'final', 'const' or
-  /// 'var' keyword, or `null` if there is no keyword. The [type] is the type
-  /// that has already been parsed, or `null` if 'var' was provided. Return the
-  /// getter that was parsed.
-  ///
-  ///     declaration ::=
-  ///         ('static' | 'covariant')? ('var' | type) initializedIdentifierList ';'
-  ///       | 'final' type? initializedIdentifierList ';'
-  ///
-  ///     initializedIdentifierList ::=
-  ///         initializedIdentifier (',' initializedIdentifier)*
-  ///
-  ///     initializedIdentifier ::=
-  ///         identifier ('=' expression)?
-  FieldDeclaration parseInitializedIdentifierList(
-      CommentAndMetadata commentAndMetadata,
-      Token staticKeyword,
-      Token covariantKeyword,
-      Token keyword,
-      TypeAnnotation type) {
-    VariableDeclarationList fieldList =
-        parseVariableDeclarationListAfterType(null, keyword, type);
-    return astFactory.fieldDeclaration2(
-        comment: commentAndMetadata.comment,
-        metadata: commentAndMetadata.metadata,
-        covariantKeyword: covariantKeyword,
-        staticKeyword: staticKeyword,
-        fieldList: fieldList,
-        semicolon: _expect(TokenType.SEMICOLON));
-  }
-
-  /// Parse an instance creation expression. The [keyword] is the 'new' or
-  /// 'const' keyword that introduces the expression. Return the instance
-  /// creation expression that was parsed.
-  ///
-  ///     instanceCreationExpression ::=
-  ///         ('new' | 'const') type ('.' identifier)? argumentList
-  InstanceCreationExpression parseInstanceCreationExpression(Token keyword) {
-    ConstructorName constructorName = parseConstructorName();
-    ArgumentList argumentList = _parseArgumentListChecked();
-    return astFactory.instanceCreationExpression(
-        keyword, constructorName, argumentList);
-  }
-
-  /// Parse a label. Return the label that was parsed.
-  ///
-  /// This method assumes that the current token matches an identifier and that
-  /// the following token matches `TokenType.COLON`.
-  ///
-  ///     label ::=
-  ///         identifier ':'
-  Label parseLabel({bool isDeclaration = false}) {
-    SimpleIdentifier label =
-        _parseSimpleIdentifierUnchecked(isDeclaration: isDeclaration);
-    Token colon = getAndAdvance();
-    return astFactory.label(label, colon);
-  }
-
-  /// Parse a library directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the library directive that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.LIBRARY`.
-  ///
-  ///     libraryDirective ::=
-  ///         metadata 'library' identifier ';'
-  LibraryDirective parseLibraryDirective(
-      CommentAndMetadata commentAndMetadata) {
-    Token keyword = getAndAdvance();
-    LibraryIdentifier libraryName = _parseLibraryName(
-        ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE, keyword);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.libraryDirective(commentAndMetadata.comment,
-        commentAndMetadata.metadata, keyword, libraryName, semicolon);
-  }
-
-  /// Parse a library identifier. Return the library identifier that was parsed.
-  ///
-  ///     libraryIdentifier ::=
-  ///         identifier ('.' identifier)*
-  LibraryIdentifier parseLibraryIdentifier() {
-    List<SimpleIdentifier> components = <SimpleIdentifier>[];
-    components.add(parseSimpleIdentifier());
-    while (_optional(TokenType.PERIOD)) {
-      components.add(parseSimpleIdentifier());
-    }
-    return astFactory.libraryIdentifier(components);
-  }
-
-  /// Parse a list literal. The [modifier] is the 'const' modifier appearing
-  /// before the literal, or `null` if there is no modifier. The [typeArguments]
-  /// is the type arguments appearing before the literal, or `null` if there are
-  /// no type arguments. Return the list literal that was parsed.
-  ///
-  /// This method assumes that the current token matches either
-  /// `TokenType.OPEN_SQUARE_BRACKET` or `TokenType.INDEX`.
-  ///
-  ///     listLiteral ::=
-  ///         'const'? typeArguments? '[' (expressionList ','?)? ']'
-  ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
-    if (_matches(TokenType.INDEX)) {
-      _splitIndex();
-      return astFactory.listLiteral(
-          modifier, typeArguments, getAndAdvance(), null, getAndAdvance());
-    }
-    Token leftBracket = getAndAdvance();
-    if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
-      return astFactory.listLiteral(
-          modifier, typeArguments, leftBracket, null, getAndAdvance());
-    }
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = false;
-    try {
-      List<Expression> elements = <Expression>[parseExpression2()];
-      while (_optional(TokenType.COMMA)) {
-        if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
-          return astFactory.listLiteral(
-              modifier, typeArguments, leftBracket, elements, getAndAdvance());
-        }
-        elements.add(parseExpression2());
-      }
-      Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
-      return astFactory.listLiteral(
-          modifier, typeArguments, leftBracket, elements, rightBracket);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
-
-  /// Parse a list or map literal. The [modifier] is the 'const' modifier
-  /// appearing before the literal, or `null` if there is no modifier. Return
-  /// the list or map literal that was parsed.
-  ///
-  ///     listOrMapLiteral ::=
-  ///         listLiteral
-  ///       | mapLiteral
-  TypedLiteral parseListOrMapLiteral(Token modifier) {
-    TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      return parseMapLiteral(modifier, typeArguments);
-    } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
-        _matches(TokenType.INDEX)) {
-      return parseListLiteral(modifier, typeArguments);
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL);
-    return astFactory.listLiteral(
-        modifier,
-        typeArguments,
-        _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET),
-        null,
-        _createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET));
-  }
-
-  /// Parse a logical and expression. Return the logical and expression that was
-  /// parsed.
-  ///
-  ///     logicalAndExpression ::=
-  ///         equalityExpression ('&&' equalityExpression)*
-  Expression parseLogicalAndExpression() {
-    Expression expression = parseEqualityExpression();
-    while (_currentToken.type == TokenType.AMPERSAND_AMPERSAND) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseEqualityExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a logical or expression. Return the logical or expression that was
-  /// parsed.
-  ///
-  ///     logicalOrExpression ::=
-  ///         logicalAndExpression ('||' logicalAndExpression)*
-  Expression parseLogicalOrExpression() {
-    Expression expression = parseLogicalAndExpression();
-    while (_currentToken.type == TokenType.BAR_BAR) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseLogicalAndExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a map literal. The [modifier] is the 'const' modifier appearing
-  /// before the literal, or `null` if there is no modifier. The [typeArguments]
-  /// is the type arguments that were declared, or `null` if there are no type
-  /// arguments. Return the map literal that was parsed.
-  ///
-  /// This method assumes that the current token matches
-  /// `TokenType.OPEN_CURLY_BRACKET`.
-  ///
-  ///     mapLiteral ::=
-  ///         'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
-  SetOrMapLiteral parseMapLiteral(
-      Token modifier, TypeArgumentList typeArguments) {
-    Token leftBracket = getAndAdvance();
-    if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-      return astFactory.setOrMapLiteral(
-          constKeyword: modifier,
-          typeArguments: typeArguments,
-          leftBracket: leftBracket,
-          rightBracket: getAndAdvance());
-    }
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = false;
-    try {
-      List<MapLiteralEntry> entries = <MapLiteralEntry>[parseMapLiteralEntry()];
-      while (_optional(TokenType.COMMA)) {
-        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-          return astFactory.setOrMapLiteral(
-              constKeyword: modifier,
-              typeArguments: typeArguments,
-              leftBracket: leftBracket,
-              elements: entries,
-              rightBracket: getAndAdvance());
-        }
-        entries.add(parseMapLiteralEntry());
-      }
-      Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-      return astFactory.setOrMapLiteral(
-          constKeyword: modifier,
-          typeArguments: typeArguments,
-          leftBracket: leftBracket,
-          elements: entries,
-          rightBracket: rightBracket);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
-
-  /// Parse a map literal entry. Return the map literal entry that was parsed.
-  ///
-  ///     mapLiteralEntry ::=
-  ///         expression ':' expression
-  MapLiteralEntry parseMapLiteralEntry() {
-    Expression key = parseExpression2();
-    Token separator = _expect(TokenType.COLON);
-    Expression value = parseExpression2();
-    return astFactory.mapLiteralEntry(key, separator, value);
-  }
-
-  /// Parse the modifiers preceding a declaration. This method allows the
-  /// modifiers to appear in any order but does generate errors for duplicated
-  /// modifiers. Checks for other problems, such as having the modifiers appear
-  /// in the wrong order or specifying both 'const' and 'final', are reported in
-  /// one of the methods whose name is prefixed with `validateModifiersFor`.
-  /// Return the modifiers that were parsed.
-  ///
-  ///     modifiers ::=
-  ///         ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')*
-  Modifiers parseModifiers() {
-    Modifiers modifiers = Modifiers();
-    bool progress = true;
-    while (progress) {
-      TokenType nextType = _peek().type;
-      if (nextType == TokenType.PERIOD ||
-          nextType == TokenType.LT ||
-          nextType == TokenType.OPEN_PAREN) {
-        return modifiers;
-      }
-      Keyword keyword = _currentToken.keyword;
-      if (keyword == Keyword.ABSTRACT) {
-        if (modifiers.abstractKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.abstractKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.CONST) {
-        if (modifiers.constKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.constKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.COVARIANT) {
-        if (modifiers.covariantKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.covariantKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.EXTERNAL) {
-        if (modifiers.externalKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.externalKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.FACTORY) {
-        if (modifiers.factoryKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.factoryKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.FINAL) {
-        if (modifiers.finalKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.finalKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.STATIC) {
-        if (modifiers.staticKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.staticKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.VAR) {
-        if (modifiers.varKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.varKeyword = getAndAdvance();
-        }
-      } else {
-        progress = false;
-      }
-    }
-    return modifiers;
-  }
-
-  /// Parse a multiplicative expression. Return the multiplicative expression
-  /// that was parsed.
-  ///
-  ///     multiplicativeExpression ::=
-  ///         unaryExpression (multiplicativeOperator unaryExpression)*
-  ///       | 'super' (multiplicativeOperator unaryExpression)+
-  Expression parseMultiplicativeExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isMultiplicativeOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseUnaryExpression();
-    }
-    while (_currentToken.type.isMultiplicativeOperator) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseUnaryExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a new expression. Return the new expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.NEW`.
-  ///
-  ///     newExpression ::=
-  ///         instanceCreationExpression
   InstanceCreationExpression parseNewExpression() =>
-      parseInstanceCreationExpression(getAndAdvance());
+      parseExpression2() as InstanceCreationExpression;
 
-  /// Parse a non-labeled statement. Return the non-labeled statement that was
-  /// parsed.
-  ///
-  ///     nonLabeledStatement ::=
-  ///         block
-  ///       | assertStatement
-  ///       | breakStatement
-  ///       | continueStatement
-  ///       | doStatement
-  ///       | forStatement
-  ///       | ifStatement
-  ///       | returnStatement
-  ///       | switchStatement
-  ///       | tryStatement
-  ///       | whileStatement
-  ///       | variableDeclarationList ';'
-  ///       | expressionStatement
-  ///       | functionSignature functionBody
-  Statement parseNonLabeledStatement() {
-    // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.OPEN_CURLY_BRACKET) {
-      if (_tokenMatches(_peek(), TokenType.STRING)) {
-        Token afterString = skipStringLiteral(_currentToken.next);
-        if (afterString != null && afterString.type == TokenType.COLON) {
-          return astFactory.expressionStatement(
-              parseExpression2(), _expect(TokenType.SEMICOLON));
-        }
-      }
-      return parseBlock();
-    } else if (type.isKeyword && !_currentToken.keyword.isBuiltInOrPseudo) {
-      Keyword keyword = _currentToken.keyword;
-      // TODO(jwren) compute some metrics to figure out a better order for this
-      // if-then sequence to optimize performance
-      if (keyword == Keyword.ASSERT) {
-        return parseAssertStatement();
-      } else if (keyword == Keyword.BREAK) {
-        return parseBreakStatement();
-      } else if (keyword == Keyword.CONTINUE) {
-        return parseContinueStatement();
-      } else if (keyword == Keyword.DO) {
-        return parseDoStatement();
-      } else if (keyword == Keyword.FOR) {
-        return parseForStatement();
-      } else if (keyword == Keyword.IF) {
-        return parseIfStatement();
-      } else if (keyword == Keyword.RETHROW) {
-        return astFactory.expressionStatement(
-            parseRethrowExpression(), _expect(TokenType.SEMICOLON));
-      } else if (keyword == Keyword.RETURN) {
-        return parseReturnStatement();
-      } else if (keyword == Keyword.SWITCH) {
-        return parseSwitchStatement();
-      } else if (keyword == Keyword.THROW) {
-        return astFactory.expressionStatement(
-            parseThrowExpression(), _expect(TokenType.SEMICOLON));
-      } else if (keyword == Keyword.TRY) {
-        return parseTryStatement();
-      } else if (keyword == Keyword.WHILE) {
-        return parseWhileStatement();
-      } else if (keyword == Keyword.VAR || keyword == Keyword.FINAL) {
-        return parseVariableDeclarationStatementAfterMetadata(
-            commentAndMetadata);
-      } else if (keyword == Keyword.VOID) {
-        TypeAnnotation returnType;
-        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
-          returnType = parseTypeAnnotation(false);
-        } else {
-          returnType = astFactory.typeName(
-              astFactory.simpleIdentifier(getAndAdvance()), null);
-        }
-        Token next = _currentToken.next;
-        if (_matchesIdentifier() &&
-            next.matchesAny(const <TokenType>[
-              TokenType.OPEN_PAREN,
-              TokenType.OPEN_CURLY_BRACKET,
-              TokenType.FUNCTION,
-              TokenType.LT
-            ])) {
-          return _parseFunctionDeclarationStatementAfterReturnType(
-              commentAndMetadata, returnType);
-        } else if (_matchesIdentifier() &&
-            next.matchesAny(const <TokenType>[
-              TokenType.EQ,
-              TokenType.COMMA,
-              TokenType.SEMICOLON
-            ])) {
-          return _parseVariableDeclarationStatementAfterType(
-              commentAndMetadata, null, returnType);
-        } else {
-          //
-          // We have found an error of some kind. Try to recover.
-          //
-          if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-            //
-            // We appear to have found an incomplete statement at the end of a
-            // block. Parse it as a variable declaration.
-            //
-            return _parseVariableDeclarationStatementAfterType(
-                commentAndMetadata, null, returnType);
-          }
-          _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-          // TODO(brianwilkerson) Recover from this error.
-          return astFactory
-              .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-        }
-      } else if (keyword == Keyword.CONST) {
-        Token next = _currentToken.next;
-        if (next.matchesAny(const <TokenType>[
-          TokenType.LT,
-          TokenType.OPEN_CURLY_BRACKET,
-          TokenType.OPEN_SQUARE_BRACKET,
-          TokenType.INDEX
-        ])) {
-          return astFactory.expressionStatement(
-              parseExpression2(), _expect(TokenType.SEMICOLON));
-        } else if (_tokenMatches(next, TokenType.IDENTIFIER)) {
-          Token afterType = skipTypeName(next);
-          if (afterType != null) {
-            if (_tokenMatches(afterType, TokenType.OPEN_PAREN) ||
-                (_tokenMatches(afterType, TokenType.PERIOD) &&
-                    _tokenMatches(afterType.next, TokenType.IDENTIFIER) &&
-                    _tokenMatches(afterType.next.next, TokenType.OPEN_PAREN))) {
-              return astFactory.expressionStatement(
-                  parseExpression2(), _expect(TokenType.SEMICOLON));
-            }
-          }
-        }
-        return parseVariableDeclarationStatementAfterMetadata(
-            commentAndMetadata);
-      } else if (keyword == Keyword.NEW ||
-          keyword == Keyword.TRUE ||
-          keyword == Keyword.FALSE ||
-          keyword == Keyword.NULL ||
-          keyword == Keyword.SUPER ||
-          keyword == Keyword.THIS) {
-        return astFactory.expressionStatement(
-            parseExpression2(), _expect(TokenType.SEMICOLON));
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-        return astFactory
-            .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-      }
-    } else if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      TypeAnnotation returnType = parseTypeAnnotation(false);
-      Token next = _currentToken.next;
-      if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.OPEN_PAREN,
-            TokenType.OPEN_CURLY_BRACKET,
-            TokenType.FUNCTION,
-            TokenType.LT
-          ])) {
-        return _parseFunctionDeclarationStatementAfterReturnType(
-            commentAndMetadata, returnType);
-      } else if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.EQ,
-            TokenType.COMMA,
-            TokenType.SEMICOLON
-          ])) {
-        return _parseVariableDeclarationStatementAfterType(
-            commentAndMetadata, null, returnType);
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-          //
-          // We appear to have found an incomplete statement at the end of a
-          // block. Parse it as a variable declaration.
-          //
-          return _parseVariableDeclarationStatementAfterType(
-              commentAndMetadata, null, returnType);
-        }
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-        // TODO(brianwilkerson) Recover from this error.
-        return astFactory
-            .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-      }
-    } else if (_inGenerator && _matchesKeyword(Keyword.YIELD)) {
-      return parseYieldStatement();
-    } else if (_inAsync && _matchesKeyword(Keyword.AWAIT)) {
-      if (_tokenMatchesKeyword(_peek(), Keyword.FOR)) {
-        return parseForStatement();
-      }
-      return astFactory.expressionStatement(
-          parseExpression2(), _expect(TokenType.SEMICOLON));
-    } else if (_matchesKeyword(Keyword.AWAIT) &&
-        _tokenMatchesKeyword(_peek(), Keyword.FOR)) {
-      Token awaitToken = _currentToken;
-      Statement statement = parseForStatement();
-      if (!(statement is ForStatement && statement.forLoopParts is ForParts)) {
-        _reportErrorForToken(
-            CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, awaitToken);
-      }
-      return statement;
-    } else if (type == TokenType.SEMICOLON) {
-      return parseEmptyStatement();
-    } else if (isInitializedVariableDeclaration()) {
-      return parseVariableDeclarationStatementAfterMetadata(commentAndMetadata);
-    } else if (isFunctionDeclaration()) {
-      return parseFunctionDeclarationStatement();
-    } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-      return astFactory
-          .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-    } else {
-      return astFactory.expressionStatement(
-          parseExpression2(), _expect(TokenType.SEMICOLON));
-    }
-  }
+  Expression parsePostfixExpression() => parseExpression2();
 
-  /// Parse a normal formal parameter. Return the normal formal parameter that
-  /// was parsed.
-  ///
-  ///     normalFormalParameter ::=
-  ///         functionSignature
-  ///       | fieldFormalParameter
-  ///       | simpleFormalParameter
-  ///
-  ///     functionSignature:
-  ///         metadata returnType? identifier typeParameters? formalParameterList
-  ///
-  ///     fieldFormalParameter ::=
-  ///         metadata finalConstVarOrType? 'this' '.' identifier
-  ///
-  ///     simpleFormalParameter ::=
-  ///         declaredIdentifier
-  ///       | metadata identifier
-  NormalFormalParameter parseNormalFormalParameter(
-      {bool inFunctionType = false}) {
-    Token covariantKeyword;
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    if (_matchesKeyword(Keyword.COVARIANT)) {
-      // Check to ensure that 'covariant' isn't being used as the parameter name.
-      Token next = _peek();
-      if (_tokenMatchesKeyword(next, Keyword.FINAL) ||
-          _tokenMatchesKeyword(next, Keyword.CONST) ||
-          _tokenMatchesKeyword(next, Keyword.VAR) ||
-          _tokenMatchesKeyword(next, Keyword.THIS) ||
-          _tokenMatchesKeyword(next, Keyword.VOID) ||
-          _tokenMatchesIdentifier(next)) {
-        covariantKeyword = getAndAdvance();
-      }
-    }
-    FinalConstVarOrType holder = parseFinalConstVarOrType(!inFunctionType,
-        inFunctionType: inFunctionType);
-    Token thisKeyword;
-    Token period;
-    if (_matchesKeyword(Keyword.THIS)) {
-      thisKeyword = getAndAdvance();
-      period = _expect(TokenType.PERIOD);
-    }
-    if (!_matchesIdentifier() && inFunctionType) {
-      return astFactory.simpleFormalParameter2(
-          comment: commentAndMetadata.comment,
-          metadata: commentAndMetadata.metadata,
-          covariantKeyword: covariantKeyword,
-          keyword: holder.keyword,
-          type: holder.type,
-          identifier: null);
-    }
-    SimpleIdentifier identifier = parseSimpleIdentifier();
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    if (_matches(TokenType.OPEN_PAREN)) {
-      FormalParameterList parameters = _parseFormalParameterListUnchecked();
-      if (thisKeyword == null) {
-        if (holder.keyword != null) {
-          _reportErrorForToken(
-              ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
-        }
-        return astFactory.functionTypedFormalParameter2(
-            comment: commentAndMetadata.comment,
-            metadata: commentAndMetadata.metadata,
-            covariantKeyword: covariantKeyword,
-            returnType: holder.type,
-            identifier: astFactory.simpleIdentifier(identifier.token,
-                isDeclaration: true),
-            typeParameters: typeParameters,
-            parameters: parameters);
-      } else {
-        return astFactory.fieldFormalParameter2(
-            comment: commentAndMetadata.comment,
-            metadata: commentAndMetadata.metadata,
-            covariantKeyword: covariantKeyword,
-            keyword: holder.keyword,
-            type: holder.type,
-            thisKeyword: thisKeyword,
-            period: period,
-            identifier: identifier,
-            typeParameters: typeParameters,
-            parameters: parameters);
-      }
-    } else if (typeParameters != null) {
-      // TODO(brianwilkerson) Report an error. It looks like a function-typed
-      // parameter with no parameter list.
-      //_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters.endToken);
-    }
-    TypeAnnotation type = holder.type;
-    if (type != null &&
-        holder.keyword != null &&
-        _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) {
-      _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword);
-    }
-    if (thisKeyword != null) {
-      // TODO(brianwilkerson) If there are type parameters but no parameters,
-      // should we create a synthetic empty parameter list here so we can
-      // capture the type parameters?
-      return astFactory.fieldFormalParameter2(
-          comment: commentAndMetadata.comment,
-          metadata: commentAndMetadata.metadata,
-          covariantKeyword: covariantKeyword,
-          keyword: holder.keyword,
-          type: type,
-          thisKeyword: thisKeyword,
-          period: period,
-          identifier: identifier);
-    }
-    return astFactory.simpleFormalParameter2(
-        comment: commentAndMetadata.comment,
-        metadata: commentAndMetadata.metadata,
-        covariantKeyword: covariantKeyword,
-        keyword: holder.keyword,
-        type: type,
-        identifier:
-            astFactory.simpleIdentifier(identifier.token, isDeclaration: true));
-  }
+  Identifier parsePrefixedIdentifier() => parseExpression2() as Identifier;
 
-  /// Parse an operator declaration. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [externalKeyword] is the 'external' token. The [returnType] is the
-  /// return type that has already been parsed, or `null` if there was no return
-  /// type. Return the operator declaration that was parsed.
-  ///
-  ///     operatorDeclaration ::=
-  ///         operatorSignature (';' | functionBody)
-  ///
-  ///     operatorSignature ::=
-  ///         'external'? returnType? 'operator' operator formalParameterList
-  MethodDeclaration parseOperator(CommentAndMetadata commentAndMetadata,
-      Token externalKeyword, TypeName returnType) {
-    Token operatorKeyword;
-    if (_matchesKeyword(Keyword.OPERATOR)) {
-      operatorKeyword = getAndAdvance();
-    } else {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken);
-      operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR);
-    }
-    return _parseOperatorAfterKeyword(
-        commentAndMetadata, externalKeyword, returnType, operatorKeyword);
-  }
-
-  /// Parse a part or part-of directive. The [commentAndMetadata] is the
-  /// metadata to be associated with the directive. Return the part or part-of
-  /// directive that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.PART`.
-  ///
-  ///     partDirective ::=
-  ///         metadata 'part' stringLiteral ';'
-  ///
-  ///     partOfDirective ::=
-  ///         metadata 'part' 'of' identifier ';'
-  Directive parsePartOrPartOfDirective(CommentAndMetadata commentAndMetadata) {
-    if (_tokenMatchesKeyword(_peek(), Keyword.OF)) {
-      return _parsePartOfDirective(commentAndMetadata);
-    }
-    return _parsePartDirective(commentAndMetadata);
-  }
-
-  /// Parse a postfix expression. Return the postfix expression that was parsed.
-  ///
-  ///     postfixExpression ::=
-  ///         assignableExpression postfixOperator
-  ///       | primary selector*
-  ///
-  ///     selector ::=
-  ///         assignableSelector
-  ///       | argumentPart
-  Expression parsePostfixExpression() {
-    Expression operand = parseAssignableExpression(true);
-    TokenType type = _currentToken.type;
-    if (type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.PERIOD ||
-        type == TokenType.QUESTION_PERIOD ||
-        type == TokenType.OPEN_PAREN ||
-        type == TokenType.LT ||
-        type == TokenType.INDEX) {
-      do {
-        if (_isLikelyArgumentList()) {
-          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-          ArgumentList argumentList = parseArgumentList();
-          Expression currentOperand = operand;
-          if (currentOperand is PropertyAccess) {
-            operand = astFactory.methodInvocation(
-                currentOperand.target,
-                currentOperand.operator,
-                currentOperand.propertyName,
-                typeArguments,
-                argumentList);
-          } else {
-            operand = astFactory.functionExpressionInvocation(
-                operand, typeArguments, argumentList);
-          }
-        } else if (enableOptionalNewAndConst &&
-            operand is Identifier &&
-            _isLikelyNamedInstanceCreation()) {
-          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-          Token period = _expect(TokenType.PERIOD);
-          SimpleIdentifier name = parseSimpleIdentifier();
-          ArgumentList argumentList = parseArgumentList();
-          TypeName typeName = astFactory.typeName(operand, typeArguments);
-          operand = astFactory.instanceCreationExpression(null,
-              astFactory.constructorName(typeName, period, name), argumentList);
-        } else {
-          operand = parseAssignableSelector(operand, true);
-        }
-        type = _currentToken.type;
-      } while (type == TokenType.OPEN_SQUARE_BRACKET ||
-          type == TokenType.PERIOD ||
-          type == TokenType.QUESTION_PERIOD ||
-          type == TokenType.OPEN_PAREN ||
-          type == TokenType.INDEX);
-      return operand;
-    }
-    if (!_currentToken.type.isIncrementOperator) {
-      return operand;
-    }
-    _ensureAssignable(operand);
-    Token operator = getAndAdvance();
-    return astFactory.postfixExpression(operand, operator);
-  }
-
-  /// Parse a prefixed identifier. Return the prefixed identifier that was
-  /// parsed.
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Identifier parsePrefixedIdentifier() {
-    return _parsePrefixedIdentifierAfterIdentifier(parseSimpleIdentifier());
-  }
-
-  /// Parse a primary expression. Return the primary expression that was parsed.
-  ///
-  ///     primary ::=
-  ///         thisExpression
-  ///       | 'super' unconditionalAssignableSelector
-  ///       | functionExpression
-  ///       | literal
-  ///       | identifier
-  ///       | newExpression
-  ///       | constObjectExpression
-  ///       | '(' expression ')'
-  ///       | argumentDefinitionTest
-  ///
-  ///     literal ::=
-  ///         nullLiteral
-  ///       | booleanLiteral
-  ///       | numericLiteral
-  ///       | stringLiteral
-  ///       | symbolLiteral
-  ///       | mapLiteral
-  ///       | listLiteral
   Expression parsePrimaryExpression() {
-    if (_matchesIdentifier()) {
-      // TODO(brianwilkerson) The code below was an attempt to recover from an
-      // error case, but it needs to be applied as a recovery only after we
-      // know that parsing it as an identifier doesn't work. Leaving the code as
-      // a reminder of how to recover.
-//      if (isFunctionExpression(_peek())) {
-//        //
-//        // Function expressions were allowed to have names at one point, but this is now illegal.
-//        //
-//        reportError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, getAndAdvance());
-//        return parseFunctionExpression();
-//      }
-      return _parsePrefixedIdentifierUnchecked();
-    }
-    TokenType type = _currentToken.type;
-    if (type == TokenType.STRING) {
-      return parseStringLiteral();
-    } else if (type == TokenType.INT) {
-      Token token = getAndAdvance();
-      int value;
-      try {
-        value = int.parse(token.lexeme);
-      } on FormatException {
-        // The invalid format should have been reported by the scanner.
-      }
-      return astFactory.integerLiteral(token, value);
-    }
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.NULL) {
-      return astFactory.nullLiteral(getAndAdvance());
-    } else if (keyword == Keyword.NEW) {
-      return parseNewExpression();
-    } else if (keyword == Keyword.THIS) {
-      return astFactory.thisExpression(getAndAdvance());
-    } else if (keyword == Keyword.SUPER) {
-      return parseAssignableSelector(
-          astFactory.superExpression(getAndAdvance()), false,
-          allowConditional: false);
-    } else if (keyword == Keyword.FALSE) {
-      return astFactory.booleanLiteral(getAndAdvance(), false);
-    } else if (keyword == Keyword.TRUE) {
-      return astFactory.booleanLiteral(getAndAdvance(), true);
-    }
-    if (type == TokenType.DOUBLE) {
-      Token token = getAndAdvance();
-      double value = 0.0;
-      try {
-        value = double.parse(token.lexeme);
-      } on FormatException {
-        // The invalid format should have been reported by the scanner.
-      }
-      return astFactory.doubleLiteral(token, value);
-    } else if (type == TokenType.HEXADECIMAL) {
-      Token token = getAndAdvance();
-      int value;
-      try {
-        value = int.parse(token.lexeme);
-      } on FormatException {
-        // The invalid format should have been reported by the scanner.
-      }
-      return astFactory.integerLiteral(token, value);
-    } else if (keyword == Keyword.CONST) {
-      return parseConstExpression();
-    } else if (type == TokenType.OPEN_PAREN) {
-      if (isFunctionExpression(_currentToken)) {
-        return parseFunctionExpression();
-      }
-      Token leftParenthesis = getAndAdvance();
-      bool wasInInitializer = _inInitializer;
-      _inInitializer = false;
-      try {
-        Expression expression = parseExpression2();
-        Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-        return astFactory.parenthesizedExpression(
-            leftParenthesis, expression, rightParenthesis);
-      } finally {
-        _inInitializer = wasInInitializer;
-      }
-    } else if (type == TokenType.LT) {
-      if (isFunctionExpression(currentToken)) {
-        return parseFunctionExpression();
-      }
-      return parseListOrMapLiteral(null);
-    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-      return parseMapLiteral(null, null);
-    } else if (type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.INDEX) {
-      return parseListLiteral(null, null);
-    } else if (type == TokenType.QUESTION &&
-        _tokenMatches(_peek(), TokenType.IDENTIFIER)) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-      _advance();
-      return parsePrimaryExpression();
-    } else if (keyword == Keyword.VOID) {
-      //
-      // Recover from having a return type of "void" where a return type is not
-      // expected.
-      //
-      // TODO(brianwilkerson) Improve this error message.
-      _reportErrorForCurrentToken(
-          ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-      _advance();
-      return parsePrimaryExpression();
-    } else if (type == TokenType.HASH) {
-      return parseSymbolLiteral();
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      return createSyntheticIdentifier();
-    }
+    currentToken = fastaParser
+        .parsePrimary(fastaParser.syntheticPreviousToken(currentToken),
+            fasta.IdentifierContext.expression)
+        .next;
+    return astBuilder.pop() as Expression;
   }
 
-  /// Parse a redirecting constructor invocation. The flag [hasPeriod] should be
-  /// `true` if the `this` is followed by a period. Return the redirecting
-  /// constructor invocation that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.THIS`.
-  ///
-  ///     redirectingConstructorInvocation ::=
-  ///         'this' ('.' identifier)? arguments
-  RedirectingConstructorInvocation parseRedirectingConstructorInvocation(
-      bool hasPeriod) {
-    Token keyword = getAndAdvance();
-    Token period;
-    SimpleIdentifier constructorName;
-    if (hasPeriod) {
-      period = getAndAdvance();
-      if (_matchesIdentifier()) {
-        constructorName = _parseSimpleIdentifierUnchecked(isDeclaration: false);
-      } else {
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-        constructorName = createSyntheticIdentifier(isDeclaration: false);
-        _advance();
-      }
-    }
-    ArgumentList argumentList = _parseArgumentListChecked();
-    return astFactory.redirectingConstructorInvocation(
-        keyword, period, constructorName, argumentList);
-  }
+  Expression parseRelationalExpression() => parseExpression2();
 
-  /// Parse a relational expression. Return the relational expression that was
-  /// parsed.
-  ///
-  ///     relationalExpression ::=
-  ///         bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bitwiseOrExpression)?
-  ///       | 'super' relationalOperator bitwiseOrExpression
-  Expression parseRelationalExpression() {
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isRelationalOperator) {
-      Expression expression = astFactory.superExpression(getAndAdvance());
-      Token operator = getAndAdvance();
-      return astFactory.binaryExpression(
-          expression, operator, parseBitwiseOrExpression());
-    }
-    Expression expression = parseBitwiseOrExpression();
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.AS) {
-      Token asOperator = getAndAdvance();
-      return astFactory.asExpression(
-          expression, asOperator, parseTypeNotVoid(true));
-    } else if (keyword == Keyword.IS) {
-      Token isOperator = getAndAdvance();
-      Token notOperator;
-      if (_matches(TokenType.BANG)) {
-        notOperator = getAndAdvance();
-      }
-      TypeAnnotation type = parseTypeNotVoid(true);
-      return astFactory.isExpression(expression, isOperator, notOperator, type);
-    } else if (_currentToken.type.isRelationalOperator) {
-      Token operator = getAndAdvance();
-      return astFactory.binaryExpression(
-          expression, operator, parseBitwiseOrExpression());
-    }
-    return expression;
-  }
+  Expression parseRethrowExpression() => parseExpression2();
 
-  /// Parse a rethrow expression. Return the rethrow expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.RETHROW`.
-  ///
-  ///     rethrowExpression ::=
-  ///         'rethrow'
-  Expression parseRethrowExpression() =>
-      astFactory.rethrowExpression(getAndAdvance());
+  Expression parseShiftExpression() => parseExpression2();
 
-  /// Parse a return statement. Return the return statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.RETURN`.
-  ///
-  ///     returnStatement ::=
-  ///         'return' expression? ';'
-  Statement parseReturnStatement() {
-    Token returnKeyword = getAndAdvance();
-    if (_matches(TokenType.SEMICOLON)) {
-      return astFactory.returnStatement(returnKeyword, null, getAndAdvance());
-    }
-    Expression expression = parseExpression2();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.returnStatement(returnKeyword, expression, semicolon);
-  }
-
-  /// Parse a setter. The [commentAndMetadata] is the documentation comment and
-  /// metadata to be associated with the declaration. The [externalKeyword] is
-  /// the 'external' token. The [staticKeyword] is the static keyword, or `null`
-  /// if the setter is not static. The [returnType] is the return type that has
-  /// already been parsed, or `null` if there was no return type. Return the
-  /// setter that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.SET`.
-  ///
-  ///     setter ::=
-  ///         setterSignature functionBody?
-  ///
-  ///     setterSignature ::=
-  ///         'external'? 'static'? returnType? 'set' identifier formalParameterList
-  MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata,
-      Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) {
-    Token propertyKeyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    FormalParameterList parameters = parseFormalParameterList();
-    _validateFormalParameterList(parameters);
-    FunctionBody body = parseFunctionBody(
-        externalKeyword != null || staticKeyword == null,
-        ParserErrorCode.STATIC_SETTER_WITHOUT_BODY,
-        false);
-    if (externalKeyword != null && body is! EmptyFunctionBody) {
-      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY);
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        propertyKeyword,
-        null,
-        name,
-        null,
-        parameters,
-        body);
-  }
-
-  /// Parse a shift expression. Return the shift expression that was parsed.
-  ///
-  ///     shiftExpression ::=
-  ///         additiveExpression (shiftOperator additiveExpression)*
-  ///       | 'super' (shiftOperator additiveExpression)+
-  Expression parseShiftExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isShiftOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseAdditiveExpression();
-    }
-    while (_currentToken.type.isShiftOperator) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseAdditiveExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a simple identifier. Return the simple identifier that was parsed.
-  ///
-  ///     identifier ::=
-  ///         IDENTIFIER
   SimpleIdentifier parseSimpleIdentifier(
-      {bool allowKeyword = false, bool isDeclaration = false}) {
-    if (_matchesIdentifier() ||
-        (allowKeyword && _tokenMatchesIdentifierOrKeyword(_currentToken))) {
-      return _parseSimpleIdentifierUnchecked(isDeclaration: isDeclaration);
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-    return createSyntheticIdentifier(isDeclaration: isDeclaration);
-  }
+          {bool allowKeyword = false, bool isDeclaration = false}) =>
+      parseExpression2() as SimpleIdentifier;
 
-  /// Parse a statement, starting with the given [token]. Return the statement
-  /// that was parsed, or `null` if the tokens do not represent a recognizable
-  /// statement.
   Statement parseStatement(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseStatement2();
   }
 
-  /// Parse a statement. Return the statement that was parsed.
-  ///
-  ///     statement ::=
-  ///         label* nonLabeledStatement
   Statement parseStatement2() {
-    if (_treeDepth > _MAX_TREE_DEPTH) {
-      throw _TooDeepTreeError();
-    }
-    _treeDepth++;
-    try {
-      List<Label> labels;
-      while (
-          _matchesIdentifier() && _currentToken.next.type == TokenType.COLON) {
-        Label label = parseLabel(isDeclaration: true);
-        if (labels == null) {
-          labels = <Label>[label];
-        } else {
-          labels.add(label);
-        }
-      }
-      Statement statement = parseNonLabeledStatement();
-      if (labels == null) {
-        return statement;
-      }
-      return astFactory.labeledStatement(labels, statement);
-    } finally {
-      _treeDepth--;
-    }
+    currentToken = fastaParser
+        .parseStatement(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as Statement;
   }
 
-  /// Parse a sequence of statements, starting with the given [token]. Return
-  /// the statements that were parsed, or `null` if the tokens do not represent
-  /// a recognizable sequence of statements.
-  List<Statement> parseStatements(Token token) {
-    _currentToken = token;
-    return _parseStatementList();
+  StringLiteral parseStringLiteral() => parseExpression2() as StringLiteral;
+
+  SymbolLiteral parseSymbolLiteral() => parseExpression2() as SymbolLiteral;
+
+  Expression parseThrowExpression() => parseExpression2();
+
+  Expression parseThrowExpressionWithoutCascade() => parseExpression2();
+
+  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
+    currentToken = fastaParser.parseTopLevelDeclaration(currentToken);
+    return (isDirective ? astBuilder.directives : astBuilder.declarations)
+        .removeLast();
   }
 
-  /// Parse a string literal. Return the string literal that was parsed.
-  ///
-  ///     stringLiteral ::=
-  ///         MULTI_LINE_STRING+
-  ///       | SINGLE_LINE_STRING+
-  StringLiteral parseStringLiteral() {
-    if (_matches(TokenType.STRING)) {
-      return _parseStringLiteralUnchecked();
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL);
-    return createSyntheticStringLiteral();
-  }
-
-  /// Parse a super constructor invocation. Return the super constructor
-  /// invocation that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.SUPER].
-  ///
-  ///     superConstructorInvocation ::=
-  ///         'super' ('.' identifier)? arguments
-  SuperConstructorInvocation parseSuperConstructorInvocation() {
-    Token keyword = getAndAdvance();
-    Token period;
-    SimpleIdentifier constructorName;
-    if (_matches(TokenType.PERIOD)) {
-      period = getAndAdvance();
-      constructorName = parseSimpleIdentifier();
-    }
-    ArgumentList argumentList = _parseArgumentListChecked();
-    return astFactory.superConstructorInvocation(
-        keyword, period, constructorName, argumentList);
-  }
-
-  /// Parse a switch statement. Return the switch statement that was parsed.
-  ///
-  ///     switchStatement ::=
-  ///         'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
-  ///
-  ///     switchCase ::=
-  ///         label* ('case' expression ':') statements
-  ///
-  ///     defaultCase ::=
-  ///         label* 'default' ':' statements
-  SwitchStatement parseSwitchStatement() {
-    bool wasInSwitch = _inSwitch;
-    _inSwitch = true;
-    try {
-      HashSet<String> definedLabels = HashSet<String>();
-      Token keyword = _expectKeyword(Keyword.SWITCH);
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      Expression expression = parseExpression2();
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
-      Token defaultKeyword;
-      List<SwitchMember> members = <SwitchMember>[];
-      TokenType type = _currentToken.type;
-      while (type != TokenType.EOF && type != TokenType.CLOSE_CURLY_BRACKET) {
-        List<Label> labels = <Label>[];
-        while (
-            _matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
-          SimpleIdentifier identifier =
-              _parseSimpleIdentifierUnchecked(isDeclaration: true);
-          String label = identifier.token.lexeme;
-          if (definedLabels.contains(label)) {
-            _reportErrorForToken(
-                ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
-                identifier.token,
-                [label]);
-          } else {
-            definedLabels.add(label);
-          }
-          Token colon = getAndAdvance();
-          labels.add(astFactory.label(identifier, colon));
-        }
-        Keyword keyword = _currentToken.keyword;
-        if (keyword == Keyword.CASE) {
-          Token caseKeyword = getAndAdvance();
-          Expression caseExpression = parseExpression2();
-          Token colon = _expect(TokenType.COLON);
-          members.add(astFactory.switchCase(labels, caseKeyword, caseExpression,
-              colon, _parseStatementList()));
-          if (defaultKeyword != null) {
-            _reportErrorForToken(
-                ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
-                caseKeyword);
-          }
-        } else if (keyword == Keyword.DEFAULT) {
-          if (defaultKeyword != null) {
-            _reportErrorForToken(
-                ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, _peek());
-          }
-          defaultKeyword = getAndAdvance();
-          Token colon = _expect(TokenType.COLON);
-          members.add(astFactory.switchDefault(
-              labels, defaultKeyword, colon, _parseStatementList()));
-        } else {
-          // We need to advance, otherwise we could end up in an infinite loop,
-          // but this could be a lot smarter about recovering from the error.
-          _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT);
-          bool atEndOrNextMember() {
-            TokenType type = _currentToken.type;
-            if (type == TokenType.EOF ||
-                type == TokenType.CLOSE_CURLY_BRACKET) {
-              return true;
-            }
-            Keyword keyword = _currentToken.keyword;
-            return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
-          }
-
-          while (!atEndOrNextMember()) {
-            _advance();
-          }
-        }
-        type = _currentToken.type;
-      }
-      Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-      return astFactory.switchStatement(keyword, leftParenthesis, expression,
-          rightParenthesis, leftBracket, members, rightBracket);
-    } finally {
-      _inSwitch = wasInSwitch;
-    }
-  }
-
-  /// Parse a symbol literal. Return the symbol literal that was parsed.
-  ///
-  /// This method assumes that the current token matches [TokenType.HASH].
-  ///
-  ///     symbolLiteral ::=
-  ///         '#' identifier ('.' identifier)*
-  SymbolLiteral parseSymbolLiteral() {
-    Token poundSign = getAndAdvance();
-    List<Token> components = <Token>[];
-    if (_matchesIdentifier()) {
-      components.add(getAndAdvance());
-      while (_optional(TokenType.PERIOD)) {
-        if (_matchesIdentifier()) {
-          components.add(getAndAdvance());
-        } else {
-          _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-          components.add(_createSyntheticToken(TokenType.IDENTIFIER));
-          break;
-        }
-      }
-    } else if (_currentToken.isOperator) {
-      components.add(getAndAdvance());
-    } else if (_matchesKeyword(Keyword.VOID)) {
-      components.add(getAndAdvance());
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      components.add(_createSyntheticToken(TokenType.IDENTIFIER));
-    }
-    return astFactory.symbolLiteral(poundSign, components);
-  }
-
-  /// Parse a throw expression. Return the throw expression that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.THROW].
-  ///
-  ///     throwExpression ::=
-  ///         'throw' expression
-  Expression parseThrowExpression() {
-    Token keyword = getAndAdvance();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.SEMICOLON || type == TokenType.CLOSE_PAREN) {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
-      return astFactory.throwExpression(keyword, createSyntheticIdentifier());
-    }
-    Expression expression = parseExpression2();
-    return astFactory.throwExpression(keyword, expression);
-  }
-
-  /// Parse a throw expression. Return the throw expression that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.THROW].
-  ///
-  ///     throwExpressionWithoutCascade ::=
-  ///         'throw' expressionWithoutCascade
-  Expression parseThrowExpressionWithoutCascade() {
-    Token keyword = getAndAdvance();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.SEMICOLON || type == TokenType.CLOSE_PAREN) {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
-      return astFactory.throwExpression(keyword, createSyntheticIdentifier());
-    }
-    Expression expression = parseExpressionWithoutCascade();
-    return astFactory.throwExpression(keyword, expression);
-  }
-
-  /// Parse a try statement. Return the try statement that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.TRY].
-  ///
-  ///     tryStatement ::=
-  ///         'try' block (onPart+ finallyPart? | finallyPart)
-  ///
-  ///     onPart ::=
-  ///         catchPart block
-  ///       | 'on' type catchPart? block
-  ///
-  ///     catchPart ::=
-  ///         'catch' '(' identifier (',' identifier)? ')'
-  ///
-  ///     finallyPart ::=
-  ///         'finally' block
-  Statement parseTryStatement() {
-    Token tryKeyword = getAndAdvance();
-    Block body = _parseBlockChecked();
-    List<CatchClause> catchClauses = <CatchClause>[];
-    Block finallyClause;
-    while (_matchesKeyword(Keyword.ON) || _matchesKeyword(Keyword.CATCH)) {
-      Token onKeyword;
-      TypeName exceptionType;
-      if (_matchesKeyword(Keyword.ON)) {
-        onKeyword = getAndAdvance();
-        exceptionType = parseTypeNotVoid(false);
-      }
-      Token catchKeyword;
-      Token leftParenthesis;
-      SimpleIdentifier exceptionParameter;
-      Token comma;
-      SimpleIdentifier stackTraceParameter;
-      Token rightParenthesis;
-      if (_matchesKeyword(Keyword.CATCH)) {
-        catchKeyword = getAndAdvance();
-        leftParenthesis = _expect(TokenType.OPEN_PAREN);
-        exceptionParameter = parseSimpleIdentifier(isDeclaration: true);
-        if (_matches(TokenType.COMMA)) {
-          comma = getAndAdvance();
-          stackTraceParameter = parseSimpleIdentifier(isDeclaration: true);
-        }
-        rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      }
-      Block catchBody = _parseBlockChecked();
-      catchClauses.add(astFactory.catchClause(
-          onKeyword,
-          exceptionType,
-          catchKeyword,
-          leftParenthesis,
-          exceptionParameter,
-          comma,
-          stackTraceParameter,
-          rightParenthesis,
-          catchBody));
-    }
-    Token finallyKeyword;
-    if (_matchesKeyword(Keyword.FINALLY)) {
-      finallyKeyword = getAndAdvance();
-      finallyClause = _parseBlockChecked();
-    } else if (catchClauses.isEmpty) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY);
-    }
-    return astFactory.tryStatement(
-        tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
-  }
-
-  /// Parse a type alias. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. Return the type alias that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.TYPEDEF].
-  ///
-  ///     typeAlias ::=
-  ///         'typedef' typeAliasBody
-  ///       | genericTypeAlias
-  ///
-  ///     typeAliasBody ::=
-  ///         functionTypeAlias
-  ///
-  ///     functionTypeAlias ::=
-  ///         functionPrefix typeParameterList? formalParameterList ';'
-  ///
-  ///     functionPrefix ::=
-  ///         returnType? name
-  TypeAlias parseTypeAlias(CommentAndMetadata commentAndMetadata) {
-    Token keyword = getAndAdvance();
-    if (_matchesIdentifier()) {
-      Token next = _peek();
-      if (_tokenMatches(next, TokenType.LT)) {
-        next = _skipTypeParameterList(next);
-        if (next != null && _tokenMatches(next, TokenType.EQ)) {
-          TypeAlias typeAlias =
-              parseGenericTypeAlias(commentAndMetadata, keyword);
-          return typeAlias;
-        }
-      } else if (_tokenMatches(next, TokenType.EQ)) {
-        TypeAlias typeAlias =
-            parseGenericTypeAlias(commentAndMetadata, keyword);
-        return typeAlias;
-      }
-    }
-    return _parseFunctionTypeAlias(commentAndMetadata, keyword);
-  }
-
-  /// Parse a type.
-  ///
-  ///     type ::=
-  ///         typeWithoutFunction
-  ///       | functionType
   TypeAnnotation parseTypeAnnotation(bool inExpression) {
-    TypeAnnotation type;
-    if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      // Generic function type with no return type.
-      type = parseGenericFunctionTypeAfterReturnType(null);
-    } else {
-      type = parseTypeWithoutFunction(inExpression);
-    }
-    while (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      type = parseGenericFunctionTypeAfterReturnType(type);
-    }
-    return type;
+    Token previous = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeType(previous, true, !inExpression)
+        .parseType(previous, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeAnnotation;
   }
 
-  /// Parse a list of type arguments. Return the type argument list that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.LT`.
-  ///
-  ///     typeArguments ::=
-  ///         '<' typeList '>'
-  ///
-  ///     typeList ::=
-  ///         type (',' type)*
   TypeArgumentList parseTypeArgumentList() {
-    Token leftBracket = getAndAdvance();
-    List<TypeAnnotation> arguments = <TypeAnnotation>[
-      parseTypeAnnotation(false)
-    ];
-    while (_optional(TokenType.COMMA)) {
-      arguments.add(parseTypeAnnotation(false));
-    }
-    Token rightBracket = _expectGt();
-    return astFactory.typeArgumentList(leftBracket, arguments, rightBracket);
+    Token previous = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeTypeParamOrArg(previous)
+        .parseArguments(previous, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeArgumentList;
   }
 
-  /// Parse a type which is not void and is not a function type. Return the type
-  /// that was parsed.
-  ///
-  ///     typeNotVoidWithoutFunction ::=
-  ///         qualified typeArguments?
-  // TODO(eernst): Rename this to `parseTypeNotVoidWithoutFunction`?
-  // Apparently,  it was named `parseTypeName` before type arguments existed.
   TypeName parseTypeName(bool inExpression) {
-    return _parseTypeName(inExpression);
+    Token previous = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeType(previous, true, !inExpression)
+        .parseType(previous, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeName;
   }
 
-  /// Parse a type which is not `void`.
-  ///
-  ///     typeNotVoid ::=
-  ///         functionType
-  ///       | typeNotVoidWithoutFunction
-  TypeAnnotation parseTypeNotVoid(bool inExpression) {
-    TypeAnnotation type;
-    if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      // Generic function type with no return type.
-      type = parseGenericFunctionTypeAfterReturnType(null);
-    } else if (_currentToken.keyword == Keyword.VOID &&
-        _atGenericFunctionTypeAfterReturnType(_currentToken.next)) {
-      type = astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
-    } else {
-      type = parseTypeName(inExpression);
-    }
-    while (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      type = parseGenericFunctionTypeAfterReturnType(type);
-    }
-    return type;
-  }
-
-  /// Parse a type parameter. Return the type parameter that was parsed.
-  ///
-  ///     typeParameter ::=
-  ///         metadata name ('extends' bound)?
   TypeParameter parseTypeParameter() {
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    if (_matchesKeyword(Keyword.EXTENDS)) {
-      Token keyword = getAndAdvance();
-      TypeAnnotation bound = parseTypeNotVoid(false);
-      return astFactory.typeParameter(commentAndMetadata.comment,
-          commentAndMetadata.metadata, name, keyword, bound);
-    }
-    return astFactory.typeParameter(commentAndMetadata.comment,
-        commentAndMetadata.metadata, name, null, null);
+    currentToken = SyntheticBeginToken(TokenType.LT, 0)
+      ..endGroup = SyntheticToken(TokenType.GT, 0)
+      ..setNext(currentToken);
+    appendToken(currentToken, currentToken.endGroup);
+    TypeParameterList typeParams = parseTypeParameterList();
+    return typeParams.typeParameters[0];
   }
 
-  /// Parse a list of type parameters. Return the list of type parameters that
-  /// were parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.LT`.
-  ///
-  ///     typeParameterList ::=
-  ///         '<' typeParameter (',' typeParameter)* '>'
   TypeParameterList parseTypeParameterList() {
-    Token leftBracket = getAndAdvance();
-    List<TypeParameter> typeParameters = <TypeParameter>[parseTypeParameter()];
-    while (_optional(TokenType.COMMA)) {
-      typeParameters.add(parseTypeParameter());
-    }
-    Token rightBracket = _expectGt();
-    return astFactory.typeParameterList(
-        leftBracket, typeParameters, rightBracket);
+    Token token = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeTypeParamOrArg(token, true)
+        .parseVariables(token, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeParameterList;
   }
 
-  /// Parse a type which is not a function type.
-  ///
-  ///     typeWithoutFunction ::=
-  ///         `void`
-  ///       | typeNotVoidWithoutFunction
-  TypeAnnotation parseTypeWithoutFunction(bool inExpression) {
-    if (_currentToken.keyword == Keyword.VOID) {
-      return astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
-    } else {
-      return parseTypeName(inExpression);
-    }
-  }
-
-  /// Parse a unary expression. Return the unary expression that was parsed.
-  ///
-  ///     unaryExpression ::=
-  ///         prefixOperator unaryExpression
-  ///       | awaitExpression
-  ///       | postfixExpression
-  ///       | unaryOperator 'super'
-  ///       | '-' 'super'
-  ///       | incrementOperator assignableExpression
-  Expression parseUnaryExpression() {
-    TokenType type = _currentToken.type;
-    if (type == TokenType.MINUS ||
-        type == TokenType.BANG ||
-        type == TokenType.TILDE) {
-      Token operator = getAndAdvance();
-      if (_matchesKeyword(Keyword.SUPER)) {
-        TokenType nextType = _peek().type;
-        if (nextType == TokenType.OPEN_SQUARE_BRACKET ||
-            nextType == TokenType.PERIOD) {
-          //     "prefixOperator unaryExpression"
-          // --> "prefixOperator postfixExpression"
-          // --> "prefixOperator primary                    selector*"
-          // --> "prefixOperator 'super' assignableSelector selector*"
-          return astFactory.prefixExpression(operator, parseUnaryExpression());
-        }
-        return astFactory.prefixExpression(
-            operator, astFactory.superExpression(getAndAdvance()));
-      }
-      return astFactory.prefixExpression(operator, parseUnaryExpression());
-    } else if (_currentToken.type.isIncrementOperator) {
-      Token operator = getAndAdvance();
-      if (_matchesKeyword(Keyword.SUPER)) {
-        TokenType nextType = _peek().type;
-        if (nextType == TokenType.OPEN_SQUARE_BRACKET ||
-            nextType == TokenType.PERIOD) {
-          // --> "prefixOperator 'super' assignableSelector selector*"
-          return astFactory.prefixExpression(operator, parseUnaryExpression());
-        }
-        //
-        // Even though it is not valid to use an incrementing operator
-        // ('++' or '--') before 'super', we can (and therefore must) interpret
-        // "--super" as semantically equivalent to "-(-super)". Unfortunately,
-        // we cannot do the same for "++super" because "+super" is also not
-        // valid.
-        //
-        if (type == TokenType.MINUS_MINUS) {
-          Token firstOperator = _createToken(operator, TokenType.MINUS);
-          Token secondOperator = Token(TokenType.MINUS, operator.offset + 1);
-          secondOperator.setNext(_currentToken);
-          firstOperator.setNext(secondOperator);
-          operator.previous.setNext(firstOperator);
-          return astFactory.prefixExpression(
-              firstOperator,
-              astFactory.prefixExpression(
-                  secondOperator, astFactory.superExpression(getAndAdvance())));
-        }
-        // Invalid operator before 'super'
-        _reportErrorForCurrentToken(
-            ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lexeme]);
-        return astFactory.prefixExpression(
-            operator, astFactory.superExpression(getAndAdvance()));
-      }
-      return astFactory.prefixExpression(
-          operator, parseAssignableExpression(false));
-    } else if (type == TokenType.PLUS) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      return createSyntheticIdentifier();
-    } else if (_inAsync && _matchesKeyword(Keyword.AWAIT)) {
-      return parseAwaitExpression();
-    }
-    return parsePostfixExpression();
-  }
-
-  /// Parse a variable declaration. Return the variable declaration that was
-  /// parsed.
-  ///
-  ///     variableDeclaration ::=
-  ///         identifier ('=' expression)?
-  VariableDeclaration parseVariableDeclaration() {
-    // TODO(paulberry): prior to the fix for bug 23204, we permitted
-    // annotations before variable declarations (e.g. "String @deprecated s;").
-    // Although such constructions are prohibited by the spec, we may want to
-    // consider handling them anyway to allow for better parser recovery in the
-    // event that the user erroneously tries to use them.  However, as a
-    // counterargument, this would likely degrade parser recovery in the event
-    // of a construct like "class C { int @deprecated foo() {} }" (i.e. the
-    // user is in the middle of inserting "int bar;" prior to
-    // "@deprecated foo() {}").
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    Token equals;
-    Expression initializer;
-    if (_matches(TokenType.EQ)) {
-      equals = getAndAdvance();
-      initializer = parseExpression2();
-    }
-    return astFactory.variableDeclaration(name, equals, initializer);
-  }
-
-  /// Parse a variable declaration list. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration list. Return the
-  /// variable declaration list that was parsed.
-  ///
-  ///     variableDeclarationList ::=
-  ///         finalConstVarOrType variableDeclaration (',' variableDeclaration)*
-  VariableDeclarationList parseVariableDeclarationListAfterMetadata(
-      CommentAndMetadata commentAndMetadata) {
-    FinalConstVarOrType holder = parseFinalConstVarOrType(false);
-    return parseVariableDeclarationListAfterType(
-        commentAndMetadata, holder.keyword, holder.type);
-  }
-
-  /// Parse a variable declaration list. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration list, or `null`
-  /// if there is no attempt at parsing the comment and metadata. The [keyword]
-  /// is the token representing the 'final', 'const' or 'var' keyword, or
-  /// `null` if there is no keyword. The [type] is the type of the variables in
-  /// the list. Return the variable declaration list that was parsed.
-  ///
-  ///     variableDeclarationList ::=
-  ///         finalConstVarOrType variableDeclaration (',' variableDeclaration)*
-  VariableDeclarationList parseVariableDeclarationListAfterType(
-      CommentAndMetadata commentAndMetadata,
-      Token keyword,
-      TypeAnnotation type) {
-    if (type != null &&
-        keyword != null &&
-        _tokenMatchesKeyword(keyword, Keyword.VAR)) {
-      _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword);
-    }
-    List<VariableDeclaration> variables = <VariableDeclaration>[
-      parseVariableDeclaration()
-    ];
-    while (_optional(TokenType.COMMA)) {
-      variables.add(parseVariableDeclaration());
-    }
-    return astFactory.variableDeclarationList(commentAndMetadata?.comment,
-        commentAndMetadata?.metadata, keyword, type, variables);
-  }
-
-  /// Parse a variable declaration statement. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration statement, or
-  /// `null` if there is no attempt at parsing the comment and metadata. Return
-  /// the variable declaration statement that was parsed.
-  ///
-  ///     variableDeclarationStatement ::=
-  ///         variableDeclarationList ';'
-  VariableDeclarationStatement parseVariableDeclarationStatementAfterMetadata(
-      CommentAndMetadata commentAndMetadata) {
-    //    Token startToken = currentToken;
-    VariableDeclarationList variableList =
-        parseVariableDeclarationListAfterMetadata(commentAndMetadata);
-//        if (!matches(TokenType.SEMICOLON)) {
-//          if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken.getNext())) {
-//            // TODO(brianwilkerson) This appears to be of the form "var type variable". We should do
-//            // a better job of recovering in this case.
-//          }
-//        }
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.variableDeclarationStatement(variableList, semicolon);
-  }
-
-  /// Parse a while statement. Return the while statement that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.WHILE].
-  ///
-  ///     whileStatement ::=
-  ///         'while' '(' expression ')' statement
-  Statement parseWhileStatement() {
-    bool wasInLoop = _inLoop;
-    _inLoop = true;
-    try {
-      Token keyword = getAndAdvance();
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      Expression condition = parseExpression2();
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Statement body = parseStatement2();
-      return astFactory.whileStatement(
-          keyword, leftParenthesis, condition, rightParenthesis, body);
-    } finally {
-      _inLoop = wasInLoop;
-    }
-  }
-
-  /// Parse a with clause. Return the with clause that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.WITH`.
-  ///
-  ///     withClause ::=
-  ///         'with' typeName (',' typeName)*
-  WithClause parseWithClause() {
-    Token withKeyword = getAndAdvance();
-    List<TypeName> types = <TypeName>[];
-    do {
-      TypeName typeName = parseTypeName(false);
-      types.add(typeName);
-    } while (_optional(TokenType.COMMA));
-    return astFactory.withClause(withKeyword, types);
-  }
-
-  /// Parse a yield statement. Return the yield statement that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.YIELD].
-  ///
-  ///     yieldStatement ::=
-  ///         'yield' '*'? expression ';'
-  YieldStatement parseYieldStatement() {
-    Token yieldToken = getAndAdvance();
-    Token star;
-    if (_matches(TokenType.STAR)) {
-      star = getAndAdvance();
-    }
-    Expression expression = parseExpression2();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.yieldStatement(yieldToken, star, expression, semicolon);
-  }
-
-  /// Parse a formal parameter list, starting at the [startToken], without
-  /// actually creating a formal parameter list or changing the current token.
-  /// Return the token following the parameter list that was parsed, or `null`
-  /// if the given token is not the first token in a valid parameter list.
-  ///
-  /// This method must be kept in sync with [parseFormalParameterList].
-  Token skipFormalParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
-      return null;
-    }
-    return (startToken as BeginToken).endToken?.next;
-  }
-
-  /// Parse the portion of a generic function type after the return type,
-  /// starting at the [startToken], without actually creating a generic function
-  /// type or changing the current token. Return the token following the generic
-  /// function type that was parsed, or `null` if the given token is not the
-  /// first token in a valid generic function type.
-  ///
-  /// This method must be kept in sync with
-  /// [parseGenericFunctionTypeAfterReturnType].
-  Token skipGenericFunctionTypeAfterReturnType(Token startToken) {
-    Token next = startToken.next; // Skip 'Function'
-    if (_tokenMatches(next, TokenType.LT)) {
-      next = skipTypeParameterList(next);
-      if (next == null) {
-        return null;
-      }
-    }
-    return skipFormalParameterList(next);
-  }
-
-  /// Parse a prefixed identifier, starting at the [startToken], without
-  /// actually creating a prefixed identifier or changing the current token.
-  /// Return the token following the prefixed identifier that was parsed, or
-  /// `null` if the given token is not the first token in a valid prefixed
-  /// identifier.
-  ///
-  /// This method must be kept in sync with [parsePrefixedIdentifier].
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Token skipPrefixedIdentifier(Token startToken) {
-    Token token = skipSimpleIdentifier(startToken);
-    if (token == null) {
-      return null;
-    } else if (!_tokenMatches(token, TokenType.PERIOD)) {
-      return token;
-    }
-    token = token.next;
-    Token nextToken = skipSimpleIdentifier(token);
-    if (nextToken != null) {
-      return nextToken;
-    } else if (_tokenMatches(token, TokenType.CLOSE_PAREN) ||
-        _tokenMatches(token, TokenType.COMMA)) {
-      // If the `id.` is followed by something that cannot produce a valid
-      // structure then assume this is a prefixed identifier but missing the
-      // trailing identifier
-      return token;
-    }
-    return null;
-  }
-
-  /// Parse a simple identifier, starting at the [startToken], without actually
-  /// creating a simple identifier or changing the current token. Return the
-  /// token following the simple identifier that was parsed, or `null` if the
-  /// given token is not the first token in a valid simple identifier.
-  ///
-  /// This method must be kept in sync with [parseSimpleIdentifier].
-  ///
-  ///     identifier ::=
-  ///         IDENTIFIER
-  Token skipSimpleIdentifier(Token startToken) {
-    if (_tokenMatches(startToken, TokenType.IDENTIFIER) ||
-        _tokenMatchesPseudoKeyword(startToken)) {
-      return startToken.next;
-    }
-    return null;
-  }
-
-  /// Parse a string literal, starting at the [startToken], without actually
-  /// creating a string literal or changing the current token. Return the token
-  /// following the string literal that was parsed, or `null` if the given token
-  /// is not the first token in a valid string literal.
-  ///
-  /// This method must be kept in sync with [parseStringLiteral].
-  ///
-  ///     stringLiteral ::=
-  ///         MULTI_LINE_STRING+
-  ///       | SINGLE_LINE_STRING+
-  Token skipStringLiteral(Token startToken) {
-    Token token = startToken;
-    while (token != null && _tokenMatches(token, TokenType.STRING)) {
-      token = token.next;
-      TokenType type = token.type;
-      if (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
-          type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-        token = _skipStringInterpolation(token);
-      }
-    }
-    if (identical(token, startToken)) {
-      return null;
-    }
-    return token;
-  }
-
-  /// Parse a type annotation, starting at the [startToken], without actually
-  /// creating a type annotation or changing the current token. Return the token
-  /// following the type annotation that was parsed, or `null` if the given
-  /// token is not the first token in a valid type annotation.
-  ///
-  /// This method must be kept in sync with [parseTypeAnnotation].
-  Token skipTypeAnnotation(Token startToken) {
-    Token next;
-    if (_atGenericFunctionTypeAfterReturnType(startToken)) {
-      // Generic function type with no return type.
-      next = skipGenericFunctionTypeAfterReturnType(startToken);
-    } else {
-      next = skipTypeWithoutFunction(startToken);
-    }
-    while (next != null && _atGenericFunctionTypeAfterReturnType(next)) {
-      next = skipGenericFunctionTypeAfterReturnType(next);
-    }
-    return next;
-  }
-
-  /// Parse a list of type arguments, starting at the [startToken], without
-  /// actually creating a type argument list or changing the current token.
-  /// Return the token following the type argument list that was parsed, or
-  /// `null` if the given token is not the first token in a valid type argument
-  /// list.
-  ///
-  /// This method must be kept in sync with [parseTypeArgumentList].
-  ///
-  ///     typeArguments ::=
-  ///         '<' typeList '>'
-  ///
-  ///     typeList ::=
-  ///         type (',' type)*
-  Token skipTypeArgumentList(Token startToken) {
-    Token token = startToken;
-    if (!_tokenMatches(token, TokenType.LT)) {
-      return null;
-    }
-    token = skipTypeAnnotation(token.next);
-    if (token == null) {
-      // If the start token '<' is followed by '>'
-      // then assume this should be type argument list but is missing a type
-      token = startToken.next;
-      if (_tokenMatches(token, TokenType.GT)) {
-        return token.next;
-      }
-      return null;
-    }
-    while (_tokenMatches(token, TokenType.COMMA)) {
-      token = skipTypeAnnotation(token.next);
-      if (token == null) {
-        return null;
-      }
-    }
-    if (token.type == TokenType.GT) {
-      return token.next;
-    } else if (token.type == TokenType.GT_GT) {
-      Token second = Token(TokenType.GT, token.offset + 1);
-      second.setNextWithoutSettingPrevious(token.next);
-      return second;
-    }
-    return null;
-  }
-
-  /// Parse a type name, starting at the [startToken], without actually creating
-  /// a type name or changing the current token. Return the token following the
-  /// type name that was parsed, or `null` if the given token is not the first
-  /// token in a valid type name.
-  ///
-  /// This method must be kept in sync with [parseTypeName].
-  ///
-  ///     type ::=
-  ///         qualified typeArguments?
-  Token skipTypeName(Token startToken) {
-    Token token = skipPrefixedIdentifier(startToken);
-    if (token == null) {
-      return null;
-    }
-    if (_tokenMatches(token, TokenType.LT)) {
-      token = skipTypeArgumentList(token);
-    }
-    return token;
-  }
-
-  /// Parse a type parameter list, starting at the [startToken], without
-  /// actually creating a type parameter list or changing the current token.
-  /// Return the token following the type parameter list that was parsed, or
-  /// `null` if the given token is not the first token in a valid type parameter
-  /// list.
-  ///
-  /// This method must be kept in sync with [parseTypeParameterList].
-  Token skipTypeParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.LT)) {
-      return null;
-    }
-    int depth = 1;
-    Token previous = startToken;
-    Token next = startToken.next;
-    while (next != previous) {
-      if (_tokenMatches(next, TokenType.LT)) {
-        depth++;
-      } else if (_tokenMatches(next, TokenType.GT)) {
-        depth--;
-        if (depth == 0) {
-          return next.next;
-        }
-      }
-      previous = next;
-      next = next.next;
-    }
-    return null;
-  }
-
-  /// Parse a typeWithoutFunction, starting at the [startToken], without
-  /// actually creating a TypeAnnotation or changing the current token. Return
-  /// the token following the typeWithoutFunction that was parsed, or `null` if
-  /// the given token is not the first token in a valid typeWithoutFunction.
-  ///
-  /// This method must be kept in sync with [parseTypeWithoutFunction].
-  Token skipTypeWithoutFunction(Token startToken) {
-    if (startToken.keyword == Keyword.VOID) {
-      return startToken.next;
-    } else {
-      return skipTypeName(startToken);
-    }
-  }
-
-  /// Advance to the next token in the token stream.
-  void _advance() {
-    _currentToken = _currentToken.next;
-  }
-
-  /// Append the character equivalent of the given [codePoint] to the given
-  /// [builder]. Use the [startIndex] and [endIndex] to report an error, and
-  /// don't append anything to the builder, if the code point is invalid. The
-  /// [escapeSequence] is the escape sequence that was parsed to produce the
-  /// code point (used for error reporting).
-  void _appendCodePoint(StringBuffer buffer, String source, int codePoint,
-      int startIndex, int endIndex) {
-    if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) {
-      String escapeSequence = source.substring(startIndex, endIndex + 1);
-      _reportErrorForCurrentToken(
-          ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
-      return;
-    }
-    if (codePoint < Character.MAX_VALUE) {
-      buffer.writeCharCode(codePoint);
-    } else {
-      buffer.write(Character.toChars(codePoint));
-    }
-  }
-
-  /// Return `true` if we are positioned at the keyword 'Function' in a generic
-  /// function type alias.
-  bool _atGenericFunctionTypeAfterReturnType(Token startToken) {
-    if (_tokenMatchesKeyword(startToken, Keyword.FUNCTION)) {
-      Token next = startToken.next;
-      if (next != null &&
-          (_tokenMatches(next, TokenType.OPEN_PAREN) ||
-              _tokenMatches(next, TokenType.LT))) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  void _configureFeatures(FeatureSet featureSet) {
-    if (featureSet.isEnabled(Feature.control_flow_collections)) {
-      throw UnimplementedError('control_flow_collections experiment'
-          ' not supported by analyzer parser');
-    }
-    if (featureSet.isEnabled(Feature.non_nullable)) {
-      throw UnimplementedError(
-          'non-nullable experiment not supported by analyzer parser');
-    }
-    if (featureSet.isEnabled(Feature.spread_collections)) {
-      throw UnimplementedError(
-          'spread_collections experiment not supported by analyzer parser');
-    }
-    if (featureSet.isEnabled(Feature.triple_shift)) {
-      throw UnimplementedError('triple_shift experiment'
-          ' not supported by analyzer parser');
-    }
-    _featureSet = featureSet;
-  }
-
-  /// Convert the given [method] declaration into the nearest valid top-level
-  /// function declaration (that is, the function declaration that most closely
-  /// captures the components of the given method declaration).
-  FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) =>
-      astFactory.functionDeclaration(
-          method.documentationComment,
-          method.metadata,
-          method.externalKeyword,
-          method.returnType,
-          method.propertyKeyword,
-          method.name,
-          astFactory.functionExpression(
-              method.typeParameters, method.parameters, method.body));
-
-  /// Return `true` if the current token could be the start of a compilation
-  /// unit member. This method is used for recovery purposes to decide when to
-  /// stop skipping tokens after finding an error while parsing a compilation
-  /// unit member.
-  bool _couldBeStartOfCompilationUnitMember() {
-    Keyword keyword = _currentToken.keyword;
-    Token next = _currentToken.next;
-    TokenType nextType = next.type;
-    if ((keyword == Keyword.IMPORT ||
-            keyword == Keyword.EXPORT ||
-            keyword == Keyword.LIBRARY ||
-            keyword == Keyword.PART) &&
-        nextType != TokenType.PERIOD &&
-        nextType != TokenType.LT) {
-      // This looks like the start of a directive
-      return true;
-    } else if (keyword == Keyword.CLASS) {
-      // This looks like the start of a class definition
-      return true;
-    } else if (keyword == Keyword.TYPEDEF &&
-        nextType != TokenType.PERIOD &&
-        nextType != TokenType.LT) {
-      // This looks like the start of a typedef
-      return true;
-    } else if (keyword == Keyword.VOID ||
-        ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-            _tokenMatchesIdentifier(next)) ||
-        (keyword == Keyword.OPERATOR && _isOperator(next))) {
-      // This looks like the start of a function
-      return true;
-    } else if (_matchesIdentifier()) {
-      if (nextType == TokenType.OPEN_PAREN) {
-        // This looks like the start of a function
-        return true;
-      }
-      Token token = skipTypeAnnotation(_currentToken);
-      if (token == null) {
-        return false;
-      }
-      // TODO(brianwilkerson) This looks wrong; should we be checking 'token'?
-      if (keyword == Keyword.GET ||
-          keyword == Keyword.SET ||
-          (keyword == Keyword.OPERATOR && _isOperator(next)) ||
-          _matchesIdentifier()) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Return a synthetic token representing the given [keyword].
-  Token _createSyntheticKeyword(Keyword keyword) =>
-      _injectToken(SyntheticKeywordToken(keyword, _currentToken.offset));
-
-  /// Return a synthetic token with the given [type].
-  Token _createSyntheticToken(TokenType type) =>
-      _injectToken(StringToken(type, "", _currentToken.offset));
-
-  /// Create and return a new token with the given [type]. The token will
-  /// replace the first portion of the given [token], so it will have the same
-  /// offset and will have any comments that might have preceded the token.
-  Token _createToken(Token token, TokenType type, {bool isBegin = false}) {
-    CommentToken comments = token.precedingComments;
-    if (comments == null) {
-      if (isBegin) {
-        return BeginToken(type, token.offset);
-      }
-      return Token(type, token.offset);
-    } else if (isBegin) {
-      return BeginToken(type, token.offset, comments);
-    }
-    return Token(type, token.offset, comments);
-  }
-
-  /// Check that the given [expression] is assignable and report an error if it
-  /// isn't.
-  ///
-  ///     assignableExpression ::=
-  ///         primary (arguments* assignableSelector)+
-  ///       | 'super' unconditionalAssignableSelector
-  ///       | identifier
-  ///
-  ///     unconditionalAssignableSelector ::=
-  ///         '[' expression ']'
-  ///       | '.' identifier
-  ///
-  ///     assignableSelector ::=
-  ///         unconditionalAssignableSelector
-  ///       | '?.' identifier
-  void _ensureAssignable(Expression expression) {
-    if (expression != null && !expression.isAssignable) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE);
-    }
-  }
-
-  /// If the current token has the expected type, return it after advancing to
-  /// the next token. Otherwise report an error and return the current token
-  /// without advancing.
-  ///
-  /// Note that the method [_expectGt] should be used if the argument to this
-  /// method would be [TokenType.GT].
-  ///
-  /// The [type] is the type of token that is expected.
-  Token _expect(TokenType type) {
-    if (_matches(type)) {
-      return getAndAdvance();
-    }
-    // Remove uses of this method in favor of matches?
-    // Pass in the error code to use to report the error?
-    if (type == TokenType.SEMICOLON) {
-      if (_tokenMatches(_currentToken.next, TokenType.SEMICOLON)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-        _advance();
-        return getAndAdvance();
-      }
-      _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
-          _currentToken.previous, [type.lexeme]);
-      return _createSyntheticToken(TokenType.SEMICOLON);
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
-    return _createSyntheticToken(type);
-  }
-
-  /// If the current token has the type [TokenType.GT], return it after
-  /// advancing to the next token. Otherwise report an error and create a
-  /// synthetic token.
-  Token _expectGt() {
-    if (_matchesGt()) {
-      return getAndAdvance();
-    }
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.lexeme]);
-    return _createSyntheticToken(TokenType.GT);
-  }
-
-  /// If the current token is a keyword matching the given [keyword], return it
-  /// after advancing to the next token. Otherwise report an error and return
-  /// the current token without advancing.
-  Token _expectKeyword(Keyword keyword) {
-    if (_matchesKeyword(keyword)) {
-      return getAndAdvance();
-    }
-    // Remove uses of this method in favor of matches?
-    // Pass in the error code to use to report the error?
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [keyword.lexeme]);
-    return _currentToken;
-  }
-
-  /// Search the given list of [ranges] for a range that contains the given
-  /// [index]. Return the range that was found, or `null` if none of the ranges
-  /// contain the index.
-  List<int> _findRange(List<List<int>> ranges, int index) {
-    int rangeCount = ranges.length;
-    for (int i = 0; i < rangeCount; i++) {
-      List<int> range = ranges[i];
-      if (range[0] <= index && index <= range[1]) {
-        return range;
-      } else if (index < range[0]) {
-        return null;
-      }
-    }
-    return null;
-  }
-
-  /// Return a list of the ranges of characters in the given [comment] that
-  /// should be treated as code blocks.
-  List<List<int>> _getCodeBlockRanges(String comment) {
-    List<List<int>> ranges = <List<int>>[];
-    int length = comment.length;
-    if (length < 3) {
-      return ranges;
-    }
-    int index = 0;
-    int firstChar = comment.codeUnitAt(0);
-    if (firstChar == 0x2F) {
-      int secondChar = comment.codeUnitAt(1);
-      int thirdChar = comment.codeUnitAt(2);
-      if ((secondChar == 0x2A && thirdChar == 0x2A) ||
-          (secondChar == 0x2F && thirdChar == 0x2F)) {
-        index = 3;
-      }
-    }
-    if (StringUtilities.startsWith4(comment, index, 0x20, 0x20, 0x20, 0x20)) {
-      int end = index + 4;
-      while (end < length &&
-          comment.codeUnitAt(end) != 0xD &&
-          comment.codeUnitAt(end) != 0xA) {
-        end = end + 1;
-      }
-      ranges.add(<int>[index, end]);
-      index = end;
-    }
-    while (index < length) {
-      int currentChar = comment.codeUnitAt(index);
-      if (currentChar == 0xD || currentChar == 0xA) {
-        index = index + 1;
-        while (index < length &&
-            Character.isWhitespace(comment.codeUnitAt(index))) {
-          index = index + 1;
-        }
-        if (StringUtilities.startsWith6(
-            comment, index, 0x2A, 0x20, 0x20, 0x20, 0x20, 0x20)) {
-          int end = index + 6;
-          while (end < length &&
-              comment.codeUnitAt(end) != 0xD &&
-              comment.codeUnitAt(end) != 0xA) {
-            end = end + 1;
-          }
-          ranges.add(<int>[index, end]);
-          index = end;
-        }
-      } else if (index + 1 < length &&
-          currentChar == 0x5B &&
-          comment.codeUnitAt(index + 1) == 0x3A) {
-        int end = StringUtilities.indexOf2(comment, index + 2, 0x3A, 0x5D);
-        if (end < 0) {
-          end = length;
-        }
-        ranges.add(<int>[index, end]);
-        index = end + 1;
-      } else {
-        index = index + 1;
-      }
-    }
-    return ranges;
-  }
-
-  /// Return the end token associated with the given [beginToken], or `null` if
-  /// either the given token is not a begin token or it does not have an end
-  /// token associated with it.
-  Token _getEndToken(Token beginToken) {
-    if (beginToken is BeginToken) {
-      return beginToken.endToken;
-    }
-    return null;
-  }
-
-  /// Inject the given [token] into the token stream immediately before the
-  /// current token.
-  Token _injectToken(Token token) {
-    Token previous = _currentToken.previous;
-    token.setNext(_currentToken);
-    previous.setNext(token);
-    return token;
-  }
-
-  /// Return `true` if the given [character] is a valid hexadecimal digit.
-  bool _isHexDigit(int character) =>
-      (0x30 <= character && character <= 0x39) ||
-      (0x41 <= character && character <= 0x46) ||
-      (0x61 <= character && character <= 0x66);
-
-  bool _isLikelyArgumentList() {
-    // Try to reduce the amount of lookahead required here before enabling
-    // generic methods.
-    if (_matches(TokenType.OPEN_PAREN)) {
-      return true;
-    }
-    Token token = skipTypeArgumentList(_currentToken);
-    return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
-  }
-
-  /// Return `true` if it looks like we have found the invocation of a named
-  /// constructor following the name of the type:
-  /// ```
-  /// typeArguments? '.' identifier '('
-  /// ```
-  bool _isLikelyNamedInstanceCreation() {
-    Token token = skipTypeArgumentList(_currentToken);
-    if (token != null && _tokenMatches(token, TokenType.PERIOD)) {
-      token = skipSimpleIdentifier(token.next);
-      if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Given that we have just found bracketed text within the given [comment],
-  /// look to see whether that text is (a) followed by a parenthesized link
-  /// address, (b) followed by a colon, or (c) followed by optional whitespace
-  /// and another square bracket. The [rightIndex] is the index of the right
-  /// bracket. Return `true` if the bracketed text is followed by a link
-  /// address.
-  ///
-  /// This method uses the syntax described by the
-  /// <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a>
-  /// project.
-  bool _isLinkText(String comment, int rightIndex) {
-    int length = comment.length;
-    int index = rightIndex + 1;
-    if (index >= length) {
-      return false;
-    }
-    int nextChar = comment.codeUnitAt(index);
-    if (nextChar == 0x28 || nextChar == 0x3A) {
-      return true;
-    }
-    while (Character.isWhitespace(nextChar)) {
-      index = index + 1;
-      if (index >= length) {
-        return false;
-      }
-      nextChar = comment.codeUnitAt(index);
-    }
-    return nextChar == 0x5B;
-  }
-
-  /// Return `true` if the given [startToken] appears to be the beginning of an
-  /// operator declaration.
-  bool _isOperator(Token startToken) {
-    // Accept any operator here, even if it is not user definable.
-    if (!startToken.isOperator) {
-      return false;
-    }
-    // Token "=" means that it is actually a field initializer.
-    if (startToken.type == TokenType.EQ) {
-      return false;
-    }
-    // Consume all operator tokens.
-    Token token = startToken.next;
-    while (token.isOperator) {
-      token = token.next;
-    }
-    // Formal parameter list is expect now.
-    return _tokenMatches(token, TokenType.OPEN_PAREN);
-  }
-
-  bool _isPeekGenericTypeParametersAndOpenParen() {
-    Token token = _skipTypeParameterList(_peek());
-    return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
-  }
-
-  /// Return `true` if the [startToken] appears to be the first token of a type
-  /// name that is followed by a variable or field formal parameter.
-  bool _isTypedIdentifier(Token startToken) {
-    Token token = skipTypeAnnotation(startToken);
-    if (token == null) {
-      return false;
-    } else if (_tokenMatchesIdentifier(token)) {
-      return true;
-    } else if (_tokenMatchesKeyword(token, Keyword.THIS) &&
-        _tokenMatches(token.next, TokenType.PERIOD) &&
-        _tokenMatchesIdentifier(token.next.next)) {
-      return true;
-    } else if (startToken.next != token &&
-        !_tokenMatches(token, TokenType.OPEN_PAREN)) {
-      // The type is more than a simple identifier, so it should be assumed to
-      // be a type name.
-      return true;
-    }
-    return false;
-  }
-
-  /// Return `true` if the given [expression] is a primary expression that is
-  /// allowed to be an assignable expression without any assignable selector.
-  bool _isValidAssignableExpression(Expression expression) {
-    if (expression is SimpleIdentifier) {
-      return true;
-    } else if (expression is PropertyAccess) {
-      return expression.target is SuperExpression;
-    } else if (expression is IndexExpression) {
-      return expression.target is SuperExpression;
-    }
-    return false;
-  }
-
-  /// Increments the error reporting lock level. If level is more than `0`, then
-  /// [reportError] wont report any error.
-  void _lockErrorListener() {
-    _errorListenerLock++;
-  }
-
-  /// Return `true` if the current token has the given [type]. Note that the
-  /// method [_matchesGt] should be used if the argument to this method would be
-  /// [TokenType.GT].
-  bool _matches(TokenType type) => _currentToken.type == type;
-
-  /// Return `true` if the current token has a type of [TokenType.GT]. Note that
-  /// this method, unlike other variants, will modify the token stream if
-  /// possible to match desired type. In particular, if the next token is either
-  /// a '>>' or '>>>', the token stream will be re-written and `true` will be
-  /// returned.
-  bool _matchesGt() {
-    TokenType currentType = _currentToken.type;
-    if (currentType == TokenType.GT) {
-      return true;
-    } else if (currentType == TokenType.GT_GT) {
-      Token first = _createToken(_currentToken, TokenType.GT);
-      Token second = Token(TokenType.GT, _currentToken.offset + 1);
-      second.setNext(_currentToken.next);
-      first.setNext(second);
-      _currentToken.previous.setNext(first);
-      _currentToken = first;
-      return true;
-    } else if (currentType == TokenType.GT_EQ) {
-      Token first = _createToken(_currentToken, TokenType.GT);
-      Token second = Token(TokenType.EQ, _currentToken.offset + 1);
-      second.setNext(_currentToken.next);
-      first.setNext(second);
-      _currentToken.previous.setNext(first);
-      _currentToken = first;
-      return true;
-    } else if (currentType == TokenType.GT_GT_EQ) {
-      int offset = _currentToken.offset;
-      Token first = _createToken(_currentToken, TokenType.GT);
-      Token second = Token(TokenType.GT, offset + 1);
-      Token third = Token(TokenType.EQ, offset + 2);
-      third.setNext(_currentToken.next);
-      second.setNext(third);
-      first.setNext(second);
-      _currentToken.previous.setNext(first);
-      _currentToken = first;
-      return true;
-    }
-    return false;
-  }
-
-  /// Return `true` if the current token is a valid identifier. Valid
-  /// identifiers include built-in identifiers (pseudo-keywords).
-  bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken);
-
-  /// Return `true` if the current token matches the given [keyword].
-  bool _matchesKeyword(Keyword keyword) =>
-      _tokenMatchesKeyword(_currentToken, keyword);
-
-  /// If the current token has the given [type], then advance to the next token
-  /// and return `true`. Otherwise, return `false` without advancing. This
-  /// method should not be invoked with an argument value of [TokenType.GT].
-  bool _optional(TokenType type) {
-    if (_currentToken.type == type) {
-      _advance();
-      return true;
-    }
-    return false;
-  }
-
-  /// Parse an argument list when we need to check for an open paren and recover
-  /// when there isn't one. Return the argument list that was parsed.
-  ArgumentList _parseArgumentListChecked() {
-    if (_matches(TokenType.OPEN_PAREN)) {
-      return parseArgumentList();
-    }
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_PAREN.lexeme]);
-    // Recovery: Look to see whether there is a close paren that isn't matched
-    // to an open paren and if so parse the list of arguments as normal.
-    return astFactory.argumentList(_createSyntheticToken(TokenType.OPEN_PAREN),
-        null, _createSyntheticToken(TokenType.CLOSE_PAREN));
-  }
-
-  /// Parse an assert within a constructor's initializer list. Return the
-  /// assert.
-  ///
-  /// This method assumes that the current token matches `Keyword.ASSERT`.
-  ///
-  ///     assertInitializer ::=
-  ///         'assert' '(' expression [',' expression] ')'
-  AssertInitializer _parseAssertInitializer() {
-    Token keyword = getAndAdvance();
-    Token leftParen = _expect(TokenType.OPEN_PAREN);
-    Expression expression = parseExpression2();
-    Token comma;
-    Expression message;
-    if (_matches(TokenType.COMMA)) {
-      comma = getAndAdvance();
-      if (_matches(TokenType.CLOSE_PAREN)) {
-        comma;
-      } else {
-        message = parseExpression2();
-        if (_matches(TokenType.COMMA)) {
-          getAndAdvance();
-        }
-      }
-    }
-    Token rightParen = _expect(TokenType.CLOSE_PAREN);
-    return astFactory.assertInitializer(
-        keyword, leftParen, expression, comma, message, rightParen);
-  }
-
-  /// Parse a block when we need to check for an open curly brace and recover
-  /// when there isn't one. Return the block that was parsed.
-  ///
-  ///     block ::=
-  ///         '{' statements '}'
-  Block _parseBlockChecked() {
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      return parseBlock();
-    }
-    // TODO(brianwilkerson) Improve the error message.
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_CURLY_BRACKET.lexeme]);
-    // Recovery: Check for an unmatched closing curly bracket and parse
-    // statements until it is reached.
-    return astFactory.block(_createSyntheticToken(TokenType.OPEN_CURLY_BRACKET),
-        null, _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET));
-  }
-
-  /// Parse a list of class members. The [className] is the name of the class
-  /// whose members are being parsed. The [closingBracket] is the closing
-  /// bracket for the class, or `null` if the closing bracket is missing.
-  /// Return the list of class members that were parsed.
-  ///
-  ///     classMembers ::=
-  ///         (metadata memberDefinition)*
-  List<ClassMember> _parseClassMembers(String className, Token closingBracket) {
-    List<ClassMember> members = <ClassMember>[];
-    Token memberStart = _currentToken;
-    TokenType type = _currentToken.type;
-    Keyword keyword = _currentToken.keyword;
-    while (type != TokenType.EOF &&
-        type != TokenType.CLOSE_CURLY_BRACKET &&
-        (closingBracket != null ||
-            (keyword != Keyword.CLASS && keyword != Keyword.TYPEDEF))) {
-      if (type == TokenType.SEMICOLON) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      } else {
-        ClassMember member = parseClassMember(className);
-        if (member != null) {
-          members.add(member);
-        }
-      }
-      if (identical(_currentToken, memberStart)) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      }
-      memberStart = _currentToken;
-      type = _currentToken.type;
-      keyword = _currentToken.keyword;
-    }
-    return members;
-  }
-
-  /// Parse a class type alias. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. The [abstractKeyword] is the token
-  /// representing the 'abstract' keyword. The [classKeyword] is the token
-  /// representing the 'class' keyword. The [className] is the name of the
-  /// alias, and the [typeParameters] are the type parameters following the
-  /// name. Return the class type alias that was parsed.
-  ///
-  ///     classTypeAlias ::=
-  ///         identifier typeParameters? '=' 'abstract'? mixinApplication
-  ///
-  ///     mixinApplication ::=
-  ///         type withClause implementsClause? ';'
-  ClassTypeAlias _parseClassTypeAliasAfterName(
-      CommentAndMetadata commentAndMetadata,
-      Token abstractKeyword,
-      Token classKeyword,
-      SimpleIdentifier className,
-      TypeParameterList typeParameters) {
-    Token equals = _expect(TokenType.EQ);
-    TypeName superclass = parseTypeName(false);
-    WithClause withClause;
-    if (_matchesKeyword(Keyword.WITH)) {
-      withClause = parseWithClause();
-    } else {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.lexeme]);
-    }
-    ImplementsClause implementsClause;
-    if (_matchesKeyword(Keyword.IMPLEMENTS)) {
-      implementsClause = parseImplementsClause();
-    }
-    Token semicolon;
-    if (_matches(TokenType.SEMICOLON)) {
-      semicolon = getAndAdvance();
-    } else {
-      if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.EXPECTED_TOKEN, [TokenType.SEMICOLON.lexeme]);
-        Token leftBracket = getAndAdvance();
-        _parseClassMembers(className.name, _getEndToken(leftBracket));
-        _expect(TokenType.CLOSE_CURLY_BRACKET);
-      } else {
-        _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
-            _currentToken.previous, [TokenType.SEMICOLON.lexeme]);
-      }
-      semicolon = _createSyntheticToken(TokenType.SEMICOLON);
-    }
-    return astFactory.classTypeAlias(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        classKeyword,
-        className,
-        typeParameters,
-        equals,
-        abstractKeyword,
-        superclass,
-        withClause,
-        implementsClause,
-        semicolon);
-  }
-
-  /// Parse a list of configurations. Return the configurations that were
-  /// parsed, or `null` if there are no configurations.
-  List<Configuration> _parseConfigurations() {
-    List<Configuration> configurations;
-    while (_matchesKeyword(Keyword.IF)) {
-      configurations ??= <Configuration>[];
-      configurations.add(parseConfiguration());
-    }
-    return configurations;
-  }
-
-  ConstructorDeclaration _parseConstructor(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      Token constKeyword,
-      Token factoryKeyword,
-      SimpleIdentifier returnType,
-      Token period,
-      SimpleIdentifier name,
-      FormalParameterList parameters) {
-    bool bodyAllowed = externalKeyword == null;
-    Token separator;
-    List<ConstructorInitializer> initializers;
-    if (_matches(TokenType.COLON)) {
-      separator = getAndAdvance();
-      initializers = <ConstructorInitializer>[];
-      do {
-        Keyword keyword = _currentToken.keyword;
-        if (keyword == Keyword.THIS) {
-          TokenType nextType = _peek().type;
-          if (nextType == TokenType.OPEN_PAREN) {
-            bodyAllowed = false;
-            initializers.add(parseRedirectingConstructorInvocation(false));
-          } else if (nextType == TokenType.PERIOD &&
-              _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
-            bodyAllowed = false;
-            initializers.add(parseRedirectingConstructorInvocation(true));
-          } else {
-            initializers.add(parseConstructorFieldInitializer(true));
-          }
-        } else if (keyword == Keyword.SUPER) {
-          initializers.add(parseSuperConstructorInvocation());
-        } else if (_matches(TokenType.OPEN_CURLY_BRACKET) ||
-            _matches(TokenType.FUNCTION)) {
-          _reportErrorForCurrentToken(ParserErrorCode.MISSING_INITIALIZER);
-        } else if (_matchesKeyword(Keyword.ASSERT)) {
-          initializers.add(_parseAssertInitializer());
-        } else {
-          initializers.add(parseConstructorFieldInitializer(false));
-        }
-      } while (_optional(TokenType.COMMA));
-      if (factoryKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.FACTORY_WITH_INITIALIZERS, factoryKeyword);
-      }
-    }
-    ConstructorName redirectedConstructor;
-    FunctionBody body;
-    if (_matches(TokenType.EQ)) {
-      separator = getAndAdvance();
-      redirectedConstructor = parseConstructorName();
-      body = astFactory.emptyFunctionBody(_expect(TokenType.SEMICOLON));
-      if (factoryKeyword == null) {
-        _reportErrorForNode(
-            ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
-            redirectedConstructor);
-      }
-    } else {
-      body =
-          parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-      if (constKeyword != null &&
-          factoryKeyword != null &&
-          externalKeyword == null &&
-          body is! NativeFunctionBody) {
-        _reportErrorForToken(ParserErrorCode.CONST_FACTORY, factoryKeyword);
-      } else if (body is EmptyFunctionBody) {
-        if (factoryKeyword != null &&
-            externalKeyword == null &&
-            _parseFunctionBodies) {
-          _reportErrorForToken(
-              ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyword);
-        }
-      } else {
-        if (constKeyword != null && body is! NativeFunctionBody) {
-          _reportErrorForNode(
-              ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body);
-        } else if (externalKeyword != null) {
-          _reportErrorForNode(
-              ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body);
-        } else if (!bodyAllowed) {
-          _reportErrorForNode(
-              ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, body);
-        }
-      }
-    }
-    return astFactory.constructorDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        constKeyword,
-        factoryKeyword,
-        returnType,
-        period,
-        name,
-        parameters,
-        separator,
-        initializers,
-        redirectedConstructor,
-        body);
-  }
-
-  /// Parse an enum constant declaration. Return the enum constant declaration
-  /// that was parsed.
-  ///
-  /// Specified:
-  ///
-  ///     enumConstant ::=
-  ///         id
-  ///
-  /// Actual:
-  ///
-  ///     enumConstant ::=
-  ///         metadata id
-  EnumConstantDeclaration _parseEnumConstantDeclaration() {
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    SimpleIdentifier name;
-    if (_matchesIdentifier()) {
-      name = _parseSimpleIdentifierUnchecked(isDeclaration: true);
-    } else {
-      name = createSyntheticIdentifier();
-    }
-    return astFactory.enumConstantDeclaration(
-        commentAndMetadata.comment, commentAndMetadata.metadata, name);
-  }
-
-  /// Parse a list of formal parameters given that the list starts with the
-  /// given [leftParenthesis]. Return the formal parameters that were parsed.
-  FormalParameterList _parseFormalParameterListAfterParen(Token leftParenthesis,
-      {bool inFunctionType = false}) {
-    if (_matches(TokenType.CLOSE_PAREN)) {
-      return astFactory.formalParameterList(
-          leftParenthesis, null, null, null, getAndAdvance());
-    }
-    //
-    // Even though it is invalid to have default parameters outside of brackets,
-    // required parameters inside of brackets, or multiple groups of default and
-    // named parameters, we allow all of these cases so that we can recover
-    // better.
-    //
-    List<FormalParameter> parameters = <FormalParameter>[];
-    Token leftSquareBracket;
-    Token rightSquareBracket;
-    Token leftCurlyBracket;
-    Token rightCurlyBracket;
-    ParameterKind kind = ParameterKind.REQUIRED;
-    bool firstParameter = true;
-    bool reportedMultiplePositionalGroups = false;
-    bool reportedMultipleNamedGroups = false;
-    bool reportedMixedGroups = false;
-    bool wasOptionalParameter = false;
-    Token initialToken;
-    do {
-      if (firstParameter) {
-        firstParameter = false;
-      } else if (!_optional(TokenType.COMMA)) {
-        // TODO(brianwilkerson) The token is wrong, we need to recover from this
-        // case.
-        if (_getEndToken(leftParenthesis) != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme]);
-        } else {
-          _reportErrorForToken(ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
-              _currentToken.previous);
-          break;
-        }
-      }
-      initialToken = _currentToken;
-      //
-      // Handle the beginning of parameter groups.
-      //
-      TokenType type = _currentToken.type;
-      if (type == TokenType.OPEN_SQUARE_BRACKET) {
-        wasOptionalParameter = true;
-        if (leftSquareBracket != null && !reportedMultiplePositionalGroups) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS);
-          reportedMultiplePositionalGroups = true;
-        }
-        if (leftCurlyBracket != null && !reportedMixedGroups) {
-          _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
-          reportedMixedGroups = true;
-        }
-        leftSquareBracket = getAndAdvance();
-        kind = ParameterKind.POSITIONAL;
-      } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-        wasOptionalParameter = true;
-        if (leftCurlyBracket != null && !reportedMultipleNamedGroups) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS);
-          reportedMultipleNamedGroups = true;
-        }
-        if (leftSquareBracket != null && !reportedMixedGroups) {
-          _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
-          reportedMixedGroups = true;
-        }
-        leftCurlyBracket = getAndAdvance();
-        kind = ParameterKind.NAMED;
-      }
-      //
-      // Parse and record the parameter.
-      //
-      FormalParameter parameter =
-          parseFormalParameter(kind, inFunctionType: inFunctionType);
-      parameters.add(parameter);
-      if (kind == ParameterKind.REQUIRED && wasOptionalParameter) {
-        _reportErrorForNode(
-            ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, parameter);
-      }
-      //
-      // Handle the end of parameter groups.
-      //
-      // TODO(brianwilkerson) Improve the detection and reporting of missing and
-      // mismatched delimiters.
-      type = _currentToken.type;
-
-      // Advance past trailing commas as appropriate.
-      if (type == TokenType.COMMA) {
-        // Only parse commas trailing normal (non-positional/named) params.
-        if (rightSquareBracket == null && rightCurlyBracket == null) {
-          Token next = _peek();
-          if (next.type == TokenType.CLOSE_PAREN ||
-              next.type == TokenType.CLOSE_CURLY_BRACKET ||
-              next.type == TokenType.CLOSE_SQUARE_BRACKET) {
-            _advance();
-            type = _currentToken.type;
-          }
-        }
-      }
-
-      if (type == TokenType.CLOSE_SQUARE_BRACKET) {
-        rightSquareBracket = getAndAdvance();
-        if (leftSquareBracket == null) {
-          if (leftCurlyBracket != null) {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
-                ['}', ']']);
-            rightCurlyBracket = rightSquareBracket;
-            rightSquareBracket;
-            // Skip over synthetic closer inserted by fasta
-            // since we've already reported an error
-            if (_currentToken.type == TokenType.CLOSE_CURLY_BRACKET &&
-                _currentToken.isSynthetic) {
-              _advance();
-            }
-          } else {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
-                ["["]);
-          }
-        }
-        kind = ParameterKind.REQUIRED;
-      } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-        rightCurlyBracket = getAndAdvance();
-        if (leftCurlyBracket == null) {
-          if (leftSquareBracket != null) {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
-                [']', '}']);
-            rightSquareBracket = rightCurlyBracket;
-            rightCurlyBracket;
-            // Skip over synthetic closer inserted by fasta
-            // since we've already reported an error
-            if (_currentToken.type == TokenType.CLOSE_SQUARE_BRACKET &&
-                _currentToken.isSynthetic) {
-              _advance();
-            }
-          } else {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
-                ["{"]);
-          }
-        }
-        kind = ParameterKind.REQUIRED;
-      }
-    } while (!_matches(TokenType.CLOSE_PAREN) &&
-        !identical(initialToken, _currentToken));
-    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-    //
-    // Check that the groups were closed correctly.
-    //
-    if (leftSquareBracket != null && rightSquareBracket == null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
-    }
-    if (leftCurlyBracket != null && rightCurlyBracket == null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
-    }
-    //
-    // Build the parameter list.
-    //
-    leftSquareBracket ??= leftCurlyBracket;
-    rightSquareBracket ??= rightCurlyBracket;
-    return astFactory.formalParameterList(leftParenthesis, parameters,
-        leftSquareBracket, rightSquareBracket, rightParenthesis);
-  }
-
-  /// Parse a list of formal parameters. Return the formal parameters that were
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.OPEN_PAREN`.
-  FormalParameterList _parseFormalParameterListUnchecked(
-      {bool inFunctionType = false}) {
-    return _parseFormalParameterListAfterParen(getAndAdvance(),
-        inFunctionType: inFunctionType);
-  }
-
-  /// Parse a function declaration statement. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [returnType] is the return type, or `null` if there is no return type.
-  /// Return the function declaration statement that was parsed.
-  ///
-  ///     functionDeclarationStatement ::=
-  ///         functionSignature functionBody
-  Statement _parseFunctionDeclarationStatementAfterReturnType(
-      CommentAndMetadata commentAndMetadata, TypeAnnotation returnType) {
-    FunctionDeclaration declaration =
-        parseFunctionDeclaration(commentAndMetadata, null, returnType);
-    Token propertyKeyword = declaration.propertyKeyword;
-    if (propertyKeyword != null) {
-      if (propertyKeyword.keyword == Keyword.GET) {
-        _reportErrorForToken(
-            ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword);
-      } else {
-        _reportErrorForToken(
-            ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword);
-      }
-    }
-    return astFactory.functionDeclarationStatement(declaration);
-  }
-
-  /// Parse a function type alias. The [commentAndMetadata] is the metadata to
-  /// be associated with the member. The [keyword] is the token representing the
-  /// 'typedef' keyword. Return the function type alias that was parsed.
-  ///
-  ///     functionTypeAlias ::=
-  ///         functionPrefix typeParameterList? formalParameterList ';'
-  ///
-  ///     functionPrefix ::=
-  ///         returnType? name
-  FunctionTypeAlias _parseFunctionTypeAlias(
-      CommentAndMetadata commentAndMetadata, Token keyword) {
-    TypeAnnotation returnType;
-    if (hasReturnTypeInTypeAlias) {
-      returnType = parseTypeAnnotation(false);
-    }
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    TypeParameterList typeParameters;
-    if (_matches(TokenType.LT)) {
-      typeParameters = parseTypeParameterList();
-    }
-    TokenType type = _currentToken.type;
-    if (type == TokenType.SEMICOLON || type == TokenType.EOF) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
-      FormalParameterList parameters = astFactory.formalParameterList(
-          _createSyntheticToken(TokenType.OPEN_PAREN),
-          null,
-          null,
-          null,
-          _createSyntheticToken(TokenType.CLOSE_PAREN));
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.functionTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          returnType,
-          name,
-          typeParameters,
-          parameters,
-          semicolon);
-    } else if (type == TokenType.OPEN_PAREN) {
-      FormalParameterList parameters = _parseFormalParameterListUnchecked();
-      _validateFormalParameterList(parameters);
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.functionTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          returnType,
-          name,
-          typeParameters,
-          parameters,
-          semicolon);
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
-      // Recovery: At the very least we should skip to the start of the next
-      // valid compilation unit member, allowing for the possibility of finding
-      // the typedef parameters before that point.
-      return astFactory.functionTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          returnType,
-          name,
-          typeParameters,
-          astFactory.formalParameterList(
-              _createSyntheticToken(TokenType.OPEN_PAREN),
-              null,
-              null,
-              null,
-              _createSyntheticToken(TokenType.CLOSE_PAREN)),
-          _createSyntheticToken(TokenType.SEMICOLON));
-    }
-  }
-
-  /// Parse the generic method or function's type parameters.
-  ///
-  /// For backwards compatibility this can optionally use comments.
-  /// See [parseGenericMethodComments].
-  TypeParameterList _parseGenericMethodTypeParameters() {
-    if (_matches(TokenType.LT)) {
-      return parseTypeParameterList();
-    }
-    return null;
-  }
-
-  /// Parse a library name. The [missingNameError] is the error code to be used
-  /// if the library name is missing. The [missingNameToken] is the token
-  /// associated with the error produced if the library name is missing. Return
-  /// the library name that was parsed.
-  ///
-  ///     libraryName ::=
-  ///         libraryIdentifier
-  LibraryIdentifier _parseLibraryName(
-      ParserErrorCode missingNameError, Token missingNameToken) {
-    if (_matchesIdentifier()) {
-      return parseLibraryIdentifier();
-    } else if (_matches(TokenType.STRING)) {
-      // Recovery: This should be extended to handle arbitrary tokens until we
-      // can find a token that can start a compilation unit member.
-      StringLiteral string = parseStringLiteral();
-      _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string);
-    } else {
-      _reportErrorForToken(missingNameError, missingNameToken);
-    }
-    return astFactory
-        .libraryIdentifier(<SimpleIdentifier>[createSyntheticIdentifier()]);
-  }
-
-  /// Parse a method declaration. The [commentAndMetadata] is the documentation
-  /// comment and metadata to be associated with the declaration. The
-  /// [externalKeyword] is the 'external' token. The [staticKeyword] is the
-  /// static keyword, or `null` if the getter is not static. The [returnType] is
-  /// the return type of the method. The [name] is the name of the method. The
-  /// [parameters] is the parameters to the method. Return the method
-  /// declaration that was parsed.
-  ///
-  ///     functionDeclaration ::=
-  ///         ('external' 'static'?)? functionSignature functionBody
-  ///       | 'external'? functionSignature ';'
-  MethodDeclaration _parseMethodDeclarationAfterParameters(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      Token staticKeyword,
-      TypeAnnotation returnType,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters) {
-    FunctionBody body = parseFunctionBody(
-        externalKeyword != null || staticKeyword == null,
-        ParserErrorCode.MISSING_FUNCTION_BODY,
-        false);
-    if (externalKeyword != null) {
-      if (body is! EmptyFunctionBody) {
-        _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body);
-      }
-    } else if (staticKeyword != null) {
-      if (body is EmptyFunctionBody && _parseFunctionBodies) {
-        _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body);
-      }
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        null,
-        null,
-        name,
-        typeParameters,
-        parameters,
-        body);
-  }
-
-  /// Parse a method declaration. The [commentAndMetadata] is the documentation
-  /// comment and metadata to be associated with the declaration. The
-  /// [externalKeyword] is the 'external' token. The [staticKeyword] is the
-  /// static keyword, or `null` if the getter is not static. The [returnType] is
-  /// the return type of the method. Return the method declaration that was
-  /// parsed.
-  ///
-  ///     functionDeclaration ::=
-  ///         'external'? 'static'? functionSignature functionBody
-  ///       | 'external'? functionSignature ';'
-  MethodDeclaration _parseMethodDeclarationAfterReturnType(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      Token staticKeyword,
-      TypeAnnotation returnType) {
-    SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    FormalParameterList parameters;
-    TokenType type = _currentToken.type;
-    // TODO(brianwilkerson) Figure out why we care what the current token is if
-    // it isn't a paren.
-    if (type != TokenType.OPEN_PAREN &&
-        (type == TokenType.OPEN_CURLY_BRACKET || type == TokenType.FUNCTION)) {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous);
-      parameters = astFactory.formalParameterList(
-          _createSyntheticToken(TokenType.OPEN_PAREN),
-          null,
-          null,
-          null,
-          _createSyntheticToken(TokenType.CLOSE_PAREN));
-    } else {
-      parameters = parseFormalParameterList();
-    }
-    _validateFormalParameterList(parameters);
-    return _parseMethodDeclarationAfterParameters(
-        commentAndMetadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        methodName,
-        typeParameters,
-        parameters);
-  }
-
-  /// Parse a class native clause. Return the native clause that was parsed.
-  ///
-  /// This method assumes that the current token matches `_NATIVE`.
-  ///
-  ///     classNativeClause ::=
-  ///         'native' name
-  NativeClause _parseNativeClause() {
-    Token keyword = getAndAdvance();
-    StringLiteral name = parseStringLiteral();
-    return astFactory.nativeClause(keyword, name);
-  }
-
-  /// Parse an operator declaration starting after the 'operator' keyword. The
-  /// [commentAndMetadata] is the documentation comment and metadata to be
-  /// associated with the declaration. The [externalKeyword] is the 'external'
-  /// token. The [returnType] is the return type that has already been parsed,
-  /// or `null` if there was no return type. The [operatorKeyword] is the
-  /// 'operator' keyword. Return the operator declaration that was parsed.
-  ///
-  ///     operatorDeclaration ::=
-  ///         operatorSignature (';' | functionBody)
-  ///
-  ///     operatorSignature ::=
-  ///         'external'? returnType? 'operator' operator formalParameterList
-  MethodDeclaration _parseOperatorAfterKeyword(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      TypeAnnotation returnType,
-      Token operatorKeyword) {
-    if (!_currentToken.isUserDefinableOperator) {
-      _reportErrorForCurrentToken(
-          _currentToken.type == TokenType.EQ_EQ_EQ
-              ? ParserErrorCode.INVALID_OPERATOR
-              : ParserErrorCode.NON_USER_DEFINABLE_OPERATOR,
-          [_currentToken.lexeme]);
-    }
-    SimpleIdentifier name =
-        astFactory.simpleIdentifier(getAndAdvance(), isDeclaration: true);
-    if (_matches(TokenType.EQ)) {
-      Token previous = _currentToken.previous;
-      if ((_tokenMatches(previous, TokenType.EQ_EQ) ||
-              _tokenMatches(previous, TokenType.BANG_EQ)) &&
-          _currentToken.offset == previous.offset + 2) {
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR,
-            ["${previous.lexeme}${_currentToken.lexeme}"]);
-        _advance();
-      }
-    }
-    FormalParameterList parameters = parseFormalParameterList();
-    _validateFormalParameterList(parameters);
-    FunctionBody body =
-        parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-    if (externalKeyword != null && body is! EmptyFunctionBody) {
-      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY);
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        null,
-        returnType,
-        null,
-        operatorKeyword,
-        name,
-        null,
-        parameters,
-        body);
-  }
-
-  /// Parse a return type if one is given, otherwise return `null` without
-  /// advancing. Return the return type that was parsed.
-  TypeAnnotation _parseOptionalReturnType() {
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.VOID) {
-      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
-        return parseTypeAnnotation(false);
-      }
-      return astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
-    } else if (_matchesIdentifier()) {
-      Token next = _peek();
-      if (keyword != Keyword.GET &&
-          keyword != Keyword.SET &&
-          keyword != Keyword.OPERATOR &&
-          (_tokenMatchesIdentifier(next) ||
-              _tokenMatches(next, TokenType.LT))) {
-        Token afterTypeParameters = _skipTypeParameterList(next);
-        if (afterTypeParameters != null &&
-            _tokenMatches(afterTypeParameters, TokenType.OPEN_PAREN)) {
-          // If the identifier is followed by type parameters and a parenthesis,
-          // then the identifier is the name of a generic method, not a return
-          // type.
-          return null;
-        }
-        return parseTypeAnnotation(false);
-      }
-      Token next2 = next.next;
-      Token next3 = next2.next;
-      if (_tokenMatches(next, TokenType.PERIOD) &&
-          _tokenMatchesIdentifier(next2) &&
-          (_tokenMatchesIdentifier(next3) ||
-              _tokenMatches(next3, TokenType.LT))) {
-        return parseTypeAnnotation(false);
-      }
-    }
-    return null;
-  }
-
-  /// Parse a [TypeArgumentList] if present, otherwise return null.
-  /// This also supports the comment form, if enabled: `/*<T>*/`
-  TypeArgumentList _parseOptionalTypeArguments() {
-    if (_matches(TokenType.LT)) {
-      return parseTypeArgumentList();
-    }
-    return null;
-  }
-
-  /// Parse a part directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the part or part-of directive that
-  /// was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.PART`.
-  ///
-  ///     partDirective ::=
-  ///         metadata 'part' stringLiteral ';'
-  Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) {
-    Token partKeyword = getAndAdvance();
-    StringLiteral partUri = _parseUri();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.partDirective(commentAndMetadata.comment,
-        commentAndMetadata.metadata, partKeyword, partUri, semicolon);
-  }
-
-  /// Parse a part-of directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the part or part-of directive that
-  /// was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.PART] and that
-  /// the following token matches the identifier 'of'.
-  ///
-  ///     partOfDirective ::=
-  ///         metadata 'part' 'of' identifier ';'
-  Directive _parsePartOfDirective(CommentAndMetadata commentAndMetadata) {
-    Token partKeyword = getAndAdvance();
-    Token ofKeyword = getAndAdvance();
-    if (_matches(TokenType.STRING)) {
-      StringLiteral libraryUri = _parseUri();
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.partOfDirective(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          partKeyword,
-          ofKeyword,
-          libraryUri,
-          null,
-          semicolon);
-    }
-    LibraryIdentifier libraryName = _parseLibraryName(
-        ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.partOfDirective(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        partKeyword,
-        ofKeyword,
-        null,
-        libraryName,
-        semicolon);
-  }
-
-  /// Parse a prefixed identifier given that the given [qualifier] was already
-  /// parsed. Return the prefixed identifier that was parsed.
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Identifier _parsePrefixedIdentifierAfterIdentifier(
-      SimpleIdentifier qualifier) {
-    if (!_matches(TokenType.PERIOD)) {
-      return qualifier;
-    }
-    Token period = getAndAdvance();
-    SimpleIdentifier qualified = parseSimpleIdentifier();
-    return astFactory.prefixedIdentifier(qualifier, period, qualified);
-  }
-
-  /// Parse a prefixed identifier. Return the prefixed identifier that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches an identifier.
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Identifier _parsePrefixedIdentifierUnchecked() {
-    return _parsePrefixedIdentifierAfterIdentifier(
-        _parseSimpleIdentifierUnchecked());
-  }
-
-  /// Parse a simple identifier. Return the simple identifier that was parsed.
-  ///
-  /// This method assumes that the current token matches an identifier.
-  ///
-  ///     identifier ::=
-  ///         IDENTIFIER
-  SimpleIdentifier _parseSimpleIdentifierUnchecked(
-      {bool isDeclaration = false}) {
-    String lexeme = _currentToken.lexeme;
-    if ((_inAsync || _inGenerator) && (lexeme == _AWAIT || lexeme == _YIELD)) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
-    }
-    return astFactory.simpleIdentifier(getAndAdvance(),
-        isDeclaration: isDeclaration);
-  }
-
-  /// Parse a list of statements within a switch statement. Return the
-  /// statements that were parsed.
-  ///
-  ///     statements ::=
-  ///         statement*
-  List<Statement> _parseStatementList() {
-    List<Statement> statements = <Statement>[];
-    Token statementStart = _currentToken;
-    TokenType type = _currentToken.type;
-    while (type != TokenType.EOF &&
-        type != TokenType.CLOSE_CURLY_BRACKET &&
-        !isSwitchMember()) {
-      statements.add(parseStatement2());
-      if (identical(_currentToken, statementStart)) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      }
-      statementStart = _currentToken;
-      type = _currentToken.type;
-    }
-    return statements;
-  }
-
-  /// Parse a string literal that contains interpolations. Return the string
-  /// literal that was parsed.
-  ///
-  /// This method assumes that the current token matches either
-  /// [TokenType.STRING_INTERPOLATION_EXPRESSION] or
-  /// [TokenType.STRING_INTERPOLATION_IDENTIFIER].
-  StringInterpolation _parseStringInterpolation(Token string) {
-    List<InterpolationElement> elements = <InterpolationElement>[
-      astFactory.interpolationString(
-          string, computeStringValue(string.lexeme, true, false))
-    ];
-    bool hasMore = true;
-    bool isExpression = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION);
-    while (hasMore) {
-      if (isExpression) {
-        Token openToken = getAndAdvance();
-        bool wasInInitializer = _inInitializer;
-        _inInitializer = false;
-        try {
-          Expression expression = parseExpression2();
-          Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-          elements.add(astFactory.interpolationExpression(
-              openToken, expression, rightBracket));
-        } finally {
-          _inInitializer = wasInInitializer;
-        }
-      } else {
-        Token openToken = getAndAdvance();
-        Expression expression;
-        if (_matchesKeyword(Keyword.THIS)) {
-          expression = astFactory.thisExpression(getAndAdvance());
-        } else {
-          expression = parseSimpleIdentifier();
-        }
-        elements.add(
-            astFactory.interpolationExpression(openToken, expression, null));
-      }
-      if (_matches(TokenType.STRING)) {
-        string = getAndAdvance();
-        isExpression = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION);
-        hasMore =
-            isExpression || _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER);
-        elements.add(astFactory.interpolationString(
-            string, computeStringValue(string.lexeme, false, !hasMore)));
-      } else {
-        hasMore = false;
-      }
-    }
-    return astFactory.stringInterpolation(elements);
-  }
-
-  /// Parse a string literal. Return the string literal that was parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.STRING`.
-  ///
-  ///     stringLiteral ::=
-  ///         MULTI_LINE_STRING+
-  ///       | SINGLE_LINE_STRING+
-  StringLiteral _parseStringLiteralUnchecked() {
-    List<StringLiteral> strings = <StringLiteral>[];
-    do {
-      Token string = getAndAdvance();
-      if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
-          _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
-        strings.add(_parseStringInterpolation(string));
-      } else {
-        strings.add(astFactory.simpleStringLiteral(
-            string, computeStringValue(string.lexeme, true, true)));
-      }
-    } while (_matches(TokenType.STRING));
-    return strings.length == 1
-        ? strings[0]
-        : astFactory.adjacentStrings(strings);
-  }
-
-  /// Parse a type annotation, possibly superseded by a type name in a comment.
-  /// Return the type name that was parsed.
-  ///
-  /// This method assumes that the current token is an identifier.
-  ///
-  ///     type ::=
-  ///         qualified typeArguments?
-  TypeAnnotation _parseTypeAnnotationAfterIdentifier() {
-    return parseTypeAnnotation(false);
-  }
-
-  TypeName _parseTypeName(bool inExpression) {
-    Identifier typeName;
-    if (_matchesIdentifier()) {
-      typeName = _parsePrefixedIdentifierUnchecked();
-    } else if (_matchesKeyword(Keyword.VAR)) {
-      _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME);
-      typeName = astFactory.simpleIdentifier(getAndAdvance());
-    } else {
-      typeName = createSyntheticIdentifier();
-      _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME);
-    }
-    TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-    return astFactory.typeName(typeName, typeArguments);
-  }
-
-  /// Parse a string literal representing a URI. Return the string literal that
-  /// was parsed.
-  StringLiteral _parseUri() {
-    // TODO(brianwilkerson) Should this function also return true for valid
-    // top-level keywords?
-    bool isKeywordAfterUri(Token token) =>
-        token.lexeme == Keyword.AS.lexeme ||
-        token.lexeme == _HIDE ||
-        token.lexeme == _SHOW;
-    TokenType type = _currentToken.type;
-    if (type != TokenType.STRING &&
-        type != TokenType.SEMICOLON &&
-        !isKeywordAfterUri(_currentToken)) {
-      // Attempt to recover in the case where the URI was not enclosed in
-      // quotes.
-      Token token = _currentToken;
-      bool isValidInUri(Token token) {
-        TokenType type = token.type;
-        return type == TokenType.COLON ||
-            type == TokenType.SLASH ||
-            type == TokenType.PERIOD ||
-            type == TokenType.PERIOD_PERIOD ||
-            type == TokenType.PERIOD_PERIOD_PERIOD ||
-            type == TokenType.INT ||
-            type == TokenType.DOUBLE;
-      }
-
-      while ((_tokenMatchesIdentifier(token) && !isKeywordAfterUri(token)) ||
-          isValidInUri(token)) {
-        token = token.next;
-      }
-      if (_tokenMatches(token, TokenType.SEMICOLON) ||
-          isKeywordAfterUri(token)) {
-        Token endToken = token.previous;
-        token = _currentToken;
-        int endOffset = token.end;
-        StringBuffer buffer = StringBuffer();
-        buffer.write(token.lexeme);
-        while (token != endToken) {
-          token = token.next;
-          if (token.offset != endOffset || token.precedingComments != null) {
-            return parseStringLiteral();
-          }
-          buffer.write(token.lexeme);
-          endOffset = token.end;
-        }
-        String value = buffer.toString();
-        Token newToken =
-            StringToken(TokenType.STRING, "'$value'", _currentToken.offset);
-        _reportErrorForToken(
-            ParserErrorCode.NON_STRING_LITERAL_AS_URI, newToken);
-        _currentToken = endToken.next;
-        return astFactory.simpleStringLiteral(newToken, value);
-      }
-    }
-    return parseStringLiteral();
-  }
-
-  /// Parse a variable declaration statement. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration statement, or
-  /// `null` if there is no attempt at parsing the comment and metadata. The
-  /// [keyword] is the token representing the 'final', 'const' or 'var' keyword,
-  /// or `null` if there is no keyword. The [type] is the type of the variables
-  /// in the list. Return the variable declaration statement that was parsed.
-  ///
-  ///     variableDeclarationStatement ::=
-  ///         variableDeclarationList ';'
-  VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(
-      CommentAndMetadata commentAndMetadata,
-      Token keyword,
-      TypeAnnotation type) {
-    VariableDeclarationList variableList =
-        parseVariableDeclarationListAfterType(
-            commentAndMetadata, keyword, type);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.variableDeclarationStatement(variableList, semicolon);
-  }
-
-  /// Return the token that is immediately after the current token. This is
-  /// equivalent to [_peekAt](1).
-  Token _peek() => _currentToken.next;
-
-  /// Return the token that is the given [distance] after the current token,
-  /// where the distance is the number of tokens to look ahead. A distance of
-  /// `0` is the current token, `1` is the next token, etc.
-  Token _peekAt(int distance) {
-    Token token = _currentToken;
-    for (int i = 0; i < distance; i++) {
-      token = token.next;
-    }
-    return token;
-  }
-
-  String _removeGitHubInlineCode(String comment) {
-    int index = 0;
-    while (true) {
-      int beginIndex = comment.indexOf('`', index);
-      if (beginIndex == -1) {
-        break;
-      }
-      int endIndex = comment.indexOf('`', beginIndex + 1);
-      if (endIndex == -1) {
-        break;
-      }
-      comment = comment.substring(0, beginIndex + 1) +
-          ' ' * (endIndex - beginIndex - 1) +
-          comment.substring(endIndex);
-      index = endIndex + 1;
-    }
-    return comment;
-  }
-
-  /// Report the given [error].
-  void _reportError(AnalysisError error) {
-    if (_errorListenerLock != 0) {
-      return;
-    }
-    _errorListener.onError(error);
-  }
-
-  /// Report an error with the given [errorCode] and [arguments] associated with
-  /// the current token.
-  void _reportErrorForCurrentToken(ParserErrorCode errorCode,
-      [List<Object> arguments]) {
-    _reportErrorForToken(errorCode, _currentToken, arguments);
-  }
-
-  /// Report an error with the given [errorCode] and [arguments] associated with
-  /// the given [node].
-  void _reportErrorForNode(ParserErrorCode errorCode, AstNode node,
-      [List<Object> arguments]) {
-    _reportError(
-        AnalysisError(_source, node.offset, node.length, errorCode, arguments));
-  }
-
-  /// Report an error with the given [errorCode] and [arguments] associated with
-  /// the given [token].
-  void _reportErrorForToken(ErrorCode errorCode, Token token,
-      [List<Object> arguments]) {
-    if (token.type == TokenType.EOF) {
-      token = token.previous;
-    }
-    _reportError(AnalysisError(_source, token.offset, math.max(token.length, 1),
-        errorCode, arguments));
-  }
-
-  /// Skips a block with all containing blocks.
-  void _skipBlock() {
-    Token endToken = (_currentToken as BeginToken).endToken;
-    if (endToken == null) {
-      endToken = _currentToken.next;
-      while (!identical(endToken, _currentToken)) {
-        _currentToken = endToken;
-        endToken = _currentToken.next;
-      }
-      _reportErrorForToken(
-          ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, ["}"]);
-    } else {
-      _currentToken = endToken.next;
-    }
-  }
-
-  /// Parse the 'final', 'const', 'var' or type preceding a variable
-  /// declaration, starting at the given token, without actually creating a
-  /// type or changing the current token. Return the token following the type
-  /// that was parsed, or `null` if the given token is not the first token in a
-  /// valid type. The [startToken] is the token at which parsing is to begin.
-  /// Return the token following the type that was parsed.
-  ///
-  /// finalConstVarOrType ::=
-  ///   | 'final' type?
-  ///   | 'const' type?
-  ///   | 'var'
-  ///   | type
-  Token _skipFinalConstVarOrType(Token startToken) {
-    Keyword keyword = startToken.keyword;
-    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
-      Token next = startToken.next;
-      if (_tokenMatchesIdentifier(next)) {
-        Token next2 = next.next;
-        // "Type parameter" or "Type<" or "prefix.Type"
-        if (_tokenMatchesIdentifier(next2) ||
-            _tokenMatches(next2, TokenType.LT) ||
-            _tokenMatches(next2, TokenType.PERIOD)) {
-          return skipTypeName(next);
-        }
-        // "parameter"
-        return next;
-      }
-    } else if (keyword == Keyword.VAR) {
-      return startToken.next;
-    } else if (_tokenMatchesIdentifier(startToken)) {
-      Token next = startToken.next;
-      if (_tokenMatchesIdentifier(next) ||
-          _tokenMatches(next, TokenType.LT) ||
-          _tokenMatchesKeyword(next, Keyword.THIS) ||
-          (_tokenMatches(next, TokenType.PERIOD) &&
-              _tokenMatchesIdentifier(next.next) &&
-              (_tokenMatchesIdentifier(next.next.next) ||
-                  _tokenMatches(next.next.next, TokenType.LT) ||
-                  _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) {
-        return skipTypeAnnotation(startToken);
-      }
-    }
-    return null;
-  }
-
-  /// Parse a list of formal parameters, starting at the [startToken], without
-  /// actually creating a formal parameter list or changing the current token.
-  /// Return the token following the formal parameter list that was parsed, or
-  /// `null` if the given token is not the first token in a valid list of formal
-  /// parameter.
-  ///
-  /// Note that unlike other skip methods, this method uses a heuristic. In the
-  /// worst case, the parameters could be prefixed by metadata, which would
-  /// require us to be able to skip arbitrary expressions. Rather than duplicate
-  /// the logic of most of the parse methods we simply look for something that
-  /// is likely to be a list of parameters and then skip to returning the token
-  /// after the closing parenthesis.
-  ///
-  /// This method must be kept in sync with [parseFormalParameterList].
-  ///
-  ///     formalParameterList ::=
-  ///         '(' ')'
-  ///       | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
-  ///       | '(' optionalFormalParameters ')'
-  ///
-  ///     normalFormalParameters ::=
-  ///         normalFormalParameter (',' normalFormalParameter)*
-  ///
-  ///     optionalFormalParameters ::=
-  ///         optionalPositionalFormalParameters
-  ///       | namedFormalParameters
-  ///
-  ///     optionalPositionalFormalParameters ::=
-  ///         '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
-  ///
-  ///     namedFormalParameters ::=
-  ///         '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
-  Token _skipFormalParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
-      return null;
-    }
-    Token next = startToken.next;
-    if (_tokenMatches(next, TokenType.CLOSE_PAREN)) {
-      return next.next;
-    }
-    //
-    // Look to see whether the token after the open parenthesis is something
-    // that should only occur at the beginning of a parameter list.
-    //
-    if (next.matchesAny(const <TokenType>[
-          TokenType.AT,
-          TokenType.OPEN_SQUARE_BRACKET,
-          TokenType.OPEN_CURLY_BRACKET
-        ]) ||
-        _tokenMatchesKeyword(next, Keyword.VOID) ||
-        (_tokenMatchesIdentifier(next) &&
-            (next.next.matchesAny(
-                const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
-      return _skipPastMatchingToken(startToken);
-    }
-    //
-    // Look to see whether the first parameter is a function typed parameter
-    // without a return type.
-    //
-    if (_tokenMatchesIdentifier(next) &&
-        _tokenMatches(next.next, TokenType.OPEN_PAREN)) {
-      Token afterParameters = _skipFormalParameterList(next.next);
-      if (afterParameters != null &&
-          afterParameters.matchesAny(
-              const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])) {
-        return _skipPastMatchingToken(startToken);
-      }
-    }
-    //
-    // Look to see whether the first parameter has a type or is a function typed
-    // parameter with a return type.
-    //
-    Token afterType = _skipFinalConstVarOrType(next);
-    if (afterType == null) {
-      return null;
-    }
-    if (skipSimpleIdentifier(afterType) == null) {
-      return null;
-    }
-    return _skipPastMatchingToken(startToken);
-  }
-
-  /// If the [startToken] is a begin token with an associated end token, then
-  /// return the token following the end token. Otherwise, return `null`.
-  Token _skipPastMatchingToken(Token startToken) {
-    if (startToken is! BeginToken) {
-      return null;
-    }
-    Token closeParen = (startToken as BeginToken).endToken;
-    if (closeParen == null) {
-      return null;
-    }
-    return closeParen.next;
-  }
-
-  /// Parse a string literal that contains interpolations, starting at the
-  /// [startToken], without actually creating a string literal or changing the
-  /// current token. Return the token following the string literal that was
-  /// parsed, or `null` if the given token is not the first token in a valid
-  /// string literal.
-  ///
-  /// This method must be kept in sync with [parseStringInterpolation].
-  Token _skipStringInterpolation(Token startToken) {
-    Token token = startToken;
-    TokenType type = token.type;
-    while (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
-        type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-      if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
-        token = token.next;
-        type = token.type;
-        //
-        // Rather than verify that the following tokens represent a valid
-        // expression, we simply skip tokens until we reach the end of the
-        // interpolation, being careful to handle nested string literals.
-        //
-        int bracketNestingLevel = 1;
-        while (bracketNestingLevel > 0) {
-          if (type == TokenType.EOF) {
-            return null;
-          } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-            bracketNestingLevel++;
-            token = token.next;
-          } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-            bracketNestingLevel--;
-            token = token.next;
-          } else if (type == TokenType.STRING) {
-            token = skipStringLiteral(token);
-            if (token == null) {
-              return null;
-            }
-          } else {
-            token = token.next;
-          }
-          type = token.type;
-        }
-        token = token.next;
-        type = token.type;
-      } else {
-        token = token.next;
-        if (token.type != TokenType.IDENTIFIER) {
-          return null;
-        }
-        token = token.next;
-      }
-      type = token.type;
-      if (type == TokenType.STRING) {
-        token = token.next;
-        type = token.type;
-      }
-    }
-    return token;
-  }
-
-  /// Parse a list of type parameters, starting at the [startToken], without
-  /// actually creating a type parameter list or changing the current token.
-  /// Return the token following the type parameter list that was parsed, or
-  /// `null` if the given token is not the first token in a valid type parameter
-  /// list.
-  ///
-  /// This method must be kept in sync with [parseTypeParameterList].
-  ///
-  ///     typeParameterList ::=
-  ///         '<' typeParameter (',' typeParameter)* '>'
-  Token _skipTypeParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.LT)) {
-      return null;
-    }
-    //
-    // We can't skip a type parameter because it can be preceded by metadata,
-    // so we just assume that everything before the matching end token is valid.
-    //
-    int depth = 1;
-    Token next = startToken.next;
-    while (depth > 0) {
-      if (_tokenMatches(next, TokenType.EOF)) {
-        return null;
-      } else if (_tokenMatches(next, TokenType.LT)) {
-        depth++;
-      } else if (_tokenMatches(next, TokenType.GT)) {
-        depth--;
-      } else if (_tokenMatches(next, TokenType.GT_EQ)) {
-        if (depth == 1) {
-          Token fakeEquals = Token(TokenType.EQ, next.offset + 2);
-          fakeEquals.setNextWithoutSettingPrevious(next.next);
-          return fakeEquals;
-        }
-        depth--;
-      } else if (_tokenMatches(next, TokenType.GT_GT)) {
-        depth -= 2;
-      } else if (_tokenMatches(next, TokenType.GT_GT_EQ)) {
-        if (depth < 2) {
-          return null;
-        } else if (depth == 2) {
-          Token fakeEquals = Token(TokenType.EQ, next.offset + 2);
-          fakeEquals.setNextWithoutSettingPrevious(next.next);
-          return fakeEquals;
-        }
-        depth -= 2;
-      }
-      next = next.next;
-    }
-    return next;
-  }
-
-  /// Assuming that the current token is an index token ('[]'), split it into
-  /// two tokens ('[' and ']'), leaving the left bracket as the current token.
-  void _splitIndex() {
-    // Split the token into two separate tokens.
-    BeginToken leftBracket = _createToken(
-        _currentToken, TokenType.OPEN_SQUARE_BRACKET,
-        isBegin: true);
-    Token rightBracket =
-        Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1);
-    leftBracket.endToken = rightBracket;
-    rightBracket.setNext(_currentToken.next);
-    leftBracket.setNext(rightBracket);
-    _currentToken.previous.setNext(leftBracket);
-    _currentToken = leftBracket;
-  }
-
-  /// Return `true` if the given [token] has the given [type].
-  bool _tokenMatches(Token token, TokenType type) => token.type == type;
-
-  /// Return `true` if the given [token] is a valid identifier. Valid
-  /// identifiers include built-in identifiers (pseudo-keywords).
-  bool _tokenMatchesIdentifier(Token token) =>
-      _tokenMatches(token, TokenType.IDENTIFIER) ||
-      _tokenMatchesPseudoKeyword(token);
-
-  /// Return `true` if the given [token] is either an identifier or a keyword.
-  bool _tokenMatchesIdentifierOrKeyword(Token token) =>
-      _tokenMatches(token, TokenType.IDENTIFIER) || token.type.isKeyword;
-
-  /// Return `true` if the given [token] matches the given [keyword].
-  bool _tokenMatchesKeyword(Token token, Keyword keyword) =>
-      token.keyword == keyword;
-
-  /// Return `true` if the given [token] matches a pseudo keyword.
-  bool _tokenMatchesPseudoKeyword(Token token) =>
-      token.keyword?.isBuiltInOrPseudo ?? false;
-
-  /// Translate the characters at the given [index] in the given [lexeme],
-  /// appending the translated character to the given [buffer]. The index is
-  /// assumed to be valid.
-  int _translateCharacter(StringBuffer buffer, String lexeme, int index) {
-    int currentChar = lexeme.codeUnitAt(index);
-    if (currentChar != 0x5C) {
-      buffer.writeCharCode(currentChar);
-      return index + 1;
-    }
-    //
-    // We have found an escape sequence, so we parse the string to determine
-    // what kind of escape sequence and what character to add to the builder.
-    //
-    int length = lexeme.length;
-    int currentIndex = index + 1;
-    if (currentIndex >= length) {
-      // Illegal escape sequence: no char after escape.
-      // This cannot actually happen because it would require the escape
-      // character to be the last character in the string, but if it were it
-      // would escape the closing quote, leaving the string unclosed.
-      // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE);
-      return length;
-    }
-    currentChar = lexeme.codeUnitAt(currentIndex);
-    if (currentChar == 0x6E) {
-      buffer.writeCharCode(0xA);
-      // newline
-    } else if (currentChar == 0x72) {
-      buffer.writeCharCode(0xD);
-      // carriage return
-    } else if (currentChar == 0x66) {
-      buffer.writeCharCode(0xC);
-      // form feed
-    } else if (currentChar == 0x62) {
-      buffer.writeCharCode(0x8);
-      // backspace
-    } else if (currentChar == 0x74) {
-      buffer.writeCharCode(0x9);
-      // tab
-    } else if (currentChar == 0x76) {
-      buffer.writeCharCode(0xB);
-      // vertical tab
-    } else if (currentChar == 0x78) {
-      if (currentIndex + 2 >= length) {
-        // Illegal escape sequence: not enough hex digits
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
-        return length;
-      }
-      int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
-      int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
-      if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) {
-        // Illegal escape sequence: invalid hex digit
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
-      } else {
-        int charCode = (Character.digit(firstDigit, 16) << 4) +
-            Character.digit(secondDigit, 16);
-        buffer.writeCharCode(charCode);
-      }
-      return currentIndex + 3;
-    } else if (currentChar == 0x75) {
-      currentIndex++;
-      if (currentIndex >= length) {
-        // Illegal escape sequence: not enough hex digits
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-        return length;
-      }
-      currentChar = lexeme.codeUnitAt(currentIndex);
-      if (currentChar == 0x7B) {
-        currentIndex++;
-        if (currentIndex >= length) {
-          // Illegal escape sequence: incomplete escape
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-          return length;
-        }
-        currentChar = lexeme.codeUnitAt(currentIndex);
-        int digitCount = 0;
-        int value = 0;
-        while (currentChar != 0x7D) {
-          if (!_isHexDigit(currentChar)) {
-            // Illegal escape sequence: invalid hex digit
-            _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-            currentIndex++;
-            while (currentIndex < length &&
-                lexeme.codeUnitAt(currentIndex) != 0x7D) {
-              currentIndex++;
-            }
-            return currentIndex + 1;
-          }
-          digitCount++;
-          value = (value << 4) + Character.digit(currentChar, 16);
-          currentIndex++;
-          if (currentIndex >= length) {
-            // Illegal escape sequence: incomplete escape
-            _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-            return length;
-          }
-          currentChar = lexeme.codeUnitAt(currentIndex);
-        }
-        if (digitCount < 1 || digitCount > 6) {
-          // Illegal escape sequence: not enough or too many hex digits
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-        }
-        _appendCodePoint(buffer, lexeme, value, index, currentIndex);
-        return currentIndex + 1;
-      } else {
-        if (currentIndex + 3 >= length) {
-          // Illegal escape sequence: not enough hex digits
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-          return length;
-        }
-        int firstDigit = currentChar;
-        int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
-        int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
-        int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
-        if (!_isHexDigit(firstDigit) ||
-            !_isHexDigit(secondDigit) ||
-            !_isHexDigit(thirdDigit) ||
-            !_isHexDigit(fourthDigit)) {
-          // Illegal escape sequence: invalid hex digits
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-        } else {
-          _appendCodePoint(
-              buffer,
-              lexeme,
-              (((((Character.digit(firstDigit, 16) << 4) +
-                                  Character.digit(secondDigit, 16)) <<
-                              4) +
-                          Character.digit(thirdDigit, 16)) <<
-                      4) +
-                  Character.digit(fourthDigit, 16),
-              index,
-              currentIndex + 3);
-        }
-        return currentIndex + 4;
-      }
-    } else {
-      buffer.writeCharCode(currentChar);
-    }
-    return currentIndex + 1;
-  }
-
-  /// Decrements the error reporting lock level. If level is more than `0`, then
-  /// [reportError] wont report any error.
-  void _unlockErrorListener() {
-    if (_errorListenerLock == 0) {
-      throw StateError("Attempt to unlock not locked error listener.");
-    }
-    _errorListenerLock--;
-  }
-
-  /// Validate that the given [parameterList] does not contain any field
-  /// initializers.
-  void _validateFormalParameterList(FormalParameterList parameterList) {
-    for (FormalParameter parameter in parameterList.parameters) {
-      if (parameter is FieldFormalParameter) {
-        _reportErrorForNode(
-            ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
-            parameter.identifier);
-      }
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a class and
-  /// return the 'abstract' keyword if there is one.
-  Token _validateModifiersForClass(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword);
-    }
-    return modifiers.abstractKeyword;
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a
-  /// constructor and return the 'const' keyword if there is one.
-  Token _validateModifiersForConstructor(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abstractKeyword);
-    }
-    if (modifiers.covariantKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.COVARIANT_CONSTRUCTOR, modifiers.covariantKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword);
-    }
-    if (modifiers.staticKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifiers.varKeyword);
-    }
-    Token externalKeyword = modifiers.externalKeyword;
-    Token constKeyword = modifiers.constKeyword;
-    Token factoryKeyword = modifiers.factoryKeyword;
-    if (externalKeyword != null &&
-        constKeyword != null &&
-        constKeyword.offset < externalKeyword.offset) {
-      _reportErrorForToken(
-          ParserErrorCode.MODIFIER_OUT_OF_ORDER, externalKeyword);
-    }
-    if (externalKeyword != null &&
-        factoryKeyword != null &&
-        factoryKeyword.offset < externalKeyword.offset) {
-      _reportErrorForToken(
-          ParserErrorCode.MODIFIER_OUT_OF_ORDER, externalKeyword);
-    }
-    return constKeyword;
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for an enum and
-  /// return the 'abstract' keyword if there is one.
-  void _validateModifiersForEnum(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyword);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a field and
-  /// return the 'final', 'const' or 'var' keyword if there is one.
-  Token _validateModifiersForField(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
-    }
-    Token staticKeyword = modifiers.staticKeyword;
-    Token covariantKeyword = modifiers.covariantKeyword;
-    Token constKeyword = modifiers.constKeyword;
-    Token finalKeyword = modifiers.finalKeyword;
-    Token varKeyword = modifiers.varKeyword;
-    if (constKeyword != null) {
-      if (covariantKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, covariantKeyword);
-      }
-      if (finalKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
-      }
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.MODIFIER_OUT_OF_ORDER, varKeyword);
-      }
-      if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, staticKeyword);
-      }
-    } else if (finalKeyword != null) {
-      if (covariantKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.FINAL_AND_COVARIANT, covariantKeyword);
-      }
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
-      }
-      if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, staticKeyword);
-      }
-    } else if (varKeyword != null) {
-      if (staticKeyword != null && varKeyword.offset < staticKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, staticKeyword);
-      }
-      if (covariantKeyword != null &&
-          varKeyword.offset < covariantKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, covariantKeyword);
-      }
-    }
-    if (covariantKeyword != null && staticKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.COVARIANT_AND_STATIC, staticKeyword);
-    }
-    return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a local
-  /// function.
-  void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null ||
-        modifiers.constKeyword != null ||
-        modifiers.externalKeyword != null ||
-        modifiers.factoryKeyword != null ||
-        modifiers.finalKeyword != null ||
-        modifiers.staticKeyword != null ||
-        modifiers.varKeyword != null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a getter,
-  /// setter, or method.
-  void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
-    }
-    if (modifiers.covariantKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.COVARIANT_MEMBER, modifiers.covariantKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
-    }
-    Token externalKeyword = modifiers.externalKeyword;
-    Token staticKeyword = modifiers.staticKeyword;
-    if (externalKeyword != null &&
-        staticKeyword != null &&
-        staticKeyword.offset < externalKeyword.offset) {
-      _reportErrorForToken(
-          ParserErrorCode.MODIFIER_OUT_OF_ORDER, externalKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a getter,
-  /// setter, or method.
-  void _validateModifiersForOperator(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
-    }
-    if (modifiers.staticKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a top-level
-  /// declaration.
-  void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
-    if (modifiers.covariantKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION,
-          modifiers.covariantKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION,
-          modifiers.factoryKeyword);
-    }
-    if (modifiers.staticKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION,
-          modifiers.staticKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a top-level
-  /// function.
-  void _validateModifiersForTopLevelFunction(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a field and
-  /// return the 'final', 'const' or 'var' keyword if there is one.
-  Token _validateModifiersForTopLevelVariable(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
-    }
-    Token constKeyword = modifiers.constKeyword;
-    Token finalKeyword = modifiers.finalKeyword;
-    Token varKeyword = modifiers.varKeyword;
-    if (constKeyword != null) {
-      if (finalKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
-      }
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.MODIFIER_OUT_OF_ORDER, varKeyword);
-      }
-    } else if (finalKeyword != null) {
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
-      }
-    }
-    return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a class and
-  /// return the 'abstract' keyword if there is one.
-  void _validateModifiersForTypedef(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword);
-    }
-  }
+  Expression parseUnaryExpression() => parseExpression2();
 }
-
-/// Instances of this class are thrown when the parser detects that AST has
-/// too many nested expressions to be parsed safely and avoid possibility of
-/// [StackOverflowError] in the parser or during later analysis.
-class _TooDeepTreeError {}
diff --git a/pkg/analyzer/lib/src/generated/parser_fasta.dart b/pkg/analyzer/lib/src/generated/parser_fasta.dart
deleted file mode 100644
index c43c75f..0000000
--- a/pkg/analyzer/lib/src/generated/parser_fasta.dart
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of analyzer.parser;
-
-/// Proxy implementation of the analyzer parser, implemented in terms of the
-/// Fasta parser.
-abstract class ParserAdapter implements Parser {
-  @override
-  Token currentToken;
-
-  /// The fasta parser being wrapped.
-  final fasta.Parser fastaParser;
-
-  /// The builder which creates the analyzer AST data structures
-  /// based on the Fasta parser.
-  final AstBuilder astBuilder;
-
-  ParserAdapter(this.currentToken, ErrorReporter errorReporter, Uri fileUri,
-      FeatureSet featureSet,
-      {bool allowNativeClause = false})
-      : fastaParser = fasta.Parser(null),
-        astBuilder = AstBuilder(errorReporter, fileUri, true, featureSet) {
-    fastaParser.listener = astBuilder;
-    astBuilder.parser = fastaParser;
-    astBuilder.allowNativeClause = allowNativeClause;
-  }
-
-  @override
-  set allowNativeClause(bool value) {
-    astBuilder.allowNativeClause = value;
-  }
-
-  @override
-  bool get enableOptionalNewAndConst => false;
-
-  @override
-  set enableOptionalNewAndConst(bool enable) {}
-
-  @override
-  set enableSetLiterals(bool value) {
-    // TODO(danrubel): Remove this method once the reference to this flag
-    // has been removed from dartfmt.
-  }
-
-  @override
-  set parseFunctionBodies(bool parseFunctionBodies) {
-    astBuilder.parseFunctionBodies = parseFunctionBodies;
-  }
-
-  @override
-  set parseGenericMethods(_) {}
-
-  /// Append the given token to the end of the token stream,
-  /// and update the token's offset.
-  void appendToken(Token token, Token newToken) {
-    while (!token.next.isEof) {
-      token = token.next;
-    }
-    newToken
-      ..offset = token.end
-      ..setNext(token.next);
-    token.setNext(newToken);
-  }
-
-  @override
-  Expression parseAdditiveExpression() => parseExpression2();
-
-  @override
-  Annotation parseAnnotation() {
-    currentToken = fastaParser
-        .parseMetadata(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Annotation;
-  }
-
-  @override
-  Expression parseArgument() {
-    currentToken = SimpleToken(TokenType.OPEN_PAREN, 0)..setNext(currentToken);
-    appendToken(currentToken, SimpleToken(TokenType.CLOSE_PAREN, 0));
-    currentToken = fastaParser
-        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    var invocation = astBuilder.pop() as MethodInvocation;
-    return invocation.argumentList.arguments[0];
-  }
-
-  @override
-  ArgumentList parseArgumentList() {
-    currentToken = fastaParser
-        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    var result = astBuilder.pop();
-    return result is MethodInvocation
-        ? result.argumentList
-        : result as ArgumentList;
-  }
-
-  @override
-  Expression parseAssignableExpression(bool primaryAllowed) =>
-      parseExpression2();
-
-  @override
-  Expression parseBitwiseAndExpression() => parseExpression2();
-
-  @override
-  Expression parseBitwiseOrExpression() => parseExpression2();
-
-  @override
-  Expression parseBitwiseXorExpression() => parseExpression2();
-
-  @override
-  ClassMember parseClassMember(String className) {
-    astBuilder.classDeclaration = astFactory.classDeclaration(
-      null,
-      null,
-      null,
-      Token(Keyword.CLASS, 0),
-      astFactory.simpleIdentifier(
-          fasta.StringToken.fromString(TokenType.IDENTIFIER, className, 6)),
-      null,
-      null,
-      null,
-      null,
-      null /* leftBracket */,
-      <ClassMember>[],
-      null /* rightBracket */,
-    ) as ClassDeclarationImpl;
-    // TODO(danrubel): disambiguate between class and mixin
-    currentToken = fastaParser.parseClassMember(currentToken, className);
-    //currentToken = fastaParser.parseMixinMember(currentToken);
-    ClassDeclaration declaration = astBuilder.classDeclaration;
-    astBuilder.classDeclaration = null;
-    return declaration.members.isNotEmpty ? declaration.members[0] : null;
-  }
-
-  @override
-  List<Combinator> parseCombinators() {
-    currentToken = fastaParser
-        .parseCombinatorStar(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as List<Combinator>;
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit(Token token) {
-    currentToken = token;
-    return parseCompilationUnit2();
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit2() {
-    currentToken = fastaParser.parseUnit(currentToken);
-    return astBuilder.pop() as CompilationUnit;
-  }
-
-  @override
-  Expression parseConditionalExpression() => parseExpression2();
-
-  @override
-  Configuration parseConfiguration() {
-    currentToken = fastaParser
-        .parseConditionalUri(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Configuration;
-  }
-
-  @override
-  Expression parseConstExpression() => parseExpression2();
-
-  @override
-  CompilationUnit parseDirectives(Token token) {
-    currentToken = token;
-    return parseDirectives2();
-  }
-
-  @override
-  CompilationUnit parseDirectives2() {
-    currentToken = fastaParser.parseDirectives(currentToken);
-    return astBuilder.pop() as CompilationUnit;
-  }
-
-  @override
-  DottedName parseDottedName() {
-    currentToken = fastaParser
-        .parseDottedName(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as DottedName;
-  }
-
-  @override
-  Expression parseEqualityExpression() => parseExpression2();
-
-  @override
-  Expression parseExpression(Token token) {
-    currentToken = token;
-    return parseExpression2();
-  }
-
-  @override
-  Expression parseExpression2() {
-    currentToken = fastaParser
-        .parseExpression(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Expression;
-  }
-
-  @override
-  Expression parseExpressionWithoutCascade() => parseExpression2();
-
-  @override
-  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
-    currentToken = fastaParser
-        .parseFormalParametersRequiredOpt(
-            fastaParser.syntheticPreviousToken(currentToken),
-            inFunctionType
-                ? fasta.MemberKind.GeneralizedFunctionType
-                : fasta.MemberKind.NonStaticMethod)
-        .next;
-    return astBuilder.pop() as FormalParameterList;
-  }
-
-  @override
-  FunctionBody parseFunctionBody(
-      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
-    currentToken = fastaParser.parseAsyncModifierOpt(
-        fastaParser.syntheticPreviousToken(currentToken));
-    currentToken =
-        fastaParser.parseFunctionBody(currentToken, inExpression, mayBeEmpty);
-    return astBuilder.pop() as FunctionBody;
-  }
-
-  @override
-  FunctionExpression parseFunctionExpression() =>
-      parseExpression2() as FunctionExpression;
-
-  @override
-  Expression parseLogicalAndExpression() => parseExpression2();
-
-  @override
-  Expression parseLogicalOrExpression() => parseExpression2();
-
-  @override
-  Expression parseMultiplicativeExpression() => parseExpression2();
-
-  @override
-  InstanceCreationExpression parseNewExpression() =>
-      parseExpression2() as InstanceCreationExpression;
-
-  @override
-  Expression parsePostfixExpression() => parseExpression2();
-
-  @override
-  Identifier parsePrefixedIdentifier() => parseExpression2() as Identifier;
-
-  @override
-  Expression parsePrimaryExpression() {
-    currentToken = fastaParser
-        .parsePrimary(fastaParser.syntheticPreviousToken(currentToken),
-            fasta.IdentifierContext.expression)
-        .next;
-    return astBuilder.pop() as Expression;
-  }
-
-  @override
-  Expression parseRelationalExpression() => parseExpression2();
-
-  @override
-  Expression parseRethrowExpression() => parseExpression2();
-
-  @override
-  Expression parseShiftExpression() => parseExpression2();
-
-  @override
-  SimpleIdentifier parseSimpleIdentifier(
-          {bool allowKeyword = false, bool isDeclaration = false}) =>
-      parseExpression2() as SimpleIdentifier;
-
-  @override
-  Statement parseStatement(Token token) {
-    currentToken = token;
-    return parseStatement2();
-  }
-
-  @override
-  Statement parseStatement2() {
-    currentToken = fastaParser
-        .parseStatement(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Statement;
-  }
-
-  @override
-  StringLiteral parseStringLiteral() => parseExpression2() as StringLiteral;
-
-  @override
-  SymbolLiteral parseSymbolLiteral() => parseExpression2() as SymbolLiteral;
-
-  @override
-  Expression parseThrowExpression() => parseExpression2();
-
-  @override
-  Expression parseThrowExpressionWithoutCascade() => parseExpression2();
-
-  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
-    currentToken = fastaParser.parseTopLevelDeclaration(currentToken);
-    return (isDirective ? astBuilder.directives : astBuilder.declarations)
-        .removeLast();
-  }
-
-  @override
-  TypeAnnotation parseTypeAnnotation(bool inExpression) {
-    Token previous = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeType(previous, true, !inExpression)
-        .parseType(previous, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeAnnotation;
-  }
-
-  @override
-  TypeArgumentList parseTypeArgumentList() {
-    Token previous = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeTypeParamOrArg(previous)
-        .parseArguments(previous, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeArgumentList;
-  }
-
-  @override
-  TypeName parseTypeName(bool inExpression) {
-    Token previous = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeType(previous, true, !inExpression)
-        .parseType(previous, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeName;
-  }
-
-  @override
-  TypeParameter parseTypeParameter() {
-    currentToken = SyntheticBeginToken(TokenType.LT, 0)
-      ..endGroup = SyntheticToken(TokenType.GT, 0)
-      ..setNext(currentToken);
-    appendToken(currentToken, currentToken.endGroup);
-    TypeParameterList typeParams = parseTypeParameterList();
-    return typeParams.typeParameters[0];
-  }
-
-  @override
-  TypeParameterList parseTypeParameterList() {
-    Token token = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeTypeParamOrArg(token, true)
-        .parseVariables(token, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeParameterList;
-  }
-
-  @override
-  Expression parseUnaryExpression() => parseExpression2();
-}
-
-/// Replacement parser based on Fasta.
-class _Parser2 extends ParserAdapter {
-  /// The source being parsed.
-  @override
-  final Source _source;
-
-  @override
-  bool enableUriInPartOf = true;
-
-  factory _Parser2(
-      Source source, AnalysisErrorListener errorListener, FeatureSet featureSet,
-      {bool allowNativeClause = false}) {
-    var errorReporter = ErrorReporter(
-      errorListener,
-      source,
-      isNonNullableByDefault: featureSet.isEnabled(Feature.non_nullable),
-    );
-    return _Parser2._(source, errorReporter, source.uri, featureSet,
-        allowNativeClause: allowNativeClause);
-  }
-
-  _Parser2._(this._source, ErrorReporter errorReporter, Uri fileUri,
-      FeatureSet featureSet, {bool allowNativeClause = false})
-      : super(null, errorReporter, fileUri, featureSet,
-            allowNativeClause: allowNativeClause);
-
-  @override
-  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analyzer/lib/src/summary2/apply_resolution.dart b/pkg/analyzer/lib/src/summary2/apply_resolution.dart
index 7c6d20e..ce90149 100644
--- a/pkg/analyzer/lib/src/summary2/apply_resolution.dart
+++ b/pkg/analyzer/lib/src/summary2/apply_resolution.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:math';
+
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -11,6 +13,7 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/exception/exception.dart';
 import 'package:analyzer/src/summary2/ast_binary_tag.dart';
 import 'package:analyzer/src/summary2/bundle_reader.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
@@ -143,12 +146,25 @@
     element.isSimplyBounded = _resolution.readByte() != 0;
     _enclosingElements.add(element);
 
-    node.typeParameters?.accept(this);
-    node.extendsClause?.accept(this);
-    node.nativeClause?.accept(this);
-    node.withClause?.accept(this);
-    node.implementsClause?.accept(this);
-    _namedCompilationUnitMember(node);
+    try {
+      node.typeParameters?.accept(this);
+      node.extendsClause?.accept(this);
+      node.nativeClause?.accept(this);
+      node.withClause?.accept(this);
+      node.implementsClause?.accept(this);
+      _namedCompilationUnitMember(node);
+    } catch (e, stackTrace) {
+      // TODO(scheglov) Remove after fixing http://dartbug.com/44449
+      var headerStr = _astCodeBeforeMarkerOrMaxLength(node, '{', 1000);
+      throw CaughtExceptionWithFiles(e, stackTrace, {
+        'state': '''
+element: ${element.reference}
+header: $headerStr
+resolution.bytes.length: ${_resolution.bytes.length}
+resolution.byteOffset: ${_resolution.byteOffset}
+''',
+      });
+    }
 
     _enclosingElements.removeLast();
   }
@@ -625,16 +641,29 @@
     _enclosingElements.add(element.enclosingElement);
     _enclosingElements.add(element);
 
-    node.typeParameters?.accept(this);
-    node.returnType?.accept(this);
-    node.parameters?.accept(this);
-    node.metadata?.accept(this);
+    try {
+      node.typeParameters?.accept(this);
+      node.returnType?.accept(this);
+      node.parameters?.accept(this);
+      node.metadata?.accept(this);
 
-    element.returnType = _nextType();
-    _setTopLevelInferenceError(element);
-    if (element is MethodElementImpl) {
-      element.isOperatorEqualWithParameterTypeFromObject =
-          _resolution.readByte() != 0;
+      element.returnType = _nextType();
+      _setTopLevelInferenceError(element);
+      if (element is MethodElementImpl) {
+        element.isOperatorEqualWithParameterTypeFromObject =
+            _resolution.readByte() != 0;
+      }
+    } catch (e, stackTrace) {
+      // TODO(scheglov) Remove after fixing http://dartbug.com/44449
+      var headerStr = _astCodeBeforeMarkerOrMaxLength(node, '{', 1000);
+      throw CaughtExceptionWithFiles(e, stackTrace, {
+        'state': '''
+element: ${element.reference}
+header: $headerStr
+resolution.bytes.length: ${_resolution.bytes.length}
+resolution.byteOffset: ${_resolution.byteOffset}
+''',
+      });
     }
 
     _enclosingElements.removeLast();
@@ -1180,6 +1209,17 @@
     node.uri.accept(this);
   }
 
+  /// TODO(scheglov) Remove after fixing http://dartbug.com/44449
+  static String _astCodeBeforeMarkerOrMaxLength(
+      AstNode node, String marker, int maxLength) {
+    var nodeStr = '$node';
+    var indexOfBody = nodeStr.indexOf(marker);
+    if (indexOfBody == -1) {
+      indexOfBody = min(maxLength, nodeStr.length);
+    }
+    return nodeStr.substring(0, indexOfBody);
+  }
+
   static Variance _decodeVariance(int encoding) {
     if (encoding == 0) {
       return null;
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 1b6e4b4..5b56415 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -585,6 +585,12 @@
     this._byteOffset,
   );
 
+  /// TODO(scheglov) Remove after fixing http://dartbug.com/44449
+  int get byteOffset => _byteOffset;
+
+  /// TODO(scheglov) Remove after fixing http://dartbug.com/44449
+  Uint8List get bytes => _unitReader._resolutionReader.bytes;
+
   Element nextElement() {
     var memberFlags = readByte();
     var element = _readRawElement();
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index ba3b7ed..6894bca 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -943,7 +943,6 @@
         source,
         listener,
         featureSet: featureSet,
-        useFasta: true,
       ).parseCompilationUnit(tokens);
     }
     return _unit;
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 34b6b84..05d5f54 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -4,8 +4,6 @@
 
 import 'package:_fe_analyzer_shared/src/parser/async_modifier.dart';
 import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
-import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'
-    show ErrorToken;
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ScannerConfiguration, ScannerResult, scanString;
@@ -17,11 +15,9 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart' show ErrorReporter;
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/fasta/ast_builder.dart';
-import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/string_source.dart';
 import 'package:pub_semver/src/version.dart';
@@ -29,12 +25,13 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../util/ast_type_matchers.dart';
-import 'parser_fasta_listener.dart';
 import 'parser_test.dart';
 import 'test_support.dart';
 
 main() {
   defineReflectiveSuite(() {
+    // TODO(srawlins): Move each of these test classes into [parser_test.dart];
+    // merge with mixins, as each mixin is only used once now; remove this file.
     defineReflectiveTests(ClassMemberParserTest_Fasta);
     defineReflectiveTests(ExtensionMethodsParserTest_Fasta);
     defineReflectiveTests(CollectionLiteralParserTest);
@@ -1190,7 +1187,6 @@
   }
 }
 
-/// Tests of the fasta parser based on [ErrorParserTest].
 @reflectiveTest
 class ErrorParserTest_Fasta extends FastaParserTestCase
     with ErrorParserTestMixin {
@@ -1905,13 +1901,10 @@
   }
 
   @override
-  GatheringErrorListener get listener => _parserProxy._errorListener;
+  GatheringErrorListener get listener => _parserProxy.errorListener;
 
   @override
-  analyzer.Parser get parser => _parserProxy;
-
-  @override
-  bool get usingFastaParser => true;
+  ParserProxy get parser => _parserProxy;
 
   void assertErrors({List<ErrorCode> codes, List<ExpectedError> errors}) {
     if (codes != null) {
@@ -1927,13 +1920,13 @@
 
   @override
   void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
-    _parserProxy._errorListener.assertErrorsWithCodes(
+    _parserProxy.errorListener.assertErrorsWithCodes(
         _toFastaGeneratedAnalyzerErrorCodes(expectedErrorCodes));
   }
 
   @override
   void assertNoErrors() {
-    _parserProxy._errorListener.assertNoErrors();
+    _parserProxy.errorListener.assertNoErrors();
   }
 
   @override
@@ -3508,214 +3501,6 @@
   }
 }
 
-/// Proxy implementation of the analyzer parser, implemented in terms of the
-/// Fasta parser.
-///
-/// This allows many of the analyzer parser tests to be run on Fasta, even if
-/// they call into the analyzer parser class directly.
-class ParserProxy extends analyzer.ParserAdapter {
-  /// The error listener to which scanner and parser errors will be reported.
-  final GatheringErrorListener _errorListener;
-
-  ForwardingTestListener _eventListener;
-
-  final int expectedEndOffset;
-
-  /// Creates a [ParserProxy] which is prepared to begin parsing at the given
-  /// Fasta token.
-  factory ParserProxy(analyzer.Token firstToken, FeatureSet featureSet,
-      {bool allowNativeClause = false, int expectedEndOffset}) {
-    TestSource source = TestSource();
-    var errorListener = GatheringErrorListener(checkRanges: true);
-    var errorReporter = ErrorReporter(
-      errorListener,
-      source,
-      isNonNullableByDefault: false,
-    );
-    return ParserProxy._(
-        firstToken, errorReporter, null, errorListener, featureSet,
-        allowNativeClause: allowNativeClause,
-        expectedEndOffset: expectedEndOffset);
-  }
-
-  ParserProxy._(analyzer.Token firstToken, ErrorReporter errorReporter,
-      Uri fileUri, this._errorListener, FeatureSet featureSet,
-      {bool allowNativeClause = false, this.expectedEndOffset})
-      : super(firstToken, errorReporter, fileUri, featureSet,
-            allowNativeClause: allowNativeClause) {
-    _eventListener = ForwardingTestListener(astBuilder);
-    fastaParser.listener = _eventListener;
-  }
-
-  @override
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
-  @override
-  Annotation parseAnnotation() {
-    return _run('MetadataStar', () => super.parseAnnotation());
-  }
-
-  @override
-  ArgumentList parseArgumentList() {
-    return _run('unspecified', () => super.parseArgumentList());
-  }
-
-  @override
-  ClassMember parseClassMember(String className) {
-    return _run('ClassOrMixinBody', () => super.parseClassMember(className));
-  }
-
-  @override
-  List<Combinator> parseCombinators() {
-    return _run('Import', () => super.parseCombinators());
-  }
-
-  @override
-  List<CommentReference> parseCommentReferences(
-      List<DocumentationCommentToken> tokens) {
-    for (int index = 0; index < tokens.length - 1; ++index) {
-      analyzer.Token next = tokens[index].next;
-      if (next == null) {
-        tokens[index].setNext(tokens[index + 1]);
-      } else {
-        expect(next, tokens[index + 1]);
-      }
-    }
-    expect(tokens[tokens.length - 1].next, isNull);
-    List<CommentReference> references =
-        astBuilder.parseCommentReferences(tokens.first);
-    if (astBuilder.stack.isNotEmpty) {
-      throw 'Expected empty stack, but found:'
-          '\n  ${astBuilder.stack.values.join('\n  ')}';
-    }
-    return references;
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit2() {
-    CompilationUnit result = super.parseCompilationUnit2();
-    expect(currentToken.isEof, isTrue, reason: currentToken.lexeme);
-    expect(astBuilder.stack, hasLength(0));
-    _eventListener.expectEmpty();
-    return result;
-  }
-
-  @override
-  Configuration parseConfiguration() {
-    return _run('ConditionalUris', () => super.parseConfiguration());
-  }
-
-  @override
-  DottedName parseDottedName() {
-    return _run('unspecified', () => super.parseDottedName());
-  }
-
-  @override
-  Expression parseExpression2() {
-    return _run('unspecified', () => super.parseExpression2());
-  }
-
-  @override
-  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
-    return _run('unspecified',
-        () => super.parseFormalParameterList(inFunctionType: inFunctionType));
-  }
-
-  @override
-  FunctionBody parseFunctionBody(
-      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
-    Token lastToken;
-    FunctionBody body = _run('unspecified', () {
-      FunctionBody body =
-          super.parseFunctionBody(mayBeEmpty, emptyErrorCode, inExpression);
-      lastToken = currentToken;
-      currentToken = currentToken.next;
-      return body;
-    });
-    if (!inExpression) {
-      if (![';', '}'].contains(lastToken.lexeme)) {
-        fail('Expected ";" or "}", but found: ${lastToken.lexeme}');
-      }
-    }
-    return body;
-  }
-
-  @override
-  Expression parsePrimaryExpression() {
-    return _run('unspecified', () => super.parsePrimaryExpression());
-  }
-
-  @override
-  Statement parseStatement(Token token) {
-    return _run('unspecified', () => super.parseStatement(token));
-  }
-
-  @override
-  Statement parseStatement2() {
-    return _run('unspecified', () => super.parseStatement2());
-  }
-
-  @override
-  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
-    return _run(
-        'CompilationUnit', () => super.parseTopLevelDeclaration(isDirective));
-  }
-
-  @override
-  TypeAnnotation parseTypeAnnotation(bool inExpression) {
-    return _run('unspecified', () => super.parseTypeAnnotation(inExpression));
-  }
-
-  @override
-  TypeArgumentList parseTypeArgumentList() {
-    return _run('unspecified', () => super.parseTypeArgumentList());
-  }
-
-  @override
-  TypeName parseTypeName(bool inExpression) {
-    return _run('unspecified', () => super.parseTypeName(inExpression));
-  }
-
-  @override
-  TypeParameter parseTypeParameter() {
-    return _run('unspecified', () => super.parseTypeParameter());
-  }
-
-  @override
-  TypeParameterList parseTypeParameterList() {
-    return _run('unspecified', () => super.parseTypeParameterList());
-  }
-
-  /// Runs the specified function and returns the result. It checks the
-  /// enclosing listener events, that the parse consumed all of the tokens, and
-  /// that the result stack is empty.
-  _run(String enclosingEvent, Function() f) {
-    _eventListener.begin(enclosingEvent);
-
-    // Simulate error handling of parseUnit by skipping error tokens
-    // before parsing and reporting them after parsing is complete.
-    Token errorToken = currentToken;
-    currentToken = fastaParser.skipErrorTokens(currentToken);
-    var result = f();
-    fastaParser.reportAllErrorTokens(errorToken);
-
-    _eventListener.end(enclosingEvent);
-
-    String lexeme = currentToken is ErrorToken
-        ? currentToken.runtimeType.toString()
-        : currentToken.lexeme;
-    if (expectedEndOffset == null) {
-      expect(currentToken.isEof, isTrue, reason: lexeme);
-    } else {
-      expect(currentToken.offset, expectedEndOffset, reason: lexeme);
-    }
-    expect(astBuilder.stack, hasLength(0));
-    expect(astBuilder.directives, hasLength(0));
-    expect(astBuilder.declarations, hasLength(0));
-    return result;
-  }
-}
-
 @reflectiveTest
 class RecoveryParserTest_Fasta extends FastaParserTestCase
     with RecoveryParserTestMixin {
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 340cb84..a563d4b 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -4,9 +4,10 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show AbstractScanner;
+import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'
+    show ErrorToken;
 import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
-    show ScannerResult, scanString;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
@@ -15,10 +16,11 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart'
-    show InstanceCreationExpressionImpl;
+    show ClassDeclarationImpl, InstanceCreationExpressionImpl;
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -26,26 +28,12 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../util/ast_type_matchers.dart';
+import 'parser_fasta_listener.dart';
 import 'test_support.dart';
 
 main() {
-  // The fasta parser has a parallel set of tests in parser_fasta_test.dart
-  if (Parser.useFasta) {
-    test('useFasta', () => true);
-    return;
-  }
-
   defineReflectiveSuite(() {
-    defineReflectiveTests(ClassMemberParserTest);
-    defineReflectiveTests(ComplexParserTest);
-    defineReflectiveTests(ErrorParserTest);
-    defineReflectiveTests(ExpressionParserTest);
-    defineReflectiveTests(FormalParameterParserTest);
     defineReflectiveTests(NonErrorParserTest);
-    defineReflectiveTests(RecoveryParserTest);
-    defineReflectiveTests(SimpleParserTest);
-    defineReflectiveTests(StatementParserTest);
-    defineReflectiveTests(TopLevelParserTest);
   });
 }
 
@@ -72,10 +60,7 @@
   /// Get the parser used by the test.
   ///
   /// Caller must first invoke [createParser].
-  Parser get parser;
-
-  /// Flag indicating whether the fasta parser is being used.
-  bool get usingFastaParser;
+  analyzer.Parser get parser;
 
   /// Assert that the number and codes of errors occurred during parsing is the
   /// same as the [expectedErrorCodes].
@@ -228,6 +213,13 @@
   VariableDeclarationList parseVariableDeclarationList(String source);
 }
 
+/// This class just narrows the type of [parser] to [ParserProxy].
+abstract class AbstractParserViaProxyTestCase
+    implements AbstractParserTestCase {
+  @override
+  ParserProxy get parser;
+}
+
 /// Instances of the class `AstValidator` are used to validate the correct
 /// construction of an AST structure.
 class AstValidator extends UnifyingAstVisitor<void> {
@@ -295,18 +287,8 @@
   }
 }
 
-@reflectiveTest
-class ClassMemberParserTest extends ParserTestCase
-    with ClassMemberParserTestMixin {
-  @failingTest
-  @override
-  void test_parseAwaitExpression_inSync() {
-    super.test_parseAwaitExpression_inSync();
-  }
-}
-
 /// Tests which exercise the parser using a class member.
-mixin ClassMemberParserTestMixin implements AbstractParserTestCase {
+mixin ClassMemberParserTestMixin implements AbstractParserViaProxyTestCase {
   void test_parseAwaitExpression_asStatement_inAsync() {
     createParser('m() async { await x; }');
     ClassMember member = parser.parseClassMember('C');
@@ -341,30 +323,16 @@
     createParser('m() { return await x + await y; }');
     MethodDeclaration method = parser.parseClassMember('C');
     expect(method, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 13, 5),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5)
-          ]
-        : [
-            // This test requires better error recovery than we currently have.
-            // In particular, we need to be able to distinguish
-            // between an await expression in the wrong context,
-            // and the use of 'await' as an identifier.
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 5),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 13, 5),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5)
+    ]);
     FunctionBody body = method.body;
     expect(body, isBlockFunctionBody);
     Statement statement = (body as BlockFunctionBody).block.statements[0];
     expect(statement, isReturnStatement);
     Expression expression = (statement as ReturnStatement).expression;
     expect(expression, isBinaryExpression);
-    if (!usingFastaParser) {
-      // TODO(danrubel): capture `await` keywords in fasta generated AST
-      expect((expression as BinaryExpression).leftOperand, isAwaitExpression);
-      expect((expression as BinaryExpression).rightOperand, isAwaitExpression);
-    }
   }
 
   void test_parseClassMember_constructor_withDocComment() {
@@ -606,15 +574,9 @@
     createParser('var for;');
     ClassMember member = parser.parseClassMember('C');
     expect(member, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 4, 3)
-          ]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 3),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 3)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 4, 3)
+    ]);
   }
 
   void test_parseClassMember_field_nameMissing() {
@@ -629,12 +591,8 @@
     createParser('var "";');
     ClassMember member = parser.parseClassMember('C');
     expect(member, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 2)
-          ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2)]);
   }
 
   void test_parseClassMember_field_static() {
@@ -921,13 +879,9 @@
     createParser('static int get C => 0;');
     ClassMember member = parser.parseClassMember('C');
     expect(member, isNotNull);
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 15, 1),
-      ]);
-    } else {
-      assertNoErrors();
-    }
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 15, 1),
+    ]);
     expect(member, isMethodDeclaration);
     MethodDeclaration method = member;
     expect(method.documentationComment, isNull);
@@ -1015,63 +969,43 @@
   void test_parseClassMember_method_native_missing_literal_not_allowed() {
     allowNativeClause = false;
     _parseClassMember_method_native_missing_literal();
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
-      ]);
-    } else {
-      assertNoErrors();
-    }
+    listener.assertErrors([
+      expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
+    ]);
   }
 
   void test_parseClassMember_method_native_not_allowed() {
     allowNativeClause = false;
     _parseClassMember_method_native();
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
-      ]);
-    } else {
-      assertNoErrors();
-    }
+    listener.assertErrors([
+      expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
+    ]);
   }
 
   void test_parseClassMember_method_native_with_body_allowed() {
     allowNativeClause = true;
     _parseClassMember_method_native_with_body();
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      assertErrorsWithCodes([
-        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
-      ]);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    assertErrorsWithCodes([
+      ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
+    ]);
 //      listener.assertErrors([
 //        expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 17, 2),
 //      ]);
-    } else {
-      assertErrorsWithCodes([
-        ParserErrorCode.EXPECTED_TOKEN,
-      ]);
-    }
   }
 
   void test_parseClassMember_method_native_with_body_not_allowed() {
     allowNativeClause = false;
     _parseClassMember_method_native_with_body();
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      assertErrorsWithCodes([
-        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
-        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
-      ]);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    assertErrorsWithCodes([
+      ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
+      ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
+    ]);
 //      listener.assertErrors([
 //        expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
 //        expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 17, 2),
 //      ]);
-    } else {
-      assertErrorsWithCodes([
-        ParserErrorCode.EXPECTED_TOKEN,
-      ]);
-    }
   }
 
   void test_parseClassMember_method_operator_noType() {
@@ -1193,13 +1127,9 @@
     createParser('static void set C(_) {}');
     ClassMember member = parser.parseClassMember('C');
     expect(member, isNotNull);
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
-      ]);
-    } else {
-      assertNoErrors();
-    }
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
+    ]);
     expect(member, isMethodDeclaration);
     MethodDeclaration method = member;
     expect(method.documentationComment, isNull);
@@ -1270,7 +1200,6 @@
   }
 
   void test_parseClassMember_method_static_mixin() {
-    if (!usingFastaParser) return;
     var unit = parseCompilationUnit('mixin C { static void m() {} }');
     MixinDeclaration c = unit.declarations[0];
     MethodDeclaration method = c.members[0];
@@ -1838,10 +1767,6 @@
   }
 }
 
-/// Tests of the analyzer parser based on [ComplexParserTestMixin].
-@reflectiveTest
-class ComplexParserTest extends ParserTestCase with ComplexParserTestMixin {}
-
 /// The class `ComplexParserTest` defines parser tests that test the parsing of
 /// more complex code fragments or the interactions between multiple parsing
 /// methods. For example, tests to ensure that the precedence of operations is
@@ -2326,22 +2251,9 @@
   }
 }
 
-/// The class `ErrorParserTest` defines parser tests that test the parsing
-/// of code to ensure that errors are correctly reported,
-/// and in some cases, not reported.
-@reflectiveTest
-class ErrorParserTest extends ParserTestCase with ErrorParserTestMixin {
-  void test_missingIdentifier_number() {
-    createParser('1');
-    SimpleIdentifier expression = parser.parseSimpleIdentifier();
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
-    expect(expression.isSynthetic, isTrue);
-  }
-}
-
-mixin ErrorParserTestMixin implements AbstractParserTestCase {
+/// This defines parser tests that test the parsing of code to ensure that
+/// errors are correctly reported, and in some cases, not reported.
+mixin ErrorParserTestMixin implements AbstractParserViaProxyTestCase {
   void test_abstractClassMember_constructor() {
     createParser('abstract C.c();');
     ClassMember member = parser.parseClassMember('C');
@@ -2457,13 +2369,10 @@
   }
 
   void test_classInClass_abstract() {
-    parseCompilationUnit("class C { abstract class B {} }",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 10, 8),
-                expectedError(ParserErrorCode.CLASS_IN_CLASS, 19, 5)
-              ]
-            : [expectedError(ParserErrorCode.CLASS_IN_CLASS, 19, 5)]);
+    parseCompilationUnit("class C { abstract class B {} }", errors: [
+      expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 10, 8),
+      expectedError(ParserErrorCode.CLASS_IN_CLASS, 19, 5)
+    ]);
   }
 
   void test_classInClass_nonAbstract() {
@@ -2477,17 +2386,11 @@
     createParser('class A = abstract B with C;', expectedEndOffset: 21);
     CompilationUnitMember member = parseFullCompilationUnitMember();
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 8),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0)
-          ]);
+    listener.assertErrors([
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 8),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1)
+    ]);
   }
 
   void test_colonInPlaceOfIn() {
@@ -2534,15 +2437,12 @@
   }
 
   void test_constEnum() {
-    parseCompilationUnit("const enum E {ONE}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `const` as a malformed top level const
-                // and `enum` as the start of an enum declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
-              ]
-            : [expectedError(ParserErrorCode.CONST_ENUM, 0, 5)]);
+    parseCompilationUnit("const enum E {ONE}", errors: [
+      // Fasta interprets the `const` as a malformed top level const
+      // and `enum` as the start of an enum declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
+    ]);
   }
 
   void test_constFactory() {
@@ -2576,56 +2476,34 @@
   void test_constructorPartial() {
     createParser('class C { C< }');
     parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 2),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 13, 1),
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 13, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 2),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 13, 1),
+    ]);
   }
 
   void test_constructorPartial2() {
     createParser('class C { C<@Foo }');
     parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 6),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 17, 1),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 17, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 6),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 17, 1),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1)
+    ]);
   }
 
   void test_constructorPartial3() {
     createParser('class C { C<@Foo @Bar() }');
     parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 13),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 1),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 24, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 24, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 13),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 1),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 24, 1)
+    ]);
   }
 
   void test_constructorWithReturnType() {
@@ -2641,21 +2519,17 @@
     createParser('var C() {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3)]
-        : [expectedError(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, 0, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3)]);
   }
 
   void test_constTypedef() {
-    parseCompilationUnit("const typedef F();",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `const` as a malformed top level const
-                // and `typedef` as the start of an typedef declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
-              ]
-            : [expectedError(ParserErrorCode.CONST_TYPEDEF, 0, 5)]);
+    parseCompilationUnit("const typedef F();", errors: [
+      // Fasta interprets the `const` as a malformed top level const
+      // and `typedef` as the start of an typedef declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
+    ]);
   }
 
   void test_continueOutsideOfLoop_continueInDoStatement() {
@@ -2749,41 +2623,32 @@
     // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
     // this would be a better error message.
     parseStatement("covariant int x;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 9)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 9)]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 9)]);
   }
 
   void test_covariantConstructor() {
     createParser('class C { covariant C(); }');
     ClassDeclaration member = parseFullCompilationUnitMember();
     expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.COVARIANT_MEMBER
-              : ParserErrorCode.COVARIANT_CONSTRUCTOR,
-          10,
-          9)
-    ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.COVARIANT_MEMBER, 10, 9)]);
   }
 
   void test_covariantMember_getter_noReturnType() {
     createParser('static covariant get x => 0;');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]
-        : [expectedError(ParserErrorCode.COVARIANT_MEMBER, 7, 9)]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]);
   }
 
   void test_covariantMember_getter_returnType() {
     createParser('static covariant int get x => 0;');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]
-        : [expectedError(ParserErrorCode.COVARIANT_MEMBER, 7, 9)]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]);
   }
 
   void test_covariantMember_method() {
@@ -2846,18 +2711,12 @@
   void test_directiveAfterDeclaration_classBeforeDirective() {
     // TODO(brianwilkerson) Remove codes when highlighting is fixed.
     CompilationUnit unit = parseCompilationUnit("class Foo{} library l;",
-        codes: usingFastaParser
-            ? [ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST]
-            : [ParserErrorCode.DIRECTIVE_AFTER_DECLARATION],
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 12, 10)
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, 12, 10)
-              ]);
+        codes: [
+          ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST
+        ],
+        errors: [
+          expectedError(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 12, 10)
+        ]);
     expect(unit, isNotNull);
   }
 
@@ -2975,47 +2834,26 @@
   void test_expectedCaseOrDefault() {
     SwitchStatement statement = parseStatement('switch (e) {break;}');
     expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)]
-        : [expectedError(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, 12, 5)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)]);
   }
 
   void test_expectedClassMember_inClass_afterType() {
-    parseCompilationUnit('class C{ heart 2 heart }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 9, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 5),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 17, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 5)
-              ]
-            : [
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 1)
-              ]);
+    parseCompilationUnit('class C{ heart 2 heart }', errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 9, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 5),
+      expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 17, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 5)
+    ]);
   }
 
   void test_expectedClassMember_inClass_beforeType() {
-    parseCompilationUnit('class C { 4 score }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 10, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 18, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 1)
-              ]);
+    parseCompilationUnit('class C { 4 score }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)
+    ]);
   }
 
   void test_expectedExecutable_afterAnnotation_atEOF() {
@@ -3026,87 +2864,49 @@
   }
 
   void test_expectedExecutable_inClass_afterVoid() {
-    parseCompilationUnit('class C { void 2 void }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 4),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 22, 1),
-              ]);
+    parseCompilationUnit('class C { void 2 void }', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 15, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 4),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
+    ]);
   }
 
   void test_expectedExecutable_topLevel_afterType() {
-    CompilationUnit unit = parseCompilationUnit('heart 2 heart',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 5),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 8, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 5),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 5)
-              ]);
+    CompilationUnit unit = parseCompilationUnit('heart 2 heart', errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 5),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 8, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 5),
+    ]);
     expect(unit, isNotNull);
   }
 
   void test_expectedExecutable_topLevel_afterVoid() {
-    CompilationUnit unit = parseCompilationUnit('void 2 void',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 5, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 0),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 0),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 5)
-              ]);
+    CompilationUnit unit = parseCompilationUnit('void 2 void', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 5, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 0),
+    ]);
     expect(unit, isNotNull);
   }
 
   void test_expectedExecutable_topLevel_beforeType() {
-    parseCompilationUnit('4 score',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 2, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 5),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 2, 5),
-              ]);
+    parseCompilationUnit('4 score', errors: [
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 2, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 5),
+    ]);
   }
 
   void test_expectedExecutable_topLevel_eof() {
-    parseCompilationUnit('x',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)
-              ]
-            : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1)]);
+    parseCompilationUnit('x', errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)
+    ]);
   }
 
   void test_expectedInterpolationIdentifier() {
@@ -3151,9 +2951,8 @@
     createParser('(x, y z)');
     ArgumentList list = parser.parseArgumentList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
   }
 
   void test_expectedToken_parseStatement_afterVoid() {
@@ -3246,23 +3045,15 @@
   }
 
   void test_exportAsType() {
-    parseCompilationUnit('export<dynamic> foo;',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 0, 6)
-              ]
-            : []);
+    parseCompilationUnit('export<dynamic> foo;', errors: [
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 0, 6)
+    ]);
   }
 
   void test_exportAsType_inClass() {
-    parseCompilationUnit('class C { export<dynamic> foo; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 6)
-              ]
-            : []);
+    parseCompilationUnit('class C { export<dynamic> foo; }', errors: [
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 6)
+    ]);
   }
 
   void test_exportDirectiveAfterPartDirective() {
@@ -3305,30 +3096,18 @@
     createParser('external factory C() {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXTERNAL_FACTORY_WITH_BODY
-              : ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY,
-          21,
-          1)
-    ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTERNAL_FACTORY_WITH_BODY, 21, 1)]);
   }
 
   void test_externalConstructorWithBody_named() {
     createParser('external C.c() {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
 //      listener.assertErrors(
 //          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 15, 2)]);
-    } else {
-      listener.assertErrorsWithCodes(
-          [ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY]);
-    }
   }
 
   void test_externalEnum() {
@@ -3340,12 +3119,8 @@
     createParser('external const A f;');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_FIELD]);
-    }
+    listener.assertErrors(
+        [expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)]);
   }
 
   void test_externalField_final() {
@@ -3380,16 +3155,10 @@
     createParser('external int get x {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
 //      listener.assertErrors(
 //          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 19, 2)]);
-    } else {
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_GETTER_WITH_BODY]);
-    }
   }
 
   void test_externalMethodWithBody() {
@@ -3406,32 +3175,20 @@
     createParser('external operator +(int value) {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
 //      listener.assertErrors(
 //          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 31, 2)]);
-    } else {
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY]);
-    }
   }
 
   void test_externalSetterWithBody() {
     createParser('external set x(int value) {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
 //      listener.assertErrors(
 //          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 26, 2)]);
-    } else {
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_SETTER_WITH_BODY]);
-    }
   }
 
   void test_externalTypedef() {
@@ -3443,38 +3200,24 @@
     createParser('(int a, , int b)');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
-          ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]);
   }
 
   void test_extraCommaTrailingNamedParameterGroup() {
     createParser('({int b},)');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
-            expectedError(
-                ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 9, 1)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]);
   }
 
   void test_extraCommaTrailingPositionalParameterGroup() {
     createParser('([int b],)');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
-            expectedError(
-                ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 9, 1)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]);
   }
 
   void test_extraTrailingCommaInParameterList() {
@@ -3507,21 +3250,16 @@
     createParser('factory C() : x = 3 {}', expectedEndOffset: 12);
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)]
-        : [expectedError(ParserErrorCode.FACTORY_WITH_INITIALIZERS, 12, 1)]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)]);
   }
 
   void test_factoryWithoutBody() {
     createParser('factory C();');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 11, 1)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.FACTORY_WITHOUT_BODY]);
-    }
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 11, 1)]);
   }
 
   void test_fieldInitializerOutsideConstructor() {
@@ -3537,12 +3275,10 @@
     createParser('final covariant f = null;');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 9),
-            expectedError(ParserErrorCode.FINAL_AND_COVARIANT, 6, 9)
-          ]
-        : [expectedError(ParserErrorCode.FINAL_AND_COVARIANT, 6, 9)]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 9),
+      expectedError(ParserErrorCode.FINAL_AND_COVARIANT, 6, 9)
+    ]);
   }
 
   void test_finalAndVar() {
@@ -3571,83 +3307,54 @@
     createParser('final C() {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.FINAL_CONSTRUCTOR]);
-    }
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
   }
 
   void test_finalEnum() {
-    parseCompilationUnit("final enum E {ONE}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `final` as a malformed top level final
-                // and `enum` as the start of a enum declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
-              ]
-            : [expectedError(ParserErrorCode.FINAL_ENUM, 0, 5)]);
+    parseCompilationUnit("final enum E {ONE}", errors: [
+      // Fasta interprets the `final` as a malformed top level final
+      // and `enum` as the start of a enum declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
+    ]);
   }
 
   void test_finalMethod() {
     createParser('final int m() {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.FINAL_METHOD]);
-    }
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
   }
 
   void test_finalTypedef() {
-    parseCompilationUnit("final typedef F();",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `final` as a malformed top level final
-                // and `typedef` as the start of an typedef declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
-              ]
-            : [expectedError(ParserErrorCode.FINAL_TYPEDEF, 0, 5)]);
+    parseCompilationUnit("final typedef F();", errors: [
+      // Fasta interprets the `final` as a malformed top level final
+      // and `typedef` as the start of an typedef declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
+    ]);
   }
 
   void test_functionTypedField_invalidType_abstract() {
-    if (usingFastaParser) {
-      parseCompilationUnit("Function(abstract) x = null;", errors: [
-        expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 9, 8)
-      ]);
-    }
+    parseCompilationUnit("Function(abstract) x = null;", errors: [
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 9, 8)
+    ]);
   }
 
   void test_functionTypedField_invalidType_class() {
-    if (usingFastaParser) {
-      parseCompilationUnit("Function(class) x = null;",
-          errors: usingFastaParser
-              ? [
-                  expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5),
-                  expectedError(
-                      ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 9, 5)
-                ]
-              : [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5)]);
-    }
+    parseCompilationUnit("Function(class) x = null;", errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5),
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 9, 5)
+    ]);
   }
 
   void test_functionTypedParameter_const() {
-    parseCompilationUnit("void f(const x()) {}",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5),
-                expectedError(
-                    ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
-              ]);
+    parseCompilationUnit("void f(const x()) {}", errors: [
+      expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5),
+      expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
+    ]);
   }
 
   void test_functionTypedParameter_final() {
@@ -3657,19 +3364,11 @@
   }
 
   void test_functionTypedParameter_incomplete1() {
-    parseCompilationUnit("void f(int Function(",
-        errors: usingFastaParser
-            ? [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
-              ]
-            : [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 0),
-              ]);
+    parseCompilationUnit("void f(int Function(", errors: [
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
+    ]);
   }
 
   void test_functionTypedParameter_var() {
@@ -3686,21 +3385,17 @@
   }
 
   void test_genericFunctionType_asIdentifier2() {
-    if (usingFastaParser) {
-      createParser('int Function() {}');
-      CompilationUnit unit = parser.parseCompilationUnit2();
-      expectNotNullIfNoErrors(unit);
-      listener.assertErrors([]);
-    }
+    createParser('int Function() {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors([]);
   }
 
   void test_genericFunctionType_asIdentifier3() {
-    if (usingFastaParser) {
-      createParser('int Function() => 0;');
-      CompilationUnit unit = parser.parseCompilationUnit2();
-      expectNotNullIfNoErrors(unit);
-      listener.assertErrors([]);
-    }
+    createParser('int Function() => 0;');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors([]);
   }
 
   void test_genericFunctionType_extraLessThan() {
@@ -3710,55 +3405,42 @@
 }''');
     CompilationUnit unit = parser.parseCompilationUnit2();
     expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 30, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 1)
-          ]
-        : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 30, 1)]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 30, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 1)
+    ]);
   }
 
   void test_getterInFunction_block_noReturnType() {
     Statement result =
         parseStatement("get x { return _x; }", expectedEndOffset: 4);
-    if (usingFastaParser) {
-      // Fasta considers `get` to be an identifier in this situation.
-      // TODO(danrubel): Investigate better recovery.
-      ExpressionStatement statement = result;
-      listener
-          .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
-      expect(statement.expression.toSource(), 'get');
-    } else {
-      FunctionDeclarationStatement statement = result;
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 0, 3)]);
-      expect(
-          statement.functionDeclaration.functionExpression.parameters, isNull);
-    }
+    // Fasta considers `get` to be an identifier in this situation.
+    // TODO(danrubel): Investigate better recovery.
+    ExpressionStatement statement = result;
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
+    expect(statement.expression.toSource(), 'get');
   }
 
   void test_getterInFunction_block_returnType() {
     // Fasta considers `get` to be an identifier in this situation.
     parseStatement("int get x { return _x; }", expectedEndOffset: 8);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]
-        : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 4, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]);
   }
 
   void test_getterInFunction_expression_noReturnType() {
     // Fasta considers `get` to be an identifier in this situation.
     parseStatement("get x => _x;", expectedEndOffset: 4);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]
-        : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 0, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
   }
 
   void test_getterInFunction_expression_returnType() {
     // Fasta considers `get` to be an identifier in this situation.
     parseStatement("int get x => _x;", expectedEndOffset: 8);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]
-        : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 4, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]);
   }
 
   void test_getterWithParameters() {
@@ -3773,30 +3455,18 @@
 
   void test_illegalAssignmentToNonAssignable_assign_int() {
     parseStatement("0 = 1;");
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 1),
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 1),
-          ]
-        : [
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 4, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 1),
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 1),
+    ]);
   }
 
   void test_illegalAssignmentToNonAssignable_assign_this() {
     parseStatement("this = 1;");
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 4),
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 4)
-          ]
-        : [
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 7, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 4),
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 4)
+    ]);
   }
 
   void test_illegalAssignmentToNonAssignable_postfix_minusMinus_literal() {
@@ -3868,32 +3538,21 @@
   void test_initializedVariableInForEach_localFunction() {
     Statement statement = parseStatement('for (f()) {}');
     expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
+    ]);
   }
 
   void test_initializedVariableInForEach_localFunction2() {
     Statement statement = parseStatement('for (T f()) {}');
     expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)
+    ]);
   }
 
   void test_initializedVariableInForEach_var() {
@@ -3959,12 +3618,8 @@
     createParser("C.*();");
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1),
-            expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 2, 1)
-          ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]);
   }
 
   void test_invalidConstructorName_with() {
@@ -3972,10 +3627,7 @@
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
     listener.assertErrors([
-      usingFastaParser
-          ? expectedError(
-              ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 2, 4)
-          : expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 0, 1)
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 2, 4)
     ]);
   }
 
@@ -3983,35 +3635,18 @@
     createParser("C() : super = 42;");
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 6, 5)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1),
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 16, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 16, 2),
-            expectedError(
-                ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, 16, 0),
-          ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 6, 5)]);
   }
 
   void test_invalidConstructorSuperFieldAssignment() {
     createParser("C() : super.a = 42;");
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS,
-                12,
-                1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1),
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 16, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 16, 2),
-            expectedError(
-                ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, 16, 0),
-          ]);
+    listener.assertErrors([
+      expectedError(
+          ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS, 12, 1)
+    ]);
   }
 
   void test_invalidHexEscape_invalidDigit() {
@@ -4029,36 +3664,20 @@
   void test_invalidInlineFunctionType() {
     parseCompilationUnit(
       'typedef F = int Function(int a());',
-      errors: usingFastaParser
-          ? [
-              expectedError(
-                  CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 30, 1)
-            ]
-          : [],
+      errors: [
+        expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 30, 1)
+      ],
     );
   }
 
   void test_invalidInterpolation_missingClosingBrace_issue35900() {
-    parseCompilationUnit(r"main () { print('${x' '); }",
-        errors: usingFastaParser
-            ? [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(
-                    ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 26, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 3),
-                expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 27, 0),
-              ]
-            : [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(
-                    ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 26, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 3),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 23, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 1),
-              ]);
+    parseCompilationUnit(r"main () { print('${x' '); }", errors: [
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 26, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 3),
+      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 23, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 27, 0),
+    ]);
   }
 
   void test_invalidInterpolationIdentifier_startWithDigit() {
@@ -4077,14 +3696,9 @@
   }
 
   void test_invalidOperator() {
-    CompilationUnit unit =
-        parseCompilationUnit('class C { void operator ===(x) { } }',
-            errors: usingFastaParser
-                ? [expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1)]
-                : [
-                    expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1),
-                    expectedError(ParserErrorCode.INVALID_OPERATOR, 24, 3)
-                  ]);
+    CompilationUnit unit = parseCompilationUnit(
+        'class C { void operator ===(x) { } }',
+        errors: [expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1)]);
     expect(unit, isNotNull);
   }
 
@@ -4092,22 +3706,10 @@
     createParser('class C { int operator unary- => 0; }');
     CompilationUnit unit = parser.parseCompilationUnit2();
     expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 28, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 8),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 28, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 28, 1),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 30, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 30, 2),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 33, 1),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 33, 1),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 34, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 28, 1)
+    ]);
   }
 
   void test_invalidOperatorAfterSuper_assignableExpression() {
@@ -4115,22 +3717,14 @@
     expectNotNullIfNoErrors(expression);
     listener.assertErrors([
       expectedError(
-          usingFastaParser
-              ? ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
-              : ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
-          5,
-          2)
+          ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER, 5, 2)
     ]);
   }
 
   void test_invalidOperatorAfterSuper_primaryExpression() {
     Expression expression = parseExpression('super?.v', errors: [
       expectedError(
-          usingFastaParser
-              ? ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
-              : ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
-          5,
-          2)
+          ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER, 5, 2)
     ]);
     expectNotNullIfNoErrors(expression);
   }
@@ -4139,11 +3733,8 @@
     createParser('++super');
     Expression expression = parser.parseUnaryExpression();
     expectNotNullIfNoErrors(expression);
-    listener.assertErrors([
-      usingFastaParser
-          ? expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 5)
-          : expectedError(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, 0, 2)
-    ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 5)]);
   }
 
   void test_invalidPropertyAccess_this() {
@@ -4155,84 +3746,52 @@
     createParser('foo() async* => 0;');
     CompilationUnit unit = parser.parseCompilationUnit2();
     expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 13, 2)]
-        : [expectedError(ParserErrorCode.INVALID_STAR_AFTER_ASYNC, 11, 1)]);
+    listener.assertErrors(
+        [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 13, 2)]);
   }
 
   void test_invalidSync() {
     createParser('foo() sync* => 0;');
     CompilationUnit unit = parser.parseCompilationUnit2();
     expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 12, 2)]
-        : [expectedError(ParserErrorCode.INVALID_SYNC, 0, 4)]);
+    listener.assertErrors(
+        [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 12, 2)]);
   }
 
   void test_invalidTopLevelSetter() {
     parseCompilationUnit("var set foo; main(){}", errors: [
       expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3),
-      usingFastaParser
-          ? expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 8, 3)
-          : expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 11, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 8, 3),
       expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 11, 1)
     ]);
   }
 
   void test_invalidTopLevelVar() {
-    parseCompilationUnit("var Function(var arg);",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 21, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 21, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 21, 2),
-              ]);
+    parseCompilationUnit("var Function(var arg);", errors: [
+      expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 21, 1),
+    ]);
   }
 
   void test_invalidTypedef() {
-    parseCompilationUnit("typedef var Function(var arg);",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
-                expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 8, 3),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 3),
-                expectedError(ParserErrorCode.VAR_RETURN_TYPE, 8, 3),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
-                expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 8, 3),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 29, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 2),
-              ]);
+    parseCompilationUnit("typedef var Function(var arg);", errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
+      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 8, 3),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 3),
+      expectedError(ParserErrorCode.VAR_RETURN_TYPE, 8, 3),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 1),
+    ]);
   }
 
   void test_invalidTypedef2() {
     // https://github.com/dart-lang/sdk/issues/31171
     parseCompilationUnit(
         "typedef T = typedef F = Map<String, dynamic> Function();",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 7),
-                expectedError(
-                    ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 10, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 7),
-                expectedError(
-                    ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 20, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 20, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 36, 7),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 43, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 43, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 55, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 55, 1),
-              ]);
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 7),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 7),
+          expectedError(ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 10, 1),
+        ]);
   }
 
   void test_invalidUnicodeEscape_incomplete_noDigits() {
@@ -4273,12 +3832,8 @@
   void test_invalidUnicodeEscape_tooManyDigits_variable() {
     Expression expression = parseStringLiteral("'\\u{12345678}'");
     expectNotNullIfNoErrors(expression);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.INVALID_CODE_POINT, 1, 9)]
-        : [
-            expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 12),
-            expectedError(ParserErrorCode.INVALID_CODE_POINT, 1, 12)
-          ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_CODE_POINT, 1, 9)]);
   }
 
   void test_libraryDirectiveNotFirst() {
@@ -4305,51 +3860,29 @@
     BlockFunctionBody body = member.body;
     expect(body.block.statements, hasLength(1));
     FunctionDeclarationStatement statement = body.block.statements[0];
-    if (usingFastaParser) {
-      expect(statement.functionDeclaration.metadata, hasLength(1));
-      Annotation metadata = statement.functionDeclaration.metadata[0];
-      expect(metadata.name.name, 'Foo');
-    }
+    expect(statement.functionDeclaration.metadata, hasLength(1));
+    Annotation metadata = statement.functionDeclaration.metadata[0];
+    expect(metadata.name.name, 'Foo');
   }
 
   void test_localFunctionDeclarationModifier_abstract() {
     parseCompilationUnit("class C { m() { abstract f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
-              ]);
+        errors: [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]);
   }
 
   void test_localFunctionDeclarationModifier_external() {
     parseCompilationUnit("class C { m() { external f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
-              ]);
+        errors: [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]);
   }
 
   void test_localFunctionDeclarationModifier_factory() {
     parseCompilationUnit("class C { m() { factory f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 7)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 7)
-              ]);
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 7)]);
   }
 
   void test_localFunctionDeclarationModifier_static() {
     parseCompilationUnit("class C { m() { static f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 6)
-              ]);
+        errors: [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6)]);
   }
 
   void test_method_invalidTypeParameterExtends() {
@@ -4359,19 +3892,11 @@
     createParser('f<E>(E extends num p);');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 7)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0,
-                0), // `extends` is a keyword
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0), // comma
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0), // close paren
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 0)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 7)]);
     expect(member, isMethodDeclaration);
     MethodDeclaration method = member;
-    expect(
-        method.parameters.toString(), usingFastaParser ? '(E)' : '(E, extends)',
+    expect(method.parameters.toString(), '(E)',
         reason: 'parser recovers what it can');
   }
 
@@ -4379,15 +3904,8 @@
     createParser('void m<E, hello!>() {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 5)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*>*/,
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*(*/,
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*)*/,
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 0)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 5)]);
     expect(member, isMethodDeclaration);
     MethodDeclaration method = member;
     expect(method.typeParameters.toString(), '<E, hello>',
@@ -4516,16 +4034,14 @@
     // to parse it as an expression statement. It isn't clear what the best
     // error message is in this case.
     parseStatement("int f => x;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 6, 2)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 6, 2)]);
   }
 
   void test_missingFunctionParameters_local_void_block() {
     parseStatement("void f { return x;}", expectedEndOffset: 7);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-        : [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
   }
 
   void test_missingFunctionParameters_local_void_expression() {
@@ -4574,16 +4090,10 @@
     createParser('int}', expectedEndOffset: 3);
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 3),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)
-          ]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 3),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)
+    ]);
   }
 
   void test_missingIdentifier_inEnum() {
@@ -4606,15 +4116,8 @@
     createParser('(a, [])');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
-    } else {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)
-      ]);
-    }
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
   }
 
   void test_missingIdentifier_inSymbol_afterPeriod() {
@@ -4675,10 +4178,8 @@
     createParser('void m {} }', expectedEndOffset: 10);
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS,
-          usingFastaParser ? 5 : 7, 1)
-    ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 5, 1)]);
     expect(member, isMethodDeclaration);
     MethodDeclaration method = member;
     expect(method.parameters, hasLength(0));
@@ -4688,10 +4189,8 @@
     createParser('void m => null; }', expectedEndOffset: 16);
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS,
-          usingFastaParser ? 5 : 7, 1)
-    ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 5, 1)]);
   }
 
   void test_missingNameForNamedParameter_colon() {
@@ -4699,16 +4198,10 @@
     FormalParameter parameter =
         parser.parseFormalParameterList(inFunctionType: true).parameters[0];
     expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1),
-            expectedError(
-                ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER, 7, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
+      expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
+    ]);
     expect(parameter.identifier, isNotNull);
   }
 
@@ -4717,16 +4210,10 @@
     FormalParameter parameter =
         parser.parseFormalParameterList(inFunctionType: true).parameters[0];
     expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1),
-            expectedError(
-                ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER, 7, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
+      expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
+    ]);
     expect(parameter.identifier, isNotNull);
   }
 
@@ -4735,36 +4222,20 @@
     FormalParameter parameter =
         parser.parseFormalParameterList(inFunctionType: true).parameters[0];
     expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER, 5, 1)
-          ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
     expect(parameter.identifier, isNotNull);
   }
 
   void test_missingNameInLibraryDirective() {
-    CompilationUnit unit = parseCompilationUnit("library;", errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_IDENTIFIER
-              : ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE,
-          7,
-          1)
-    ]);
+    CompilationUnit unit = parseCompilationUnit("library;",
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 7, 1)]);
     expect(unit, isNotNull);
   }
 
   void test_missingNameInPartOfDirective() {
-    CompilationUnit unit = parseCompilationUnit("part of;", errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_STRING_LITERAL
-              : ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE,
-          7,
-          1)
-    ]);
+    CompilationUnit unit = parseCompilationUnit("part of;",
+        errors: [expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 1)]);
     expect(unit, isNotNull);
   }
 
@@ -4784,20 +4255,17 @@
 
   void test_missingStatement() {
     parseStatement("is");
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 2),
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 0)
-          ]
-        : [expectedError(ParserErrorCode.MISSING_STATEMENT, 2, 0)]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 2),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 0)
+    ]);
   }
 
   void test_missingStatement_afterVoid() {
     parseStatement("void;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]
-        : [expectedError(ParserErrorCode.MISSING_STATEMENT, 4, 1)]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]);
   }
 
   void test_missingTerminatorForParameterGroup_named() {
@@ -4837,27 +4305,24 @@
   void test_missingVariableInForEach() {
     Statement statement = parseStatement('for (a < b in foo) {}');
     expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1)]
-        : [expectedError(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH, 5, 5)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1)]);
   }
 
   void test_mixedParameterGroups_namedPositional() {
     createParser('(a, {b}, [c])');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [expectedError(ParserErrorCode.MIXED_PARAMETER_GROUPS, 9, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
   }
 
   void test_mixedParameterGroups_positionalNamed() {
     createParser('(a, [b], {c})');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [expectedError(ParserErrorCode.MIXED_PARAMETER_GROUPS, 9, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
   }
 
   void test_mixin_application_lacks_with_clause() {
@@ -4887,11 +4352,8 @@
     createParser('(a, {b}, {c})');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [
-            expectedError(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS, 9, 3)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
   }
 
   void test_multiplePartOfDirectives() {
@@ -4904,22 +4366,15 @@
     createParser('(a, [b], [c])');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS, 9, 3)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
   }
 
   void test_multipleVariablesInForEach() {
     Statement statement = parseStatement('for (int a, b in foo) {}');
     expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 10, 1)]
-        : [
-            expectedError(ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH, 12, 1)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 10, 1)]);
   }
 
   void test_multipleWithClauses() {
@@ -4929,20 +4384,11 @@
 
   void test_namedFunctionExpression() {
     Expression expression;
-    if (usingFastaParser) {
-      createParser('f() {}');
-      expression = parser.parsePrimaryExpression();
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, 0, 1)]);
-      expect(expression, isFunctionExpression);
-    } else {
-      expression = parsePrimaryExpression('f() {}');
-      expectNotNullIfNoErrors(expression);
-      // Should generate an error.
-      //listener.assertErrors(
-      //    [expectedError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, 0, 1)]);
-      //expect(expression, isFunctionExpression);
-    }
+    createParser('f() {}');
+    expression = parser.parsePrimaryExpression();
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, 0, 1)]);
+    expect(expression, isFunctionExpression);
   }
 
   void test_namedParameterOutsideGroup() {
@@ -4959,49 +4405,35 @@
     createParser('factory int x;', expectedEndOffset: 12);
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
-          ]
-        : [expectedError(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, 0, 7)]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
+    ]);
   }
 
   void test_nonConstructorFactory_method() {
     createParser('factory int m() {}', expectedEndOffset: 12);
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
-          ]
-        : [expectedError(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, 0, 7)]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
+    ]);
   }
 
   void test_nonIdentifierLibraryName_library() {
-    CompilationUnit unit = parseCompilationUnit("library 'lib';", errors: [
-      usingFastaParser
-          ? expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 5)
-          : expectedError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, 8, 5)
-    ]);
+    CompilationUnit unit = parseCompilationUnit("library 'lib';",
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 5)]);
     expect(unit, isNotNull);
   }
 
   void test_nonIdentifierLibraryName_partOf() {
-    CompilationUnit unit = parseCompilationUnit("part of 3;",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 8, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 1)
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, 8, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)
-              ]);
+    CompilationUnit unit = parseCompilationUnit("part of 3;", errors: [
+      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 8, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 1),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 1)
+    ]);
     expect(unit, isNotNull);
   }
 
@@ -5024,34 +4456,18 @@
     createParser('operator +=(int x) => x + 1;');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.INVALID_OPERATOR
-              : ParserErrorCode.NON_USER_DEFINABLE_OPERATOR,
-          9,
-          2)
-    ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.INVALID_OPERATOR, 9, 2)]);
   }
 
   void test_optionalAfterNormalParameters_named() {
     parseCompilationUnit("f({a}, b) {}",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-            : [
-                expectedError(
-                    ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 7, 1)
-              ]);
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
   }
 
   void test_optionalAfterNormalParameters_positional() {
     parseCompilationUnit("f([a], b) {}",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-            : [
-                expectedError(
-                    ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 7, 1)
-              ]);
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
   }
 
   void test_parseCascadeSection_missingIdentifier() {
@@ -5094,18 +4510,10 @@
     createParser('(a, b = 0)');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 6, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, 4, 1)
-          ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 6, 1)]);
     expect(list.parameters[0].isRequired, isTrue);
-    if (usingFastaParser) {
-      expect(list.parameters[1].isNamed, isTrue);
-    } else {
-      expect(list.parameters[1].isOptionalPositional, isTrue);
-    }
+    expect(list.parameters[1].isNamed, isTrue);
   }
 
   void test_redirectingConstructorWithBody_named() {
@@ -5113,8 +4521,7 @@
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
     listener.assertErrors([
-      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15,
-          usingFastaParser ? 1 : 2)
+      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15, 1)
     ]);
   }
 
@@ -5123,8 +4530,7 @@
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
     listener.assertErrors([
-      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15,
-          usingFastaParser ? 1 : 2)
+      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15, 1)
     ]);
   }
 
@@ -5140,16 +4546,14 @@
 
   void test_setterInFunction_block() {
     parseStatement("set x(v) {_x = v;}");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]
-        : [expectedError(ParserErrorCode.SETTER_IN_FUNCTION, 0, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]);
   }
 
   void test_setterInFunction_expression() {
     parseStatement("set x(v) => _x = v;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]
-        : [expectedError(ParserErrorCode.SETTER_IN_FUNCTION, 0, 3)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]);
   }
 
   void test_staticAfterConst() {
@@ -5164,14 +4568,10 @@
     createParser('const static int f;');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 6),
-        expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)
-      ]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.MODIFIER_OUT_OF_ORDER]);
-    }
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 6),
+      expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)
+    ]);
   }
 
   void test_staticAfterVar() {
@@ -5194,14 +4594,8 @@
     createParser('static get m;');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_FUNCTION_BODY
-              : ParserErrorCode.STATIC_GETTER_WITHOUT_BODY,
-          12,
-          1)
-    ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)]);
   }
 
   void test_staticOperator_noReturnType() {
@@ -5224,14 +4618,8 @@
     createParser('static set m(x);');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_FUNCTION_BODY
-              : ParserErrorCode.STATIC_SETTER_WITHOUT_BODY,
-          15,
-          1)
-    ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 15, 1)]);
   }
 
   void test_staticTopLevelDeclaration_class() {
@@ -5269,29 +4657,15 @@
 m() {
  {
  '${${
-''',
-        codes: usingFastaParser
-            ? [
-                ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN
-              ]
-            : [
-                ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-              ]);
+''', codes: [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
   }
 
   void test_switchCase_missingColon() {
@@ -5351,13 +4725,7 @@
     SwitchStatement statement =
         parseStatement('switch (a) return;', expectedEndOffset: 11);
     expect(statement, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_BODY, 9, 1)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6),
-            expectedError(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, 11, 6),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6)
-          ]);
+    listener.assertErrors([expectedError(ParserErrorCode.EXPECTED_BODY, 9, 1)]);
   }
 
   void test_topLevel_getter() {
@@ -5378,20 +4746,15 @@
 
   void test_topLevelOperator_withFunction() {
     parseCompilationUnit('operator Function() x = null;',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 8)]
-            : [
-                // Should be generating an error here.
-              ]);
+        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 8)]);
   }
 
   void test_topLevelOperator_withoutOperator() {
     createParser('+(bool x, bool y) => x | y;');
     CompilationUnitMember member = parseFullCompilationUnitMember();
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 1)]
-        : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1)]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 1)]);
   }
 
   void test_topLevelOperator_withoutType() {
@@ -5410,18 +4773,11 @@
   }
 
   void test_topLevelVariable_withMetadata() {
-    parseCompilationUnit("String @A string;",
-        codes: usingFastaParser
-            ? [
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-              ]
-            : [
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-              ]);
+    parseCompilationUnit("String @A string;", codes: [
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
+    ]);
   }
 
   void test_typedef_incomplete() {
@@ -5435,29 +4791,15 @@
 main() {
   Function<
 }
-''',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 49, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 51, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 51, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 51, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 55, 8)
-              ]);
+''', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 49, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 51, 1),
+    ]);
   }
 
   void test_typedef_namedFunction() {
     parseCompilationUnit('typedef void Function();',
-        codes: usingFastaParser
-            ? [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]
-            : [
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-                ParserErrorCode.MISSING_TYPEDEF_PARAMETERS
-              ]);
+        codes: [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]);
   }
 
   void test_typedefInClass_withoutReturnType() {
@@ -5473,48 +4815,32 @@
   void test_unexpectedCommaThenInterpolation() {
     // https://github.com/Dart-Code/Dart-Code/issues/1548
     parseCompilationUnit(r"main() { String s = 'a' 'b', 'c$foo'; return s; }",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 2),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 2),
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 2),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 1),
-              ]);
+        errors: [
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 2),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 2),
+        ]);
   }
 
   void test_unexpectedTerminatorForParameterGroup_named() {
     createParser('(a, b})');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_TOKEN
-              : ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
-          5,
-          1)
-    ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
   }
 
   void test_unexpectedTerminatorForParameterGroup_optional() {
     createParser('(a, b])');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP, 5, 1)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
   }
 
   void test_unexpectedToken_endOfFieldDeclarationStatement() {
     parseStatement("String s = (null));", expectedEndOffset: 17);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1)]
-        : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 17, 1)]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1)]);
   }
 
   void test_unexpectedToken_invalidPostfixExpression() {
@@ -5538,14 +4864,8 @@
     createParser('class C { int x; ; int y;}');
     ClassDeclaration declaration = parseFullCompilationUnitMember();
     expectNotNullIfNoErrors(declaration);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_CLASS_MEMBER
-              : ParserErrorCode.UNEXPECTED_TOKEN,
-          17,
-          1)
-    ]);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 17, 1)]);
   }
 
   void test_unexpectedToken_semicolonBetweenCompilationUnitMembers() {
@@ -5640,16 +4960,11 @@
     expectNotNullIfNoErrors(expression);
     listener.assertErrors(
         [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
-    if (usingFastaParser) {
-      BinaryExpression binaryExpression = expression;
-      expect(binaryExpression.leftOperand.isSynthetic, isTrue);
-      expect(binaryExpression.rightOperand.isSynthetic, isFalse);
-      SimpleIdentifier identifier = binaryExpression.rightOperand;
-      expect(identifier.name, 'x');
-    } else {
-      var identifier = expression as SimpleIdentifier;
-      expect(identifier.isSynthetic, isTrue);
-    }
+    BinaryExpression binaryExpression = expression;
+    expect(binaryExpression.leftOperand.isSynthetic, isTrue);
+    expect(binaryExpression.rightOperand.isSynthetic, isFalse);
+    SimpleIdentifier identifier = binaryExpression.rightOperand;
+    expect(identifier.name, 'x');
   }
 
   void test_varAndType_field() {
@@ -5661,9 +4976,7 @@
     // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
     // this would be a better error message.
     parseStatement("var int x;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]
-        : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)]);
+    listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]);
   }
 
   void test_varAndType_parameter() {
@@ -5672,9 +4985,7 @@
     createParser('(var int x)');
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 1, 3)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+    listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 1, 3)]);
   }
 
   void test_varAndType_topLevelVariable() {
@@ -5685,33 +4996,25 @@
   void test_varAsTypeName_as() {
     parseExpression("x as var",
         expectedEndOffset: 5,
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 3)]
-            : [expectedError(ParserErrorCode.VAR_AS_TYPE_NAME, 7, 3)]);
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 3)]);
   }
 
   void test_varClass() {
-    parseCompilationUnit("var class C {}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `var` as a malformed top level var
-                // and `class` as the start of a class declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 5),
-              ]
-            : [expectedError(ParserErrorCode.VAR_CLASS, 0, 3)]);
+    parseCompilationUnit("var class C {}", errors: [
+      // Fasta interprets the `var` as a malformed top level var
+      // and `class` as the start of a class declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 5),
+    ]);
   }
 
   void test_varEnum() {
-    parseCompilationUnit("var enum E {ONE}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `var` as a malformed top level var
-                // and `enum` as the start of an enum declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 4),
-              ]
-            : [expectedError(ParserErrorCode.VAR_ENUM, 0, 3)]);
+    parseCompilationUnit("var enum E {ONE}", errors: [
+      // Fasta interprets the `var` as a malformed top level var
+      // and `enum` as the start of an enum declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 4),
+    ]);
   }
 
   void test_varReturnType() {
@@ -5723,15 +5026,12 @@
   }
 
   void test_varTypedef() {
-    parseCompilationUnit("var typedef F();",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `var` as a malformed top level var
-                // and `typedef` as the start of an typedef declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 7),
-              ]
-            : [expectedError(ParserErrorCode.VAR_TYPEDEF, 0, 3)]);
+    parseCompilationUnit("var typedef F();", errors: [
+      // Fasta interprets the `var` as a malformed top level var
+      // and `typedef` as the start of an typedef declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 7),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 7),
+    ]);
   }
 
   void test_voidParameter() {
@@ -5814,18 +5114,10 @@
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
     // fasta scanner generates '(a, {b, c]})' where '}' is synthetic
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
-      ]);
-    } else {
-      listener.assertErrors([
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(
-            ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, 9, 1)
-      ]);
-    }
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+    ]);
   }
 
   void test_wrongTerminatorForParameterGroup_optional() {
@@ -5833,25 +5125,13 @@
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
     // fasta scanner generates '(a, [b, c}])' where ']' is synthetic
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
-      ]);
-    } else {
-      listener.assertErrors([
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 4, 1),
-        expectedError(
-            ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, 10, 1)
-      ]);
-    }
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+    ]);
   }
 }
 
-@reflectiveTest
-class ExpressionParserTest extends ParserTestCase
-    with ExpressionParserTestMixin {}
-
 mixin ExpressionParserTestMixin implements AbstractParserTestCase {
   void test_namedArgument() {
     var invocation = parseExpression('m(a: 1, b: 2)') as MethodInvocation;
@@ -6467,7 +5747,7 @@
   }
 
   void test_parseExpression_assign_compound() {
-    if (usingFastaParser && AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
+    if (AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
       Expression expression = parseExpression('x ||= y');
       var assignmentExpression = expression as AssignmentExpression;
       expect(assignmentExpression.leftHandSide, isNotNull);
@@ -6487,13 +5767,10 @@
   }
 
   void test_parseExpression_constAndTypeParameters() {
-    Expression expression = parseExpression('const <E>',
-        codes: usingFastaParser
-            ? [
-                // TODO(danrubel): Improve this error message.
-                ParserErrorCode.EXPECTED_TOKEN
-              ]
-            : [ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL]);
+    Expression expression = parseExpression('const <E>', codes: [
+      // TODO(danrubel): Improve this error message.
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
     expect(expression, isNotNull);
   }
 
@@ -6708,37 +5985,19 @@
     FunctionExpression expression =
         parseFunctionExpression('const <E>(E i) => i++');
     expect(expression, isNotNull);
-    assertErrorsWithCodes(usingFastaParser
-        ? [ParserErrorCode.UNEXPECTED_TOKEN]
-        : [
-            ParserErrorCode.EXPECTED_TOKEN,
-            ParserErrorCode.EXPECTED_TOKEN,
-            ParserErrorCode.MISSING_IDENTIFIER,
-            ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR,
-            ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
-          ]);
+    assertErrorsWithCodes([ParserErrorCode.UNEXPECTED_TOKEN]);
     expect(expression.body, isNotNull);
-    if (usingFastaParser) {
-      expect(expression.typeParameters, isNotNull);
-      expect(expression.parameters, isNotNull);
-      expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
-    }
+    expect(expression.typeParameters, isNotNull);
+    expect(expression.parameters, isNotNull);
+    expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
   }
 
   void test_parseFunctionExpression_functionInPlaceOfTypeName() {
     Expression expression = parseExpression('<test(' ', (){});>[0, 1, 2]',
-        codes: usingFastaParser
-            ? [ParserErrorCode.EXPECTED_TOKEN]
-            : [
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
-              ]);
+        codes: [ParserErrorCode.EXPECTED_TOKEN]);
     expect(expression, isNotNull);
-    if (usingFastaParser) {
-      ListLiteral literal = expression;
-      expect(literal.typeArguments.arguments, hasLength(1));
-    }
+    ListLiteral literal = expression;
+    expect(literal.typeArguments.arguments, hasLength(1));
   }
 
   void test_parseFunctionExpression_typeParameters() {
@@ -6873,9 +6132,6 @@
   }
 
   void test_parseInstanceCreationExpression_type_named_typeArguments_34403() {
-    if (!usingFastaParser) {
-      return;
-    }
     InstanceCreationExpressionImpl expression =
         parseExpression('new a.b.c<C>()', errors: [
       expectedError(
@@ -7491,9 +6747,7 @@
 
   void test_parseRelationalExpression_as_chained() {
     AsExpression asExpression = parseExpression('x as Y as Z',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]
-            : []);
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]);
     expect(asExpression, isNotNull);
     SimpleIdentifier identifier = asExpression.expression;
     expect(identifier.name, 'x');
@@ -7566,9 +6820,7 @@
 
   void test_parseRelationalExpression_is_chained() {
     IsExpression isExpression = parseExpression('x is Y is! Z',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]
-            : []);
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]);
     expect(isExpression, isNotNull);
     SimpleIdentifier identifier = isExpression.expression;
     expect(identifier.name, 'x');
@@ -8193,11 +7445,6 @@
   }
 }
 
-/// Tests of the analyzer parser based on [FormalParameterParserTestMixin].
-@reflectiveTest
-class FormalParameterParserTest extends ParserTestCase
-    with FormalParameterParserTestMixin {}
-
 /// The class [FormalParameterParserTestMixin] defines parser tests that test
 /// the parsing of formal parameters.
 mixin FormalParameterParserTestMixin implements AbstractParserTestCase {
@@ -8952,12 +8199,7 @@
 
   void test_parseFormalParameterList_prefixedType_partial() {
     FormalParameterList list = parseFormalParameterList('(io.)', errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_TYPE_NAME
-              : ParserErrorCode.MISSING_IDENTIFIER,
-          4,
-          1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
       expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
     ]);
     expect(list, isNotNull);
@@ -8978,12 +8220,7 @@
 
   void test_parseFormalParameterList_prefixedType_partial2() {
     FormalParameterList list = parseFormalParameterList('(io.,a)', errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_TYPE_NAME
-              : ParserErrorCode.MISSING_IDENTIFIER,
-          4,
-          1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
       expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
     ]);
     expect(list, isNotNull);
@@ -8998,8 +8235,7 @@
 
   void test_parseNormalFormalParameter_field_const_noType() {
     NormalFormalParameter parameter = parseNormalFormalParameter('const this.a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
     expect(parameter, isNotNull);
     expect(parameter, isFieldFormalParameter);
     FieldFormalParameter fieldParameter = parameter;
@@ -9012,8 +8248,7 @@
   void test_parseNormalFormalParameter_field_const_type() {
     NormalFormalParameter parameter = parseNormalFormalParameter(
         'const A this.a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
     expect(parameter, isNotNull);
     expect(parameter, isFieldFormalParameter);
     FieldFormalParameter fieldParameter = parameter;
@@ -9257,8 +8492,7 @@
 
   void test_parseNormalFormalParameter_simple_const_noType() {
     NormalFormalParameter parameter = parseNormalFormalParameter('const a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
     expect(parameter, isNotNull);
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
@@ -9269,8 +8503,7 @@
 
   void test_parseNormalFormalParameter_simple_const_type() {
     NormalFormalParameter parameter = parseNormalFormalParameter('const A a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
     expect(parameter, isNotNull);
     expect(parameter, isSimpleFormalParameter);
     SimpleFormalParameter simpleParameter = parameter;
@@ -9377,6 +8610,244 @@
   }
 }
 
+/// Proxy implementation of the analyzer parser, implemented in terms of the
+/// Fasta parser.
+///
+/// This allows many of the analyzer parser tests to be run on Fasta, even if
+/// they call into the analyzer parser class directly.
+class ParserProxy extends analyzer.Parser {
+  /// The error listener to which scanner and parser errors will be reported.
+  final GatheringErrorListener errorListener;
+
+  ForwardingTestListener _eventListener;
+
+  final int expectedEndOffset;
+
+  /// Creates a [ParserProxy] which is prepared to begin parsing at the given
+  /// Fasta token.
+  factory ParserProxy(Token firstToken, FeatureSet featureSet,
+      {bool allowNativeClause = false, int expectedEndOffset}) {
+    TestSource source = TestSource();
+    var errorListener = GatheringErrorListener(checkRanges: true);
+    return ParserProxy._(firstToken, source, errorListener, featureSet,
+        allowNativeClause: allowNativeClause,
+        expectedEndOffset: expectedEndOffset);
+  }
+
+  ParserProxy._(Token firstToken, Source source, this.errorListener,
+      FeatureSet featureSet,
+      {bool allowNativeClause = false, this.expectedEndOffset})
+      : super(source, errorListener,
+            featureSet: featureSet, allowNativeClause: allowNativeClause) {
+    _eventListener = ForwardingTestListener(astBuilder);
+    fastaParser.listener = _eventListener;
+    currentToken = firstToken;
+  }
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  Annotation parseAnnotation() {
+    return _run('MetadataStar', () {
+      currentToken = fastaParser
+          .parseMetadata(fastaParser.syntheticPreviousToken(currentToken))
+          .next;
+      return astBuilder.pop() as Annotation;
+    });
+  }
+
+  ArgumentList parseArgumentList() {
+    return _run('unspecified', () {
+      currentToken = fastaParser
+          .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
+          .next;
+      var result = astBuilder.pop();
+      return result is MethodInvocation
+          ? result.argumentList
+          : result as ArgumentList;
+    });
+  }
+
+  ClassMember parseClassMember(String className) {
+    return _run('ClassOrMixinBody', () {
+      astBuilder.classDeclaration = astFactory.classDeclaration(
+        null,
+        null,
+        null,
+        Token(Keyword.CLASS, 0),
+        astFactory.simpleIdentifier(
+            fasta.StringToken.fromString(TokenType.IDENTIFIER, className, 6)),
+        null,
+        null,
+        null,
+        null,
+        null /* leftBracket */,
+        <ClassMember>[],
+        null /* rightBracket */,
+      ) as ClassDeclarationImpl;
+      // TODO(danrubel): disambiguate between class and mixin
+      currentToken = fastaParser.parseClassMember(currentToken, className);
+      //currentToken = fastaParser.parseMixinMember(currentToken);
+      ClassDeclaration declaration = astBuilder.classDeclaration;
+      astBuilder.classDeclaration = null;
+      return declaration.members.isNotEmpty ? declaration.members[0] : null;
+    });
+  }
+
+  List<Combinator> parseCombinators() {
+    return _run('Import', () {
+      currentToken = fastaParser
+          .parseCombinatorStar(fastaParser.syntheticPreviousToken(currentToken))
+          .next;
+      return astBuilder.pop() as List<Combinator>;
+    });
+  }
+
+  List<CommentReference> parseCommentReferences(
+      List<DocumentationCommentToken> tokens) {
+    for (int index = 0; index < tokens.length - 1; ++index) {
+      Token next = tokens[index].next;
+      if (next == null) {
+        tokens[index].setNext(tokens[index + 1]);
+      } else {
+        expect(next, tokens[index + 1]);
+      }
+    }
+    expect(tokens[tokens.length - 1].next, isNull);
+    List<CommentReference> references =
+        astBuilder.parseCommentReferences(tokens.first);
+    if (astBuilder.stack.isNotEmpty) {
+      throw 'Expected empty stack, but found:'
+          '\n  ${astBuilder.stack.values.join('\n  ')}';
+    }
+    return references;
+  }
+
+  @override
+  CompilationUnit parseCompilationUnit2() {
+    var result = super.parseCompilationUnit2();
+    expect(currentToken.isEof, isTrue, reason: currentToken.lexeme);
+    expect(astBuilder.stack, hasLength(0));
+    _eventListener.expectEmpty();
+    return result;
+  }
+
+  @override
+  Configuration parseConfiguration() {
+    return _run('ConditionalUris', () => super.parseConfiguration());
+  }
+
+  @override
+  DottedName parseDottedName() {
+    return _run('unspecified', () => super.parseDottedName());
+  }
+
+  @override
+  Expression parseExpression2() {
+    return _run('unspecified', () => super.parseExpression2());
+  }
+
+  @override
+  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
+    return _run('unspecified',
+        () => super.parseFormalParameterList(inFunctionType: inFunctionType));
+  }
+
+  @override
+  FunctionBody parseFunctionBody(
+      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
+    Token lastToken;
+    FunctionBody body = _run('unspecified', () {
+      FunctionBody body =
+          super.parseFunctionBody(mayBeEmpty, emptyErrorCode, inExpression);
+      lastToken = currentToken;
+      currentToken = currentToken.next;
+      return body;
+    });
+    if (!inExpression) {
+      if (![';', '}'].contains(lastToken.lexeme)) {
+        fail('Expected ";" or "}", but found: ${lastToken.lexeme}');
+      }
+    }
+    return body;
+  }
+
+  @override
+  Expression parsePrimaryExpression() {
+    return _run('unspecified', () => super.parsePrimaryExpression());
+  }
+
+  @override
+  Statement parseStatement(Token token) {
+    return _run('unspecified', () => super.parseStatement(token));
+  }
+
+  @override
+  Statement parseStatement2() {
+    return _run('unspecified', () => super.parseStatement2());
+  }
+
+  @override
+  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
+    return _run(
+        'CompilationUnit', () => super.parseTopLevelDeclaration(isDirective));
+  }
+
+  @override
+  TypeAnnotation parseTypeAnnotation(bool inExpression) {
+    return _run('unspecified', () => super.parseTypeAnnotation(inExpression));
+  }
+
+  @override
+  TypeArgumentList parseTypeArgumentList() {
+    return _run('unspecified', () => super.parseTypeArgumentList());
+  }
+
+  @override
+  TypeName parseTypeName(bool inExpression) {
+    return _run('unspecified', () => super.parseTypeName(inExpression));
+  }
+
+  @override
+  TypeParameter parseTypeParameter() {
+    return _run('unspecified', () => super.parseTypeParameter());
+  }
+
+  @override
+  TypeParameterList parseTypeParameterList() {
+    return _run('unspecified', () => super.parseTypeParameterList());
+  }
+
+  /// Runs the specified function and returns the result. It checks the
+  /// enclosing listener events, that the parse consumed all of the tokens, and
+  /// that the result stack is empty.
+  _run(String enclosingEvent, Function() f) {
+    _eventListener.begin(enclosingEvent);
+
+    // Simulate error handling of parseUnit by skipping error tokens
+    // before parsing and reporting them after parsing is complete.
+    Token errorToken = currentToken;
+    currentToken = fastaParser.skipErrorTokens(currentToken);
+    var result = f();
+    fastaParser.reportAllErrorTokens(errorToken);
+
+    _eventListener.end(enclosingEvent);
+
+    String lexeme = currentToken is ErrorToken
+        ? currentToken.runtimeType.toString()
+        : currentToken.lexeme;
+    if (expectedEndOffset == null) {
+      expect(currentToken.isEof, isTrue, reason: lexeme);
+    } else {
+      expect(currentToken.offset, expectedEndOffset, reason: lexeme);
+    }
+    expect(astBuilder.stack, hasLength(0));
+    expect(astBuilder.directives, hasLength(0));
+    expect(astBuilder.declarations, hasLength(0));
+    return result;
+  }
+}
+
 /// Implementation of [AbstractParserTestCase] specialized for testing the
 /// analyzer parser.
 class ParserTestCase with ParserTestHelpers implements AbstractParserTestCase {
@@ -9408,10 +8879,7 @@
   ///
   /// This field is typically initialized by invoking [createParser].
   @override
-  Parser parser;
-
-  @override
-  bool get usingFastaParser => Parser.useFasta;
+  analyzer.Parser parser;
 
   @override
   void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
@@ -9432,13 +8900,15 @@
     LanguageVersionToken languageVersion,
     FeatureSet featureSet,
   }) {
+    featureSet ??= FeatureSet.latestLanguageVersion();
     Source source = TestSource();
     listener = GatheringErrorListener();
 
-    ScannerResult result = scanString(content, includeComments: true);
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
     listener.setLineInfo(source, result.lineStarts);
 
-    parser = Parser(
+    parser = analyzer.Parser(
       source,
       listener,
       featureSet: featureSet,
@@ -9475,36 +8945,23 @@
   @override
   Expression parseAssignableSelector(String code, bool optional,
       {bool allowConditional = true}) {
-    if (usingFastaParser) {
-      if (optional) {
-        if (code.isEmpty) {
-          createParser('foo');
-        } else {
-          createParser('(foo)$code');
-        }
+    if (optional) {
+      if (code.isEmpty) {
+        createParser('foo');
       } else {
-        createParser('foo$code');
+        createParser('(foo)$code');
       }
-      return parser.parseExpression2();
     } else {
-      Expression prefix =
-          astFactory.simpleIdentifier(StringToken(TokenType.STRING, 'foo', 0));
-      createParser(code);
-      return parser.parseAssignableSelector(prefix, optional,
-          allowConditional: allowConditional);
+      createParser('foo$code');
     }
+    return parser.parseExpression2();
   }
 
   @override
   AwaitExpression parseAwaitExpression(String code) {
-    if (usingFastaParser) {
-      createParser('() async => $code');
-      var function = parser.parseExpression2() as FunctionExpression;
-      return (function.body as ExpressionFunctionBody).expression;
-    } else {
-      createParser(code);
-      return parser.parseAwaitExpression();
-    }
+    createParser('() async => $code');
+    var function = parser.parseExpression2() as FunctionExpression;
+    return (function.body as ExpressionFunctionBody).expression;
   }
 
   @override
@@ -9527,14 +8984,9 @@
 
   @override
   Expression parseCascadeSection(String code) {
-    if (usingFastaParser) {
-      var statement = parseStatement('null$code;') as ExpressionStatement;
-      var cascadeExpression = statement.expression as CascadeExpression;
-      return cascadeExpression.cascadeSections.first;
-    } else {
-      createParser(code);
-      return parser.parseCascadeSection();
-    }
+    var statement = parseStatement('null$code;') as ExpressionStatement;
+    var cascadeExpression = statement.expression as CascadeExpression;
+    return cascadeExpression.cascadeSections.first;
   }
 
   @override
@@ -9569,10 +9021,11 @@
     Source source = TestSource();
     GatheringErrorListener listener = GatheringErrorListener();
 
-    ScannerResult result = scanString(content, includeComments: true);
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
     listener.setLineInfo(source, result.lineStarts);
 
-    Parser parser = Parser(
+    analyzer.Parser parser = analyzer.Parser(
       source,
       listener,
       featureSet: FeatureSet.forTesting(),
@@ -9596,9 +9049,10 @@
     Source source = NonExistingSource.unknown;
     listener ??= AnalysisErrorListener.NULL_LISTENER;
 
-    ScannerResult result = scanString(content, includeComments: true);
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
 
-    Parser parser = Parser(
+    analyzer.Parser parser = analyzer.Parser(
       source,
       listener,
       featureSet: FeatureSet.forTesting(),
@@ -9671,16 +9125,11 @@
 
   @override
   List<Expression> parseExpressionList(String code) {
-    if (usingFastaParser) {
-      createParser('[$code]');
-      return (parser.parseExpression2() as ListLiteral)
-          .elements
-          .toList()
-          .cast<Expression>();
-    } else {
-      createParser(code);
-      return parser.parseExpressionList();
-    }
+    createParser('[$code]');
+    return (parser.parseExpression2() as ListLiteral)
+        .elements
+        .toList()
+        .cast<Expression>();
   }
 
   @override
@@ -9692,26 +9141,19 @@
   @override
   FormalParameter parseFormalParameter(String code, ParameterKind kind,
       {List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
-    if (usingFastaParser) {
-      String parametersCode;
-      if (kind == ParameterKind.REQUIRED) {
-        parametersCode = '($code)';
-      } else if (kind == ParameterKind.POSITIONAL) {
-        parametersCode = '([$code])';
-      } else if (kind == ParameterKind.NAMED) {
-        parametersCode = '({$code})';
-      } else {
-        fail('$kind');
-      }
-      FormalParameterList list = parseFormalParameterList(parametersCode,
-          inFunctionType: false, errorCodes: errorCodes);
-      return list.parameters.single;
+    String parametersCode;
+    if (kind == ParameterKind.REQUIRED) {
+      parametersCode = '($code)';
+    } else if (kind == ParameterKind.POSITIONAL) {
+      parametersCode = '([$code])';
+    } else if (kind == ParameterKind.NAMED) {
+      parametersCode = '({$code})';
     } else {
-      createParser(code);
-      FormalParameter parameter = parser.parseFormalParameter(kind);
-      assertErrorsWithCodes(errorCodes);
-      return parameter;
+      fail('$kind');
     }
+    FormalParameterList list = parseFormalParameterList(parametersCode,
+        inFunctionType: false, errorCodes: errorCodes);
+    return list.parameters.single;
   }
 
   @override
@@ -9732,15 +9174,12 @@
   /// Parses a single top level member of a compilation unit (other than a
   /// directive), including any comment and/or metadata that precedes it.
   @override
-  CompilationUnitMember parseFullCompilationUnitMember() => usingFastaParser
-      ? parser.parseCompilationUnit2().declarations.first
-      : parser.parseCompilationUnitMember(parser.parseCommentAndMetadata());
+  CompilationUnitMember parseFullCompilationUnitMember() =>
+      parser.parseCompilationUnit2().declarations.first;
 
   @override
   Directive parseFullDirective() {
-    return usingFastaParser
-        ? (parser as ParserAdapter).parseTopLevelDeclaration(true)
-        : parser.parseDirective(parser.parseCommentAndMetadata());
+    return parser.parseTopLevelDeclaration(true);
   }
 
   @override
@@ -9752,50 +9191,30 @@
   @override
   InstanceCreationExpression parseInstanceCreationExpression(
       String code, Token newToken) {
-    if (usingFastaParser) {
-      createParser('$newToken $code');
-      return parser.parseExpression2();
-    } else {
-      createParser(code);
-      return parser.parseInstanceCreationExpression(newToken);
-    }
+    createParser('$newToken $code');
+    return parser.parseExpression2();
   }
 
   @override
   ListLiteral parseListLiteral(
       Token token, String typeArgumentsCode, String code) {
-    if (usingFastaParser) {
-      String sc = '';
-      if (token != null) {
-        sc += token.lexeme + ' ';
-      }
-      if (typeArgumentsCode != null) {
-        sc += typeArgumentsCode;
-      }
-      sc += code;
-      createParser(sc);
-      return parser.parseExpression2();
-    } else {
-      TypeArgumentList typeArguments;
-      if (typeArgumentsCode != null) {
-        createParser(typeArgumentsCode);
-        typeArguments = parser.parseTypeArgumentList();
-      }
-      createParser(code);
-      return parser.parseListLiteral(token, typeArguments);
+    String sc = '';
+    if (token != null) {
+      sc += token.lexeme + ' ';
     }
+    if (typeArgumentsCode != null) {
+      sc += typeArgumentsCode;
+    }
+    sc += code;
+    createParser(sc);
+    return parser.parseExpression2();
   }
 
   @override
   TypedLiteral parseListOrMapLiteral(Token modifier, String code) {
-    if (usingFastaParser) {
-      String literalCode = modifier != null ? '$modifier $code' : code;
-      createParser(literalCode);
-      return parser.parseExpression2() as TypedLiteral;
-    } else {
-      createParser(code);
-      return parser.parseListOrMapLiteral(modifier);
-    }
+    String literalCode = modifier != null ? '$modifier $code' : code;
+    createParser(literalCode);
+    return parser.parseExpression2() as TypedLiteral;
   }
 
   @override
@@ -9813,37 +9232,22 @@
   @override
   SetOrMapLiteral parseMapLiteral(
       Token token, String typeArgumentsCode, String code) {
-    if (usingFastaParser) {
-      String sc = '';
-      if (token != null) {
-        sc += token.lexeme + ' ';
-      }
-      if (typeArgumentsCode != null) {
-        sc += typeArgumentsCode;
-      }
-      sc += code;
-      createParser(sc);
-      return parser.parseExpression2() as SetOrMapLiteral;
-    } else {
-      TypeArgumentList typeArguments;
-      if (typeArgumentsCode != null) {
-        createParser(typeArgumentsCode);
-        typeArguments = parser.parseTypeArgumentList();
-      }
-      createParser(code);
-      return parser.parseMapLiteral(token, typeArguments);
+    String sc = '';
+    if (token != null) {
+      sc += token.lexeme + ' ';
     }
+    if (typeArgumentsCode != null) {
+      sc += typeArgumentsCode;
+    }
+    sc += code;
+    createParser(sc);
+    return parser.parseExpression2() as SetOrMapLiteral;
   }
 
   @override
   MapLiteralEntry parseMapLiteralEntry(String code) {
-    if (usingFastaParser) {
-      var mapLiteral = parseMapLiteral(null, null, '{ $code }');
-      return mapLiteral.elements.single;
-    } else {
-      createParser(code);
-      return parser.parseMapLiteralEntry();
-    }
+    var mapLiteral = parseMapLiteral(null, null, '{ $code }');
+    return mapLiteral.elements.single;
   }
 
   @override
@@ -9862,17 +9266,9 @@
   NormalFormalParameter parseNormalFormalParameter(String code,
       {bool inFunctionType = false,
       List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
-    if (usingFastaParser) {
-      FormalParameterList list = parseFormalParameterList('($code)',
-          inFunctionType: inFunctionType, errorCodes: errorCodes);
-      return list.parameters.single;
-    } else {
-      createParser(code);
-      FormalParameter parameter =
-          parser.parseNormalFormalParameter(inFunctionType: inFunctionType);
-      assertErrorsWithCodes(errorCodes);
-      return parameter;
-    }
+    FormalParameterList list = parseFormalParameterList('($code)',
+        inFunctionType: inFunctionType, errorCodes: errorCodes);
+    return list.parameters.single;
   }
 
   @override
@@ -9930,10 +9326,11 @@
     Source source = TestSource();
     listener = GatheringErrorListener();
 
-    ScannerResult result = scanString(content, includeComments: true);
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
     listener.setLineInfo(source, result.lineStarts);
 
-    Parser parser = Parser(
+    analyzer.Parser parser = analyzer.Parser(
       source,
       listener,
       featureSet: FeatureSet.forTesting(),
@@ -9944,37 +9341,6 @@
     return statement;
   }
 
-  /// Parse the given source as a sequence of statements.
-  ///
-  /// @param source the source to be parsed
-  /// @param expectedCount the number of statements that are expected
-  /// @param errorCodes the error codes of the errors that are expected to be
-  ///          found
-  /// @return the statements that were parsed
-  /// @throws Exception if the source could not be parsed, if the number of
-  ///           statements does not match the expected count, if the compilation
-  ///           errors in the source do not match those that are expected, or if
-  ///           the result would have been `null`
-  List<Statement> parseStatements(String content, int expectedCount,
-      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
-    Source source = TestSource();
-    GatheringErrorListener listener = GatheringErrorListener();
-
-    ScannerResult result = scanString(content);
-    listener.setLineInfo(source, result.lineStarts);
-
-    Parser parser = Parser(
-      source,
-      listener,
-      featureSet: FeatureSet.forTesting(),
-    );
-    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    List<Statement> statements = parser.parseStatements(result.tokens);
-    expect(statements, hasLength(expectedCount));
-    listener.assertErrorsWithCodes(errorCodes);
-    return statements;
-  }
-
   @override
   Expression parseStringLiteral(String code) {
     createParser(code);
@@ -10007,15 +9373,8 @@
 
   @override
   VariableDeclarationList parseVariableDeclarationList(String code) {
-    if (usingFastaParser) {
-      var statement = parseStatement('$code;') as VariableDeclarationStatement;
-      return statement.variables;
-    } else {
-      createParser(code);
-      CommentAndMetadata commentAndMetadata = parser.parseCommentAndMetadata();
-      return parser
-          .parseVariableDeclarationListAfterMetadata(commentAndMetadata);
-    }
+    var statement = parseStatement('$code;') as VariableDeclarationStatement;
+    return statement.variables;
   }
 
   void setUp() {
@@ -10044,14 +9403,10 @@
   }
 }
 
-/// Tests of the analyzer parser based on [RecoveryParserTestMixin].
-@reflectiveTest
-class RecoveryParserTest extends ParserTestCase with RecoveryParserTestMixin {}
-
 /// The class `RecoveryParserTest` defines parser tests that test the parsing of
 /// invalid code sequences to ensure that the correct recovery steps are taken
 /// in the parser.
-mixin RecoveryParserTestMixin implements AbstractParserTestCase {
+mixin RecoveryParserTestMixin implements AbstractParserViaProxyTestCase {
   void test_additiveExpression_missing_LHS() {
     BinaryExpression expression =
         parseExpression("+ y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
@@ -10335,33 +9690,23 @@
   void test_classTypeAlias_withBody() {
     parseCompilationUnit(r'''
 class A {}
-class B = Object with A {}''',
-        codes: usingFastaParser
+class B = Object with A {}''', codes:
             // TODO(danrubel): Consolidate and improve error message.
-            ? [
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-                ParserErrorCode.EXPECTED_TOKEN
-              ]
-            : [ParserErrorCode.EXPECTED_TOKEN]);
+            [
+      ParserErrorCode.EXPECTED_EXECUTABLE,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
   }
 
   void test_combinator_badIdentifier() {
     createParser('import "/testB.dart" show @');
     parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0),
-            expectedError(
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 27, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0)
-          ]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 26, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
-            expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 27, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 27, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0)
+    ]);
   }
 
   void test_combinator_missingIdentifier() {
@@ -10446,17 +9791,6 @@
     expect(expression.rightOperand.isSynthetic, isTrue);
   }
 
-  void test_equalityExpression_precedence_relational_left() {
-    BinaryExpression expression = parseExpression("is ==", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    if (!usingFastaParser) {
-      expect(expression.leftOperand, isIsExpression);
-    }
-  }
-
   void test_equalityExpression_precedence_relational_right() {
     BinaryExpression expression = parseExpression("== is", codes: [
       ParserErrorCode.EXPECTED_TYPE_NAME,
@@ -10513,26 +9847,15 @@
     // The fasta parser does not use parseExpressionList when parsing for loops
     // and instead parseExpressionList is mapped to parseExpression('[$code]')
     // which allows and ignores an optional trailing comma.
-    if (usingFastaParser) {
-      assertNoErrors();
-      expect(result, hasLength(3));
-    } else {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 0)]);
-      expect(result, hasLength(4));
-      Expression syntheticExpression = result[3];
-      expect(syntheticExpression, isSimpleIdentifier);
-      expect(syntheticExpression.isSynthetic, isTrue);
-    }
+    assertNoErrors();
+    expect(result, hasLength(3));
   }
 
   void test_functionExpression_in_ConstructorFieldInitializer() {
     CompilationUnit unit =
         parseCompilationUnit("class A { A() : a = (){}; var v; }", codes: [
       ParserErrorCode.MISSING_IDENTIFIER,
-      usingFastaParser
-          ? ParserErrorCode.EXPECTED_CLASS_MEMBER
-          : ParserErrorCode.UNEXPECTED_TOKEN
+      ParserErrorCode.EXPECTED_CLASS_MEMBER
     ]);
     // Make sure we recovered and parsed "var v" correctly
     ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
@@ -10546,21 +9869,15 @@
   }
 
   void test_functionExpression_named() {
-    parseExpression("m(f() => 0);", expectedEndOffset: 11, codes: [
-      usingFastaParser
-          ? ParserErrorCode.NAMED_FUNCTION_EXPRESSION
-          : ParserErrorCode.EXPECTED_TOKEN
-    ]);
+    parseExpression("m(f() => 0);",
+        expectedEndOffset: 11,
+        codes: [ParserErrorCode.NAMED_FUNCTION_EXPRESSION]);
   }
 
   void test_ifStatement_noElse_statement() {
     parseStatement('if (x v) f(x);');
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)
-          ]);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
   }
 
   void test_importDirectivePartial_as() {
@@ -10621,26 +9938,17 @@
     Expression expression =
         (initializer as ConstructorFieldInitializer).expression;
     expect(expression, isNotNull);
-    expect(expression,
-        usingFastaParser ? isMethodInvocation : isParenthesizedExpression);
+    expect(expression, isMethodInvocation);
   }
 
   void test_incomplete_constructorInitializers_this() {
     createParser('C() : this {}');
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
-            expectedError(
-                ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
-            expectedError(
-                ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 11, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
+    ]);
   }
 
   void test_incomplete_constructorInitializers_thisField() {
@@ -10673,29 +9981,20 @@
 
   void test_incomplete_functionExpression() {
     var expression = parseExpression("() a => null",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]
-            : [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]);
-    if (usingFastaParser) {
-      FunctionExpression functionExpression = expression;
-      expect(functionExpression.parameters.parameters, hasLength(0));
-    }
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]);
+    FunctionExpression functionExpression = expression;
+    expect(functionExpression.parameters.parameters, hasLength(0));
   }
 
   void test_incomplete_functionExpression2() {
     var expression = parseExpression("() a {}",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]
-            : [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]);
-    if (usingFastaParser) {
-      FunctionExpression functionExpression = expression;
-      expect(functionExpression.parameters.parameters, hasLength(0));
-    }
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]);
+    FunctionExpression functionExpression = expression;
+    expect(functionExpression.parameters.parameters, hasLength(0));
   }
 
   void test_incomplete_returnType() {
-    if (usingFastaParser) {
-      parseCompilationUnit(r'''
+    parseCompilationUnit(r'''
 Map<Symbol, convertStringToSymbolMap(Map<String, dynamic> map) {
   if (map == null) return null;
   Map<Symbol, dynamic> result = new Map<Symbol, dynamic>();
@@ -10704,10 +10003,9 @@
   });
   return result;
 }''', errors: [
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 24),
-        expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3)
-      ]);
-    }
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 24),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3)
+    ]);
   }
 
   void test_incomplete_topLevelFunction() {
@@ -10716,14 +10014,10 @@
   }
 
   void test_incomplete_topLevelVariable() {
-    CompilationUnit unit = parseCompilationUnit("String",
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 6),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 6)
-              ]
-            : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 6)]);
+    CompilationUnit unit = parseCompilationUnit("String", errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 6),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 6)
+    ]);
     NodeList<CompilationUnitMember> declarations = unit.declarations;
     expect(declarations, hasLength(1));
     CompilationUnitMember member = declarations[0];
@@ -10732,9 +10026,7 @@
         (member as TopLevelVariableDeclaration).variables.variables;
     expect(variables, hasLength(1));
     SimpleIdentifier name = variables[0].name;
-    // Analyzer considers 'String' to be the type
-    // while fasta considers it to be the name.
-    expect(name.isSynthetic, usingFastaParser ? isFalse : isTrue);
+    expect(name.isSynthetic, isFalse);
   }
 
   void test_incomplete_topLevelVariable_const() {
@@ -10840,11 +10132,7 @@
 class C {
   static c
 }''', codes: [
-      // Fasta considers the `c` to be the type
-      // whereas analyzer considers it to be the identifier.
-      usingFastaParser
-          ? ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-          : ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
       ParserErrorCode.EXPECTED_TOKEN
     ]);
     NodeList<CompilationUnitMember> declarations = unit.declarations;
@@ -10862,7 +10150,7 @@
     NodeList<VariableDeclaration> fields = fieldList.variables;
     expect(fields, hasLength(1));
     VariableDeclaration field = fields[0];
-    expect(field.name.isSynthetic, usingFastaParser ? isFalse : isTrue);
+    expect(field.name.isSynthetic, isFalse);
   }
 
   void test_incompleteField_static2() {
@@ -10893,11 +10181,7 @@
 class C {
   A
 }''', codes: [
-      // Fasta considers the `c` to be the type
-      // whereas analyzer considers it to be the identifier.
-      usingFastaParser
-          ? ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-          : ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
       ParserErrorCode.EXPECTED_TOKEN
     ]);
     NodeList<CompilationUnitMember> declarations = unit.declarations;
@@ -10914,13 +10198,8 @@
     NodeList<VariableDeclaration> fields = fieldList.variables;
     expect(fields, hasLength(1));
     VariableDeclaration field = fields[0];
-    if (usingFastaParser) {
-      expect(type, isNull);
-      expect(field.name.name, 'A');
-    } else {
-      expect(type.name.name, 'A');
-      expect(field.name.isSynthetic, isTrue);
-    }
+    expect(type, isNull);
+    expect(field.name.name, 'A');
   }
 
   void test_incompleteField_var() {
@@ -11083,13 +10362,7 @@
   void test_incompleteTypeParameters3() {
     CompilationUnit unit = parseCompilationUnit(r'''
 class C<K extends L<T {
-}''',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
-              ]);
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1)]);
     // one class
     List<CompilationUnitMember> declarations = unit.declarations;
     expect(declarations, hasLength(1));
@@ -11109,72 +10382,42 @@
   }
 
   void test_invalidMapLiteral() {
-    parseCompilationUnit("class C { var f = Map<A, B> {}; }",
-        codes: usingFastaParser
-            ? [
-                // TODO(danrubel): Improve error message to indicate
-                // that "Map" should be removed.
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_KEYWORD_OPERATOR,
-                ParserErrorCode.MISSING_METHOD_PARAMETERS,
-                ParserErrorCode.EXPECTED_CLASS_MEMBER,
-              ]
-            : [
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_CLASS_MEMBER,
-                ParserErrorCode.EXPECTED_CLASS_MEMBER,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-              ]);
+    parseCompilationUnit("class C { var f = Map<A, B> {}; }", codes: [
+      // TODO(danrubel): Improve error message to indicate
+      // that "Map" should be removed.
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_KEYWORD_OPERATOR,
+      ParserErrorCode.MISSING_METHOD_PARAMETERS,
+      ParserErrorCode.EXPECTED_CLASS_MEMBER,
+    ]);
   }
 
   void test_invalidTypeParameters() {
     CompilationUnit unit = parseCompilationUnit(r'''
 class C {
   G<int double> g;
-}''',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 24, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 24, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 26, 1)
-              ]);
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6)]);
     // one class
     List<CompilationUnitMember> declarations = unit.declarations;
     expect(declarations, hasLength(1));
     // validate members
-    if (usingFastaParser) {
-      ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
-      expect(classDecl.members, hasLength(1));
-      FieldDeclaration fields = classDecl.members.first;
-      expect(fields.fields.variables, hasLength(1));
-      VariableDeclaration field = fields.fields.variables.first;
-      expect(field.name.name, 'g');
-    }
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+    expect(classDecl.members, hasLength(1));
+    FieldDeclaration fields = classDecl.members.first;
+    expect(fields.fields.variables, hasLength(1));
+    VariableDeclaration field = fields.fields.variables.first;
+    expect(field.name.name, 'g');
   }
 
   void test_isExpression_noType() {
     CompilationUnit unit = parseCompilationUnit(
         "class Bar<T extends Foo> {m(x){if (x is ) return;if (x is !)}}",
-        codes: usingFastaParser
-            ? [
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
-              ]
-            : [
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.MISSING_STATEMENT
-              ]);
+        codes: [
+          ParserErrorCode.EXPECTED_TYPE_NAME,
+          ParserErrorCode.EXPECTED_TYPE_NAME,
+          ParserErrorCode.MISSING_IDENTIFIER,
+          ParserErrorCode.EXPECTED_TOKEN,
+        ]);
     ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
     MethodDeclaration method = declaration.members[0] as MethodDeclaration;
     BlockFunctionBody body = method.body as BlockFunctionBody;
@@ -11186,170 +10429,75 @@
     TypeAnnotation type = expression.type;
     expect(type, isNotNull);
     expect(type is TypeName && type.name.isSynthetic, isTrue);
-    if (usingFastaParser) {
-      ExpressionStatement thenStatement = ifStatement.thenStatement;
-      expect(thenStatement.semicolon.isSynthetic, isTrue);
-      SimpleIdentifier simpleId = thenStatement.expression;
-      expect(simpleId.isSynthetic, isTrue);
-    } else {
-      expect(ifStatement.thenStatement, isEmptyStatement);
-    }
+    ExpressionStatement thenStatement = ifStatement.thenStatement;
+    expect(thenStatement.semicolon.isSynthetic, isTrue);
+    SimpleIdentifier simpleId = thenStatement.expression;
+    expect(simpleId.isSynthetic, isTrue);
   }
 
   void test_issue_34610_get() {
-    final unit = parseCompilationUnit('class C { get C.named => null; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.GETTER_CONSTRUCTOR, 10, 3),
-                expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1),
-              ]);
+    final unit =
+        parseCompilationUnit('class C { get C.named => null; }', errors: [
+      expectedError(ParserErrorCode.GETTER_CONSTRUCTOR, 10, 3),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
+    ]);
     ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration method = declaration.members[0];
-      expect(method.name.name, 'named');
-      expect(method.parameters, isNotNull);
-    } else {
-      MethodDeclaration method = declaration.members[0];
-      expect(method.name.name, 'C');
-      expect(method.isGetter, isTrue);
-      expect(method.parameters, isNull);
-    }
+    ConstructorDeclaration method = declaration.members[0];
+    expect(method.name.name, 'named');
+    expect(method.parameters, isNotNull);
   }
 
   void test_issue_34610_initializers() {
     final unit = parseCompilationUnit('class C { C.named : super(); }',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 19),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 19),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 19),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 20, 25),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 20, 25),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 26),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 26),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 26, 27),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 26, 27),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 27, 28),
-              ]);
+        errors: [
+          expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)
+        ]);
     ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration constructor = declaration.members[0];
-      expect(constructor.name.name, 'named');
-      expect(constructor.parameters, isNotNull);
-      expect(constructor.parameters.parameters, hasLength(0));
-    } else {
-      FieldDeclaration field = declaration.members[0];
-      expect(field.fields.type.toSource(), 'C.named');
-    }
+    ConstructorDeclaration constructor = declaration.members[0];
+    expect(constructor.name.name, 'named');
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, hasLength(0));
   }
 
   void test_issue_34610_missing_param() {
-    final unit = parseCompilationUnit('class C { C => null; }',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 1),
-              ]);
+    final unit = parseCompilationUnit('class C { C => null; }', errors: [
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)
+    ]);
     ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration constructor = declaration.members[0];
-      expect(constructor.name, isNull);
-      expect(constructor.parameters, isNotNull);
-      expect(constructor.parameters.parameters, hasLength(0));
-    } else {
-      FieldDeclaration field = declaration.members[0];
-      expect(field.fields.type.toSource(), 'C');
-    }
+    ConstructorDeclaration constructor = declaration.members[0];
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, hasLength(0));
   }
 
   void test_issue_34610_named_missing_param() {
-    final unit = parseCompilationUnit('class C { C.named => null; }',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 1),
-              ]);
+    final unit = parseCompilationUnit('class C { C.named => null; }', errors: [
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)
+    ]);
     ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration constructor = declaration.members[0];
-      expect(constructor.name.name, 'named');
-      expect(constructor.parameters, isNotNull);
-      expect(constructor.parameters.parameters, hasLength(0));
-    } else {
-      FieldDeclaration field = declaration.members[0];
-      expect(field.fields.type.toSource(), 'C.named');
-    }
+    ConstructorDeclaration constructor = declaration.members[0];
+    expect(constructor.name.name, 'named');
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, hasLength(0));
   }
 
   void test_issue_34610_set() {
-    final unit = parseCompilationUnit('class C { set C.named => null; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.SETTER_CONSTRUCTOR, 10, 3),
-                expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
-                expectedError(
-                    ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1),
-              ]);
+    final unit =
+        parseCompilationUnit('class C { set C.named => null; }', errors: [
+      expectedError(ParserErrorCode.SETTER_CONSTRUCTOR, 10, 3),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
+    ]);
     ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration method = declaration.members[0];
-      expect(method.name.name, 'named');
-      expect(method.parameters, isNotNull);
-      expect(method.parameters.parameters, hasLength(0));
-    } else {
-      MethodDeclaration method = declaration.members[0];
-      expect(method.name.name, 'C');
-      expect(method.isSetter, isTrue);
-      expect(method.parameters, isNotNull);
-      expect(method.parameters.parameters, hasLength(1));
-    }
+    ConstructorDeclaration method = declaration.members[0];
+    expect(method.name.name, 'named');
+    expect(method.parameters, isNotNull);
+    expect(method.parameters.parameters, hasLength(0));
   }
 
   void test_keywordInPlaceOfIdentifier() {
     // TODO(brianwilkerson) We could do better with this.
     parseCompilationUnit("do() {}",
-        codes: usingFastaParser
-            ? [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]
-            : [
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-                ParserErrorCode.UNEXPECTED_TOKEN
-              ]);
+        codes: [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]);
   }
 
   void test_logicalAndExpression_missing_LHS() {
@@ -11465,12 +10613,7 @@
   int length {}
   void foo() {}
 }''', errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_METHOD_PARAMETERS
-              : ParserErrorCode.MISSING_GET,
-          16,
-          6)
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 16, 6)
     ]);
     expect(unit, isNotNull);
     ClassDeclaration classDeclaration =
@@ -11489,18 +10632,9 @@
     expectNotNullIfNoErrors(member);
     listener.assertErrors(
         [expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1)]);
-    if (usingFastaParser) {
-      // TODO(danrubel): Consider generating a sub method so that the
-      // existing annotation can be associated with a class member.
-      expect(member, isNull);
-    } else {
-      expect(member, isMethodDeclaration);
-      MethodDeclaration method = member;
-      expect(method.documentationComment, isNull);
-      NodeList<Annotation> metadata = method.metadata;
-      expect(metadata, hasLength(1));
-      expect(metadata[0].name.name, "override");
-    }
+    // TODO(danrubel): Consider generating a sub method so that the
+    // existing annotation can be associated with a class member.
+    expect(member, isNull);
   }
 
   void test_missingSemicolon_varialeDeclarationList() {
@@ -11608,19 +10742,14 @@
   }
 
   void test_nonStringLiteralUri_import() {
-    parseCompilationUnit("import dart:io; class C {}",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 7, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 11, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 2)
-              ]
-            : [expectedError(ParserErrorCode.NON_STRING_LITERAL_AS_URI, 7, 4)]);
+    parseCompilationUnit("import dart:io; class C {}", errors: [
+      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 7, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 11, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 2)
+    ]);
   }
 
   void test_prefixExpression_missing_operand_minus() {
@@ -11634,11 +10763,9 @@
   void test_primaryExpression_argumentDefinitionTest() {
     SimpleIdentifier expression = parsePrimaryExpression('?a',
         expectedEndOffset: 0,
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]
-            : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 1)]);
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
     expectNotNullIfNoErrors(expression);
-    expect(expression.isSynthetic, usingFastaParser);
+    expect(expression.isSynthetic, isTrue);
   }
 
   void test_propertyAccess_missing_LHS_RHS() {
@@ -11646,18 +10773,10 @@
       ParserErrorCode.MISSING_IDENTIFIER,
       ParserErrorCode.MISSING_IDENTIFIER
     ]);
-    if (usingFastaParser) {
-      PrefixedIdentifier expression = result;
-      expect(expression.prefix.isSynthetic, isTrue);
-      expect(expression.period.lexeme, '.');
-      expect(expression.identifier.isSynthetic, isTrue);
-    } else {
-      PropertyAccess expression = result;
-      SimpleIdentifier target = expression.target;
-      expect(target.isSynthetic, isTrue);
-      expect(expression.operator.lexeme, '.');
-      expect(expression.propertyName.isSynthetic, isTrue);
-    }
+    PrefixedIdentifier expression = result;
+    expect(expression.prefix.isSynthetic, isTrue);
+    expect(expression.period.lexeme, '.');
+    expect(expression.identifier.isSynthetic, isTrue);
   }
 
   void test_relationalExpression_missing_LHS() {
@@ -11768,820 +10887,12 @@
   }
 }
 
-/// Tests of the analyzer parser based on [SimpleParserTestMixin].
-@reflectiveTest
-class SimpleParserTest extends ParserTestCase with SimpleParserTestMixin {
-  void test_computeStringValue_emptyInterpolationPrefix() {
-    expect(_computeStringValue("'''", true, false), "");
-  }
-
-  void test_computeStringValue_escape_b() {
-    expect(_computeStringValue("'\\b'", true, true), "\b");
-  }
-
-  void test_computeStringValue_escape_f() {
-    expect(_computeStringValue("'\\f'", true, true), "\f");
-  }
-
-  void test_computeStringValue_escape_n() {
-    expect(_computeStringValue("'\\n'", true, true), "\n");
-  }
-
-  void test_computeStringValue_escape_notSpecial() {
-    expect(_computeStringValue("'\\:'", true, true), ":");
-  }
-
-  void test_computeStringValue_escape_r() {
-    expect(_computeStringValue("'\\r'", true, true), "\r");
-  }
-
-  void test_computeStringValue_escape_t() {
-    expect(_computeStringValue("'\\t'", true, true), "\t");
-  }
-
-  void test_computeStringValue_escape_u_fixed() {
-    expect(_computeStringValue("'\\u4321'", true, true), "\u4321");
-  }
-
-  void test_computeStringValue_escape_u_variable() {
-    expect(_computeStringValue("'\\u{123}'", true, true), "\u0123");
-  }
-
-  void test_computeStringValue_escape_v() {
-    expect(_computeStringValue("'\\v'", true, true), "\u000B");
-  }
-
-  void test_computeStringValue_escape_x() {
-    expect(_computeStringValue("'\\xFF'", true, true), "\u00FF");
-  }
-
-  void test_computeStringValue_noEscape_single() {
-    expect(_computeStringValue("'text'", true, true), "text");
-  }
-
-  void test_computeStringValue_noEscape_triple() {
-    expect(_computeStringValue("'''text'''", true, true), "text");
-  }
-
-  void test_computeStringValue_raw_single() {
-    expect(_computeStringValue("r'text'", true, true), "text");
-  }
-
-  void test_computeStringValue_raw_triple() {
-    expect(_computeStringValue("r'''text'''", true, true), "text");
-  }
-
-  void test_computeStringValue_raw_withEscape() {
-    expect(_computeStringValue("r'two\\nlines'", true, true), "two\\nlines");
-  }
-
-  void test_computeStringValue_triple_internalQuote_first_empty() {
-    expect(_computeStringValue("''''", true, false), "'");
-  }
-
-  void test_computeStringValue_triple_internalQuote_first_nonEmpty() {
-    expect(_computeStringValue("''''text", true, false), "'text");
-  }
-
-  void test_computeStringValue_triple_internalQuote_last_empty() {
-    expect(_computeStringValue("'''", false, true), "");
-  }
-
-  void test_computeStringValue_triple_internalQuote_last_nonEmpty() {
-    expect(_computeStringValue("text'''", false, true), "text");
-  }
-
-  void test_createSyntheticIdentifier() {
-    createParser('');
-    SimpleIdentifier identifier = parser.createSyntheticIdentifier();
-    expectNotNullIfNoErrors(identifier);
-    expect(identifier.isSynthetic, isTrue);
-  }
-
-  void test_createSyntheticStringLiteral() {
-    createParser('');
-    SimpleStringLiteral literal = parser.createSyntheticStringLiteral();
-    expectNotNullIfNoErrors(literal);
-    expect(literal.isSynthetic, isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_block() {
-    expect(_isFunctionDeclaration("f() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_expression() {
-    expect(_isFunctionDeclaration("f() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_typeParameters_block() {
-    expect(_isFunctionDeclaration("f<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_typeParameters_expression() {
-    expect(_isFunctionDeclaration("f<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_block() {
-    expect(_isFunctionDeclaration("C f() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_expression() {
-    expect(_isFunctionDeclaration("C f() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_typeParameters_block() {
-    expect(_isFunctionDeclaration("C f<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_typeParameters_expression() {
-    expect(_isFunctionDeclaration("C f<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_block() {
-    expect(_isFunctionDeclaration("void f() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_expression() {
-    expect(_isFunctionDeclaration("void f() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_typeParameters_block() {
-    expect(_isFunctionDeclaration("void f<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_typeParameters_expression() {
-    expect(_isFunctionDeclaration("void f<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionExpression_false_noBody() {
-    expect(_isFunctionExpression("f();"), isFalse);
-  }
-
-  void test_isFunctionExpression_false_notParameters() {
-    expect(_isFunctionExpression("(a + b) {"), isFalse);
-  }
-
-  void test_isFunctionExpression_noParameters_block() {
-    expect(_isFunctionExpression("() {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_noParameters_expression() {
-    expect(_isFunctionExpression("() => e"), isTrue);
-  }
-
-  void test_isFunctionExpression_noParameters_typeParameters_block() {
-    expect(_isFunctionExpression("<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_noParameters_typeParameters_expression() {
-    expect(_isFunctionExpression("<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_final() {
-    expect(_isFunctionExpression("(final a) {}"), isTrue);
-    expect(_isFunctionExpression("(final a, b) {}"), isTrue);
-    expect(_isFunctionExpression("(final a, final b) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_final_typed() {
-    expect(_isFunctionExpression("(final int a) {}"), isTrue);
-    expect(_isFunctionExpression("(final prefix.List a) {}"), isTrue);
-    expect(_isFunctionExpression("(final List<int> a) {}"), isTrue);
-    expect(_isFunctionExpression("(final prefix.List<int> a) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_multiple() {
-    expect(_isFunctionExpression("(a, b) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_named() {
-    expect(_isFunctionExpression("({a}) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_optional() {
-    expect(_isFunctionExpression("([a]) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_single() {
-    expect(_isFunctionExpression("(a) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_typed() {
-    expect(_isFunctionExpression("(int a, int b) {}"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_assignment() {
-    expect(_isInitializedVariableDeclaration("a = null;"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_comparison() {
-    expect(_isInitializedVariableDeclaration("a < 0;"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_conditional() {
-    expect(_isInitializedVariableDeclaration("a == null ? init() : update();"),
-        isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_const_noType_initialized() {
-    expect(_isInitializedVariableDeclaration("const a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_const_noType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("const a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_const_simpleType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("const A a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_final_noType_initialized() {
-    expect(_isInitializedVariableDeclaration("final a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_final_noType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("final a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_final_simpleType_initialized() {
-    expect(_isInitializedVariableDeclaration("final A a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_functionDeclaration_typed() {
-    expect(_isInitializedVariableDeclaration("A f() {};"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_functionDeclaration_untyped() {
-    expect(_isInitializedVariableDeclaration("f() {};"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_noType_initialized() {
-    expect(_isInitializedVariableDeclaration("var a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_noType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("var a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_parameterizedType_initialized() {
-    expect(_isInitializedVariableDeclaration("List<int> a = null;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_parameterizedType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("List<int> a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_simpleType_initialized() {
-    expect(_isInitializedVariableDeclaration("A a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_simpleType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("A a;"), isTrue);
-  }
-
-  void test_isSwitchMember_case_labeled() {
-    expect(_isSwitchMember("l1: l2: case"), isTrue);
-  }
-
-  void test_isSwitchMember_case_unlabeled() {
-    expect(_isSwitchMember("case"), isTrue);
-  }
-
-  void test_isSwitchMember_default_labeled() {
-    expect(_isSwitchMember("l1: l2: default"), isTrue);
-  }
-
-  void test_isSwitchMember_default_unlabeled() {
-    expect(_isSwitchMember("default"), isTrue);
-  }
-
-  void test_isSwitchMember_false() {
-    expect(_isSwitchMember("break;"), isFalse);
-  }
-
-  void test_parseDottedName_multiple() {
-    createParser('a.b.c');
-    DottedName name = parser.parseDottedName();
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expectDottedName(name, ["a", "b", "c"]);
-  }
-
-  void test_parseDottedName_single() {
-    createParser('a');
-    DottedName name = parser.parseDottedName();
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expectDottedName(name, ["a"]);
-  }
-
-  void test_parseFinalConstVarOrType_const_functionType() {
-    createParser('const int Function(int) f');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.CONST);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_const_namedType() {
-    createParser('const A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.CONST);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_const_noType() {
-    createParser('const');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.CONST);
-    expect(result.type, isNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_functionType() {
-    createParser('final int Function(int) f');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_namedType() {
-    createParser('final A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_noType() {
-    createParser('final');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_prefixedType() {
-    createParser('final p.A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_function() {
-    createParser('int Function(int) f');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_parameterized() {
-    createParser('A<B> a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_prefixed() {
-    createParser('p.A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_prefixed_noIdentifier() {
-    createParser('p.A,');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_prefixedAndParameterized() {
-    createParser('p.A<B> a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_simple() {
-    createParser('A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_simple_noIdentifier_inFunctionType() {
-    createParser('A,');
-    FinalConstVarOrType result =
-        parser.parseFinalConstVarOrType(false, inFunctionType: true);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_var() {
-    createParser('var');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.VAR);
-    expect(result.type, isNull);
-  }
-
-  void test_parseFinalConstVarOrType_void() {
-    createParser('void f()');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_void_identifier() {
-    createParser('void x');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_void_noIdentifier() {
-    createParser('void,');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    listener.assertErrorsWithCodes(
-        [ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE]);
-  }
-
-  void test_parseFunctionBody_skip_block() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('{}');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseFunctionBody_skip_block_invalid() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('{');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    listener.assertErrorsWithCodes([ScannerErrorCode.EXPECTED_TOKEN]);
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseFunctionBody_skip_blocks() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('{ {} }');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseFunctionBody_skip_expression() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('=> y;');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseModifiers_abstract() {
-    createParser('abstract A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.abstractKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_const() {
-    createParser('const A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.constKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_covariant() {
-    createParser('covariant A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.covariantKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_external() {
-    createParser('external A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.externalKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_factory() {
-    createParser('factory A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.factoryKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_final() {
-    createParser('final A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.finalKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_static() {
-    createParser('static A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.staticKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_var() {
-    createParser('var A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.varKeyword, isNotNull);
-  }
-
-  void test_Parser() {
-    expect(
-      Parser(
-        NonExistingSource.unknown,
-        null,
-        featureSet: FeatureSet.forTesting(),
-      ),
-      isNotNull,
-    );
-  }
-
-  void test_skipPrefixedIdentifier_invalid() {
-    createParser('+');
-    Token following = parser.skipPrefixedIdentifier(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipPrefixedIdentifier_notPrefixed() {
-    createParser('a +');
-    Token following = parser.skipPrefixedIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipPrefixedIdentifier_prefixed() {
-    createParser('a.b +');
-    Token following = parser.skipPrefixedIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipReturnType_invalid() {
-    // TODO(eernst): `skipReturnType` eliminated, delete this test?
-    createParser('+');
-    Token following = parser.skipTypeAnnotation(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipReturnType_type() {
-    // TODO(eernst): `skipReturnType` eliminated, delete this test?
-    createParser('C +');
-    Token following = parser.skipTypeAnnotation(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipReturnType_void() {
-    // TODO(eernst): `skipReturnType` eliminated, delete this test?
-    createParser('void +');
-    Token following = parser.skipTypeAnnotation(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipSimpleIdentifier_identifier() {
-    createParser('i +');
-    Token following = parser.skipSimpleIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipSimpleIdentifier_invalid() {
-    createParser('9 +');
-    Token following = parser.skipSimpleIdentifier(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipSimpleIdentifier_pseudoKeyword() {
-    createParser('as +');
-    Token following = parser.skipSimpleIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipStringLiteral_adjacent() {
-    createParser("'a' 'b' +");
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipStringLiteral_interpolated() {
-    createParser("'a\${b}c' +");
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipStringLiteral_invalid() {
-    createParser('a');
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipStringLiteral_single() {
-    createParser("'a' +");
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeArgumentList_invalid() {
-    createParser('+');
-    Token following = parser.skipTypeArgumentList(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipTypeArgumentList_multiple() {
-    createParser('<E, F, G> +');
-    Token following = parser.skipTypeArgumentList(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeArgumentList_single() {
-    createParser('<E> +');
-    Token following = parser.skipTypeArgumentList(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeName_invalid() {
-    createParser('+');
-    Token following = parser.skipTypeName(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipTypeName_parameterized() {
-    createParser('C<E<F<G>>> +');
-    Token following = parser.skipTypeName(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeName_simple() {
-    createParser('C +');
-    Token following = parser.skipTypeName(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  /// Invoke the method [Parser.computeStringValue] with the given argument.
-  ///
-  /// @param lexeme the argument to the method
-  /// @param first `true` if this is the first token in a string literal
-  /// @param last `true` if this is the last token in a string literal
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  String _computeStringValue(String lexeme, bool first, bool last) {
-    createParser('');
-    String value = parser.computeStringValue(lexeme, first, last);
-    assertNoErrors();
-    return value;
-  }
-
-  /// Invoke the method [Parser.isFunctionDeclaration] with the parser set to
-  /// the token stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isFunctionDeclaration(String source) {
-    createParser(source);
-    bool result = parser.isFunctionDeclaration();
-    expectNotNullIfNoErrors(result);
-    return result;
-  }
-
-  /// Invoke the method [Parser.isFunctionExpression] with the parser set to the
-  /// token stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isFunctionExpression(String source) {
-    createParser(source);
-    return parser.isFunctionExpression(parser.currentToken);
-  }
-
-  /// Invoke the method [Parser.isInitializedVariableDeclaration] with the
-  /// parser set to the token stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isInitializedVariableDeclaration(String source) {
-    createParser(source);
-    bool result = parser.isInitializedVariableDeclaration();
-    expectNotNullIfNoErrors(result);
-    return result;
-  }
-
-  /// Invoke the method [Parser.isSwitchMember] with the parser set to the token
-  /// stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isSwitchMember(String source) {
-    createParser(source);
-    bool result = parser.isSwitchMember();
-    expectNotNullIfNoErrors(result);
-    return result;
-  }
-}
-
 /// Parser tests that test individual parsing methods. The code fragments should
 /// be as minimal as possible in order to test the method, but should not test
 /// the interactions between the method under test and other methods.
 ///
 /// More complex tests should be defined in the class [ComplexParserTest].
-mixin SimpleParserTestMixin implements AbstractParserTestCase {
+mixin SimpleParserTestMixin implements AbstractParserViaProxyTestCase {
   ConstructorName parseConstructorName(String name) {
     createParser('new $name();');
     Statement statement = parser.parseStatement2();
@@ -13771,7 +12082,7 @@
     expect(functionBody, isBlockFunctionBody);
     BlockFunctionBody body = functionBody;
     expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.ASYNC);
+    expect(body.keyword.lexeme, Keyword.ASYNC.lexeme);
     expect(body.star, isNull);
     expect(body.block, isNotNull);
     expect(body.isAsynchronous, isTrue);
@@ -13787,7 +12098,7 @@
     expect(functionBody, isBlockFunctionBody);
     BlockFunctionBody body = functionBody;
     expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.ASYNC);
+    expect(body.keyword.lexeme, Keyword.ASYNC.lexeme);
     expect(body.star, isNotNull);
     expect(body.block, isNotNull);
     expect(body.isAsynchronous, isTrue);
@@ -13803,7 +12114,7 @@
     expect(functionBody, isBlockFunctionBody);
     BlockFunctionBody body = functionBody;
     expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.SYNC);
+    expect(body.keyword.lexeme, Keyword.SYNC.lexeme);
     expect(body.star, isNotNull);
     expect(body.block, isNotNull);
     expect(body.isAsynchronous, isFalse);
@@ -13845,7 +12156,7 @@
     expect(functionBody, isExpressionFunctionBody);
     ExpressionFunctionBody body = functionBody;
     expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.ASYNC);
+    expect(body.keyword.lexeme, Keyword.ASYNC.lexeme);
     expect(body.functionDefinition, isNotNull);
     expect(body.expression, isNotNull);
     expect(body.semicolon, isNotNull);
@@ -13900,19 +12211,16 @@
 
   void test_parseInstanceCreation_noKeyword_33647() {
     enableOptionalNewAndConst = true;
-    // Old parser produces errors
-    if (usingFastaParser) {
-      CompilationUnit unit = parseCompilationUnit('''
+    CompilationUnit unit = parseCompilationUnit('''
 var c = Future<int>.sync(() => 3).then<int>((e) => e);
 ''');
-      expect(unit, isNotNull);
-      TopLevelVariableDeclaration v = unit.declarations[0];
-      MethodInvocation init = v.variables.variables[0].initializer;
-      expect(init.methodName.name, 'then');
-      NodeList<TypeAnnotation> typeArg = init.typeArguments.arguments;
-      expect(typeArg, hasLength(1));
-      expect(typeArg[0].beginToken.lexeme, 'int');
-    }
+    expect(unit, isNotNull);
+    TopLevelVariableDeclaration v = unit.declarations[0];
+    MethodInvocation init = v.variables.variables[0].initializer;
+    expect(init.methodName.name, 'then');
+    NodeList<TypeAnnotation> typeArg = init.typeArguments.arguments;
+    expect(typeArg, hasLength(1));
+    expect(typeArg[0].beginToken.lexeme, 'int');
   }
 
   void test_parseInstanceCreation_noKeyword_noPrefix() {
@@ -13934,9 +12242,6 @@
   }
 
   void test_parseInstanceCreation_noKeyword_noPrefix_34403() {
-    if (!usingFastaParser) {
-      return;
-    }
     enableOptionalNewAndConst = true;
     createParser('f() => C<E>.n<B>();');
     CompilationUnit unit = parser.parseCompilationUnit2();
@@ -13998,14 +12303,10 @@
   }
 
   void test_parseLibraryIdentifier_invalid() {
-    parseCompilationUnit('library <myLibId>;',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 7),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1),
-              ]
-            : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 1)]);
+    parseCompilationUnit('library <myLibId>;', errors: [
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 7),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1),
+    ]);
   }
 
   void test_parseLibraryIdentifier_multiple() {
@@ -14462,18 +12763,10 @@
   void test_parseTypeParameterList_single() {
     createParser('<<A>', expectedEndOffset: 0);
     TypeParameterList parameterList = parser.parseTypeParameterList();
-    if (usingFastaParser) {
-      // TODO(danrubel): Consider splitting `<<` and marking the first `<`
-      // as an unexpected token.
-      expect(parameterList, isNull);
-      assertNoErrors();
-    } else {
-      expectNotNullIfNoErrors(parameterList);
-      assertNoErrors();
-      expect(parameterList.leftBracket, isNotNull);
-      expect(parameterList.rightBracket, isNotNull);
-      expect(parameterList.typeParameters, hasLength(1));
-    }
+    // TODO(danrubel): Consider splitting `<<` and marking the first `<`
+    // as an unexpected token.
+    expect(parameterList, isNull);
+    assertNoErrors();
   }
 
   void test_parseTypeParameterList_withTrailingEquals() {
@@ -14521,42 +12814,23 @@
   }
 }
 
-@reflectiveTest
-class StatementParserTest extends ParserTestCase with StatementParserTestMixin {
-}
-
 /// The class [FormalParameterParserTestMixin] defines parser tests that test
 /// the parsing statements.
 mixin StatementParserTestMixin implements AbstractParserTestCase {
   void test_invalid_typeParamAnnotation() {
-    parseCompilationUnit('main() { C<@Foo T> v; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 4)
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1)
-              ]);
+    parseCompilationUnit('main() { C<@Foo T> v; }', errors: [
+      expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 4)
+    ]);
   }
 
   void test_invalid_typeParamAnnotation2() {
-    parseCompilationUnit('main() { C<@Foo.bar(1) T> v; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 11)
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1)
-              ]);
+    parseCompilationUnit('main() { C<@Foo.bar(1) T> v; }', errors: [
+      expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 11)
+    ]);
   }
 
   void test_invalid_typeParamAnnotation3() {
-    if (usingFastaParser) {
-      parseCompilationUnit('''
+    parseCompilationUnit('''
 main() {
   C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T,
     F Function<G>(int, String, {Bar b}),
@@ -14565,9 +12839,8 @@
     W<X<Y<Z>>>
   > v;
 }''', errors: [
-        expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 13, 63)
-      ]);
-    }
+      expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 13, 63)
+    ]);
   }
 
   void test_parseAssertStatement() {
@@ -14705,17 +12978,11 @@
   }
 
   void test_parseElseAlone() {
-    parseCompilationUnit('main() { else return 0; } ',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 4),
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_STATEMENT, 9, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 4),
-              ]);
+    parseCompilationUnit('main() { else return 0; } ', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 4),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 4),
+    ]);
   }
 
   void test_parseEmptyStatement() {
@@ -14730,7 +12997,7 @@
     String code = 'await for (element in list) {}';
     var forStatement = _parseAsyncStatement(code) as ForStatement;
     assertNoErrors();
-    expect(forStatement.awaitKeyword, usingFastaParser ? isNotNull : isNull);
+    expect(forStatement.awaitKeyword, isNotNull);
     expect(forStatement.forKeyword, isNotNull);
     expect(forStatement.leftParenthesis, isNotNull);
     var forEachParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
@@ -15143,9 +13410,6 @@
   }
 
   void test_parseNonLabeledStatement_const_object_named_typeParameters_34403() {
-    if (!usingFastaParser) {
-      return;
-    }
     var statement = parseStatement('const A<B>.c<C>();') as ExpressionStatement;
     assertErrorsWithCodes(
         [CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR]);
@@ -15586,18 +13850,9 @@
   }
 
   void test_parseTryStatement_catch_error_invalidCatchParam() {
-    CompilationUnit unit =
-        parseCompilationUnit('main() { try {} catch (int e) { } }',
-            errors: usingFastaParser
-                ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 27, 1)]
-                : [
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 1),
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 1),
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 1),
-                    expectedError(ParserErrorCode.MISSING_IDENTIFIER, 28, 1),
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 28, 1),
-                    expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
-                  ]);
+    CompilationUnit unit = parseCompilationUnit(
+        'main() { try {} catch (int e) { } }',
+        errors: [expectedError(ParserErrorCode.CATCH_SYNTAX, 27, 1)]);
     FunctionDeclaration method = unit.declarations[0];
     BlockFunctionBody body = method.functionExpression.body;
     TryStatement statement = body.block.statements[0];
@@ -15609,15 +13864,9 @@
     expect(clause.onKeyword, isNull);
     expect(clause.exceptionType, isNull);
     expect(clause.catchKeyword, isNotNull);
-    if (usingFastaParser) {
-      expect(clause.exceptionParameter.name, 'int');
-      expect(clause.comma, isNotNull);
-      expect(clause.stackTraceParameter.name, 'e');
-    } else {
-      expect(clause.exceptionParameter.name, 'int');
-      expect(clause.comma, isNull);
-      expect(clause.stackTraceParameter, isNull);
-    }
+    expect(clause.exceptionParameter.name, 'int');
+    expect(clause.comma, isNotNull);
+    expect(clause.stackTraceParameter.name, 'e');
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -15625,11 +13874,7 @@
 
   void test_parseTryStatement_catch_error_missingCatchParam() {
     var statement = parseStatement('try {} catch () {}') as TryStatement;
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 14, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
-          ]);
+    listener.assertErrors([expectedError(ParserErrorCode.CATCH_SYNTAX, 14, 1)]);
     expect(statement.tryKeyword, isNotNull);
     expect(statement.body, isNotNull);
     NodeList<CatchClause> catchClauses = statement.catchClauses;
@@ -15648,13 +13893,7 @@
 
   void test_parseTryStatement_catch_error_missingCatchParen() {
     var statement = parseStatement('try {} catch {}') as TryStatement;
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 13, 1)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1)
-          ]);
+    listener.assertErrors([expectedError(ParserErrorCode.CATCH_SYNTAX, 13, 1)]);
     expect(statement.tryKeyword, isNotNull);
     expect(statement.body, isNotNull);
     NodeList<CatchClause> catchClauses = statement.catchClauses;
@@ -15673,11 +13912,7 @@
 
   void test_parseTryStatement_catch_error_missingCatchTrace() {
     var statement = parseStatement('try {} catch (e,) {}') as TryStatement;
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 16, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
-          ]);
+    listener.assertErrors([expectedError(ParserErrorCode.CATCH_SYNTAX, 16, 1)]);
     expect(statement.tryKeyword, isNotNull);
     expect(statement.body, isNotNull);
     NodeList<CatchClause> catchClauses = statement.catchClauses;
@@ -15927,9 +14162,6 @@
   }
 }
 
-@reflectiveTest
-class TopLevelParserTest extends ParserTestCase with TopLevelParserTestMixin {}
-
 /// Tests which exercise the parser using a complete compilation unit or
 /// compilation unit member.
 mixin TopLevelParserTestMixin implements AbstractParserTestCase {
@@ -16267,16 +14499,7 @@
 
   void test_parseClassDeclaration_typeParameters_extends_void() {
     parseCompilationUnit('class C<T extends void>{}',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 18, 4)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 18, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 4),
-                expectedError(ParserErrorCode.EXPECTED_BODY, 18, 4),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 22, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 22, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
-              ]);
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 18, 4)]);
   }
 
   void test_parseClassDeclaration_withDocumentationComment() {
@@ -16293,11 +14516,9 @@
 
   void test_parseCompilationUnit_abstractAsPrefix_parameterized() {
     var errorCodes = <ErrorCode>[];
-    if (usingFastaParser) {
-      // This used to be deferred to later in the pipeline, but is now being
-      // reported by the parser.
-      errorCodes.add(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE);
-    }
+    // This used to be deferred to later in the pipeline, but is now being
+    // reported by the parser.
+    errorCodes.add(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE);
     CompilationUnit unit = parseCompilationUnit(
         'abstract<dynamic> _abstract = new abstract.A();',
         codes: errorCodes);
@@ -16318,16 +14539,14 @@
   }
 
   void test_parseCompilationUnit_builtIn_asFunctionName_withTypeParameter() {
-    if (usingFastaParser) {
-      for (Keyword keyword in Keyword.values) {
-        if (keyword.isBuiltIn || keyword.isPseudo) {
-          String lexeme = keyword.lexeme;
-          if (lexeme == 'Function') continue;
-          // The fasta type resolution phase will report an error
-          // on type arguments on `dynamic` (e.g. `dynamic<int>`).
-          parseCompilationUnit('$lexeme<T>(x) => 0;');
-          parseCompilationUnit('class C {$lexeme<T>(x) => 0;}');
-        }
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isBuiltIn || keyword.isPseudo) {
+        String lexeme = keyword.lexeme;
+        if (lexeme == 'Function') continue;
+        // The fasta type resolution phase will report an error
+        // on type arguments on `dynamic` (e.g. `dynamic<int>`).
+        parseCompilationUnit('$lexeme<T>(x) => 0;');
+        parseCompilationUnit('class C {$lexeme<T>(x) => 0;}');
       }
     }
   }
@@ -16389,13 +14608,9 @@
     createParser('export<dynamic> _export = new export.A();');
     CompilationUnit unit = parser.parseCompilationUnit2();
     expect(unit, isNotNull);
-    if (usingFastaParser) {
-      // This used to be deferred to later in the pipeline, but is now being
-      // reported by the parser.
-      assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
-    } else {
-      assertNoErrors();
-    }
+    // This used to be deferred to later in the pipeline, but is now being
+    // reported by the parser.
+    assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     expect(unit.scriptTag, isNull);
     expect(unit.directives, hasLength(0));
     expect(unit.declarations, hasLength(1));
@@ -16405,13 +14620,9 @@
     createParser('operator<dynamic> _operator = new operator.A();');
     CompilationUnit unit = parser.parseCompilationUnit2();
     expect(unit, isNotNull);
-    if (usingFastaParser) {
-      // This used to be deferred to later in the pipeline, but is now being
-      // reported by the parser.
-      assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
-    } else {
-      assertNoErrors();
-    }
+    // This used to be deferred to later in the pipeline, but is now being
+    // reported by the parser.
+    assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     expect(unit.scriptTag, isNull);
     expect(unit.directives, hasLength(0));
     expect(unit.declarations, hasLength(1));
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index ad8cc0b..43a53ee 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 
@@ -117,7 +116,7 @@
   final Map<Source, LineInfo> _lineInfoMap = <Source, LineInfo>{};
 
   /// Initialize a newly created error listener to collect errors.
-  GatheringErrorListener({this.checkRanges = Parser.useFasta});
+  GatheringErrorListener({this.checkRanges = true});
 
   /// Return the errors that were collected.
   List<AnalysisError> get errors => _errors;
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index f9e47a8..166c8b9 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/dart/analysis/status.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
@@ -125,7 +124,7 @@
   }
 
   AnalysisOptionsImpl createAnalysisOptions() => AnalysisOptionsImpl()
-    ..useFastaParser = analyzer.Parser.useFasta
+    ..useFastaParser = true
     ..contextFeatures = FeatureSet.fromEnableFlags2(
       sdkLanguageVersion: ExperimentStatus.testingSdkLanguageVersion,
       flags: enabledExperiments,
diff --git a/pkg/analyzer/test/src/dart/ast/parse_base.dart b/pkg/analyzer/test/src/dart/ast/parse_base.dart
index d280721..eb662b2 100644
--- a/pkg/analyzer/test/src/dart/ast/parse_base.dart
+++ b/pkg/analyzer/test/src/dart/ast/parse_base.dart
@@ -36,12 +36,10 @@
     var token = scanner.tokenize();
     featureSet = scanner.featureSet;
 
-    var useFasta = analysisOptions.useFastaParser;
     var parser = Parser(
       source,
       errorListener,
       featureSet: featureSet,
-      useFasta: useFasta,
     );
     parser.enableOptionalNewAndConst = true;
 
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 8d84fe7..0cb4190 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -449,6 +449,8 @@
 
   FunctionEntity getInstantiateFunction(int typeArgumentCount);
 
+  FunctionEntity get convertMainArgumentList;
+
   // From dart:_rti
 
   FunctionEntity get setRuntimeTypeInfo;
@@ -1834,6 +1836,10 @@
         cls.name.startsWith('Instantiation');
   }
 
+  @override
+  FunctionEntity get convertMainArgumentList =>
+      _findHelperFunction('convertMainArgumentList');
+
   // From dart:_rti
 
   ClassEntity _findRtiClass(String name) => _findClass(rtiLibrary, name);
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 5f63cfb..39c5e4f 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -117,10 +117,13 @@
   BackendImpact _mainWithArguments;
 
   BackendImpact get mainWithArguments {
-    return _mainWithArguments ??= new BackendImpact(instantiatedClasses: [
-      _commonElements.jsArrayClass,
-      _commonElements.jsStringClass
-    ]);
+    return _mainWithArguments ??= new BackendImpact(
+      globalUses: [_commonElements.convertMainArgumentList],
+      instantiatedClasses: [
+        _commonElements.jsArrayClass,
+        _commonElements.jsStringClass
+      ],
+    );
   }
 
   BackendImpact _asyncBody;
diff --git a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
index e20f889..d26bb2e 100644
--- a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
@@ -9,16 +9,58 @@
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
+import '../common_elements.dart';
 
 import 'code_emitter_task.dart' show Emitter;
 
 class MainCallStubGenerator {
   static jsAst.Statement generateInvokeMain(
-      Emitter emitter, FunctionEntity main) {
-    jsAst.Expression mainCallClosure = emitter.staticFunctionAccess(main);
+      CommonElements commonElements, Emitter emitter, FunctionEntity main) {
+    jsAst.Expression mainAccess = emitter.staticFunctionAccess(main);
     jsAst.Expression currentScriptAccess =
         emitter.generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT);
 
+    // TODO(https://github.com/dart-lang/language/issues/1120#issuecomment-670802088):
+    // Validate constraints on `main()` in resolution for dart2js, and in DDC.
+
+    final parameterStructure = main.parameterStructure;
+
+    // The forwarding stub passes all arguments, i.e. both required and optional
+    // positional arguments. We ignore named arguments, assuming the `main()`
+    // has been validated earlier.
+    int positionalParameters = parameterStructure.positionalParameters;
+
+    jsAst.Expression mainCallClosure;
+    if (positionalParameters == 0) {
+      if (parameterStructure.namedParameters.isEmpty) {
+        // e.g. `void main()`.
+        // No parameters. The compiled Dart `main` has no parameters and will
+        // ignore any extra parameters passed in, so it can be used directly.
+        mainCallClosure = mainAccess;
+      } else {
+        // e.g. `void main({arg})`.  We should not get here. Drop the named
+        // arguments as we don't know how to convert them.
+        mainCallClosure = js(r'''function() { return #(); }''', mainAccess);
+      }
+    } else {
+      jsAst.Expression convertArgumentList =
+          emitter.staticFunctionAccess(commonElements.convertMainArgumentList);
+      if (positionalParameters == 1) {
+        // e.g. `void main(List<String> args)`,  `main([args])`.
+        mainCallClosure = js(
+          r'''function(args) { return #(#(args)); }''',
+          [mainAccess, convertArgumentList],
+        );
+      } else {
+        // positionalParameters == 2.
+        // e.g. `void main(List<String> args, Object? extra)`
+        mainCallClosure = js(
+          r'''function(args, extra) { return #(#(args), extra); }''',
+          [mainAccess, convertArgumentList],
+        );
+      }
+    }
+
     // This code finds the currently executing script by listening to the
     // onload event of all script tags and getting the first script which
     // finishes. Since onload is called immediately after execution this should
@@ -48,11 +90,11 @@
         }
       })(function(currentScript) {
         #currentScript = currentScript;
-
+        var callMain = #mainCallClosure;
         if (typeof dartMainRunner === "function") {
-          dartMainRunner(#mainCallClosure, []);
+          dartMainRunner(callMain, []);
         } else {
-          #mainCallClosure([]);
+          callMain([]);
         }
       })''', {
       'currentScript': currentScriptAccess,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 351d6bc..99e7544 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -388,7 +388,7 @@
 
   js.Statement _buildInvokeMain() {
     return MainCallStubGenerator.generateInvokeMain(
-        _task.emitter, _mainFunction);
+        _commonElements, _task.emitter, _mainFunction);
   }
 
   DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) {
diff --git a/pkg/dev_compiler/lib/src/compiler/module_containers.dart b/pkg/dev_compiler/lib/src/compiler/module_containers.dart
index 6c76688..267afb5 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_containers.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_containers.dart
@@ -35,11 +35,11 @@
 ///   ...
 /// };
 /// ```
-class ModuleItemContainer<K> {
+abstract class ModuleItemContainer<K> {
   /// Name of the container in the emitted JS.
   String name;
 
-  /// If null, this container will be automatically renamed based on [name].
+  /// Refers to the latest container if this container is sharded.
   js_ast.Identifier containerId;
 
   final Map<K, ModuleItemData> moduleItems = {};
@@ -66,43 +66,15 @@
 
   int get length => moduleItems.keys.length;
 
+  bool get isEmpty => moduleItems.isEmpty;
+
   js_ast.Expression operator [](K key) => moduleItems[key]?.jsValue;
 
-  void operator []=(K key, js_ast.Expression value) {
-    if (moduleItems.containsKey(key)) {
-      moduleItems[key].jsValue = value;
-      return;
-    }
-    var fieldString = '$key';
-    // Avoid shadowing common JS properties.
-    if (js_ast.objectProperties.contains(fieldString)) {
-      fieldString += '\$';
-    }
-    moduleItems[key] = ModuleItemData(
-        containerId, js_ast.LiteralString("'$fieldString'"), value);
-  }
+  void operator []=(K key, js_ast.Expression value);
 
   /// Returns the expression that retrieves [key]'s corresponding JS value via
   /// a property access through its container.
-  js_ast.Expression access(K key) {
-    return js.call('#.#', [containerId, moduleItems[key].jsKey]);
-  }
-
-  /// Emit the container declaration/initializer.
-  ///
-  /// May be multiple statements if the container is automatically sharded.
-  List<js_ast.Statement> emit() {
-    var properties = <js_ast.Property>[];
-    moduleItems.forEach((k, v) {
-      if (!_noEmit.contains(k)) return;
-      properties.add(js_ast.Property(v.jsKey, v.jsValue));
-    });
-    var containerObject =
-        js_ast.ObjectInitializer(properties, multiline: properties.length > 1);
-    return [
-      js.statement('var # = Object.create(#)', [containerId, containerObject])
-    ];
-  }
+  js_ast.Expression access(K key);
 
   bool contains(K key) => moduleItems.containsKey(key);
 
@@ -115,6 +87,16 @@
   void setNoEmit(K key) {
     _noEmit.add(key);
   }
+
+  /// Emit the container declaration/initializer, using multiple statements if
+  /// necessary.
+  List<js_ast.Statement> emit();
+
+  /// Emit the container declaration/initializer incrementally.
+  ///
+  /// Used during expression evaluation. Appends all newly added types to the
+  /// most recent container.
+  List<js_ast.Statement> emitIncremental();
 }
 
 /// Associates a [K] with a container-unique JS key and arbitrary JS value.
@@ -129,9 +111,6 @@
 /// var C$1 = { ... };
 /// ```
 class ModuleItemObjectContainer<K> extends ModuleItemContainer<K> {
-  /// Holds the TemporaryId for the current container shard.
-  js_ast.Identifier _currentContainerId;
-
   /// Tracks how often JS emitted field names appear.
   ///
   /// [keyToString] may resolve multiple unique keys to the same JS string.
@@ -144,7 +123,7 @@
   String Function(K) keyToString;
 
   ModuleItemObjectContainer(String name, this.keyToString)
-      : super._(name, null);
+      : super._(name, js_ast.TemporaryId(name));
 
   @override
   void operator []=(K key, js_ast.Expression value) {
@@ -152,7 +131,6 @@
       moduleItems[key].jsValue = value;
       return;
     }
-    if (length % 500 == 0) _currentContainerId = js_ast.TemporaryId(name);
     // Create a unique name for K when emitted as a JS field.
     var fieldString = keyToString(key);
     _nameFrequencies.update(fieldString, (v) {
@@ -166,7 +144,8 @@
       return 0;
     });
     moduleItems[key] = ModuleItemData(
-        _currentContainerId, js_ast.LiteralString("'$fieldString'"), value);
+        containerId, js_ast.LiteralString("'$fieldString'"), value);
+    if (length % 500 == 0) containerId = js_ast.TemporaryId(name);
   }
 
   @override
@@ -185,6 +164,14 @@
       containersToProperties[v.id].add(js_ast.Property(v.jsKey, v.jsValue));
     });
 
+    // Emit a self-reference for the next container so V8 does not optimize it
+    // away. Required for expression evaluation.
+    if (containersToProperties[containerId] == null) {
+      containersToProperties[containerId] = [
+        js_ast.Property(
+            js_ast.LiteralString('_'), js.call('() => #', [containerId]))
+      ];
+    }
     var statements = <js_ast.Statement>[];
     containersToProperties.forEach((containerId, properties) {
       var containerObject = js_ast.ObjectInitializer(properties,
@@ -194,6 +181,18 @@
     });
     return statements;
   }
+
+  /// Appends all newly added types to the most recent container.
+  @override
+  List<js_ast.Statement> emitIncremental() {
+    var statements = <js_ast.Statement>[];
+    moduleItems.forEach((k, v) {
+      if (_noEmit.contains(k)) return;
+      statements
+          .add(js.statement('#[#] = #', [containerId, v.jsKey, v.jsValue]));
+    });
+    return statements;
+  }
 }
 
 /// Associates a unique [K] with an arbitrary JS value.
@@ -226,7 +225,6 @@
 
   @override
   List<js_ast.Statement> emit() {
-    if (moduleItems.isEmpty) return [];
     var properties = List<js_ast.Expression>.filled(length, null);
 
     // If the entire array holds just one value, generate a short initializer.
@@ -256,4 +254,15 @@
       ])
     ];
   }
+
+  @override
+  List<js_ast.Statement> emitIncremental() {
+    var statements = <js_ast.Statement>[];
+    moduleItems.forEach((k, v) {
+      if (_noEmit.contains(k)) return;
+      statements
+          .add(js.statement('#[#] = #', [containerId, v.jsKey, v.jsValue]));
+    });
+    return statements;
+  }
 }
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 46ee30d..ba707e4 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -364,6 +364,17 @@
       _pendingClasses.addAll(l.classes);
     }
 
+    // Insert a circular reference so neither the constant table or its cache
+    // are optimized away by V8. Required for expression evaluation.
+    var constTableDeclaration =
+        js.statement('const # = Object.create({# : () => (#, #)});', [
+      _constTable,
+      js_ast.LiteralString('_'),
+      _constTableCache.containerId,
+      _constTable
+    ]);
+    moduleItems.add(constTableDeclaration);
+
     // Record a safe index after the declaration of type generators and
     // top-level symbols but before the declaration of any functions.
     // Various preliminary data structures must be inserted here prior before
@@ -384,19 +395,12 @@
     // Emit hoisted assert strings
     moduleItems.insertAll(safeDeclarationIndex, _uriContainer.emit());
 
-    if (_constTableCache.isNotEmpty) {
-      moduleItems.insertAll(safeDeclarationIndex, _constTableCache.emit());
-    }
+    moduleItems.insertAll(safeDeclarationIndex, _constTableCache.emit());
 
-    // This can cause problems if it's ever true during the SDK build, as it's
-    // emitted before dart.defineLazy.
     if (_constLazyAccessors.isNotEmpty) {
-      var constTableDeclaration =
-          js.statement('const # = Object.create(null);', [_constTable]);
       var constTableBody = runtimeStatement(
           'defineLazy(#, { # }, false)', [_constTable, _constLazyAccessors]);
-      moduleItems.insertAll(
-          _constTableInsertionIndex, [constTableDeclaration, constTableBody]);
+      moduleItems.insert(_constTableInsertionIndex, constTableBody);
       _constLazyAccessors.clear();
     }
 
@@ -3093,8 +3097,9 @@
     // Issue: https://github.com/dart-lang/sdk/issues/43288
     var fun = _emitFunction(functionNode, name);
 
-    var types = _typeTable?.dischargeFreeTypes();
+    var types = _typeTable?.dischargeBoundTypes(incremental: true);
     var constants = _dischargeConstTable();
+
     var body = js_ast.Block([...?types, ...?constants, ...fun.body.statements]);
     return js_ast.Fun(fun.params, body);
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index b9b73fd..d25ae97 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -122,12 +122,20 @@
 
   /// Emit the initializer statements for the type container, which contains
   /// all named types with fully bound type parameters.
-  List<js_ast.Statement> dischargeBoundTypes() {
+  ///
+  /// [incremental] is only used for expression evaluation.
+  List<js_ast.Statement> dischargeBoundTypes({bool incremental = false}) {
     for (var t in typeContainer.keys) {
       typeContainer[t] = js.call('() => ((# = #.constFn(#))())',
           [typeContainer.access(t), _runtimeModule, typeContainer[t]]);
     }
-    return typeContainer.emit();
+    var boundTypes =
+        incremental ? typeContainer.emitIncremental() : typeContainer.emit();
+    // Bound types should only be emitted once (even across multiple evals).
+    for (var t in typeContainer.keys) {
+      typeContainer.setNoEmit(t);
+    }
+    return boundTypes;
   }
 
   js_ast.Statement _dischargeFreeType(DartType type) {
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
index 1209475..bd36fbb 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
@@ -452,14 +452,13 @@
             expression: 'main',
             expectedResult: '''
             (function(x, y, z) {
-              var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
+              T.VoidTodynamic = () => (T.VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.fn(foo.main, VoidTodynamic());
+                  return C[0] = dart.fn(foo.main, T.VoidTodynamic());
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1,
               2,
@@ -1342,8 +1341,8 @@
             expression: 'baz(p as String)',
             expectedResult: '''
             (function(p) {
-              var StringL = () => (StringL = dart.constFn(dart.legacy(core.String)))();
-              return foo.baz(StringL().as(p));
+              T.StringL = () => (T.StringL = dart.constFn(dart.legacy(core.String)))();
+              return foo.baz(T.StringL().as(p));
             }(
             0
             ))
@@ -1358,14 +1357,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.MyClass.prototype,
                     [_t]: 1
                   });
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
@@ -1407,14 +1405,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.ValueKey.prototype,
                     [value]: "t"
                     });
                   }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
@@ -1927,6 +1924,103 @@
             expectedError: "Error: Getter not found: 'z'");
       });
     });
+
+    group('Expression compiler tests for interactions with module containers:',
+        () {
+      var source = '''
+        ${options.dartLangComment}
+        class A {
+          const A();
+        }
+        class B {
+          const B();
+        }
+        void foo() {
+          const a = A();
+          var check = a is int;
+          /* evaluation placeholder */
+          return;
+        }
+        
+        void main() => foo();
+        ''';
+
+      TestDriver driver;
+      setUp(() {
+        driver = TestDriver(options, source);
+      });
+
+      tearDown(() {
+        driver.delete();
+      });
+
+      test('evaluation that non-destructively appends to the type container',
+          () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'a is String',
+            expectedResult: '''
+            (function(a, check) {
+              T.StringL = () => (T.StringL = dart.constFn(dart.legacy(core.String)))();
+              return T.StringL().is(a);
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+
+      test('evaluation that reuses the type container', () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'a is int',
+            expectedResult: '''
+            (function(a, check) {
+              return T.intL().is(a);
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+
+      test(
+          'evaluation that non-destructively appends to the constant container',
+          () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'const B()',
+            expectedResult: '''
+            (function(a, check) {
+            dart.defineLazy(CT, {
+              get C1() {
+                return C[1] = dart.const({
+                  __proto__: foo.B.prototype
+                });
+              }
+            }, false);
+            return C[1] || CT.C1;
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+
+      test('evaluation that reuses the constant container', () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'const A()',
+            expectedResult: '''
+            (function(a, check) {
+              return C[0] || CT.C0;
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+    });
   });
 
   group('Sound null safety:', () {
@@ -2090,14 +2184,13 @@
             expression: 'main',
             expectedResult: '''
             (function(x, y, z) {
-              var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
+              T.VoidTodynamic = () => (T.VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.fn(foo.main, VoidTodynamic());
+                  return C[0] = dart.fn(foo.main, T.VoidTodynamic());
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1,
               2,
@@ -2995,14 +3088,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.MyClass.prototype,
                     [_t]: 1
                   });
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
@@ -3044,14 +3136,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.ValueKey.prototype,
                     [value]: "t"
                     });
                   }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
diff --git a/pkg/scrape/example/strings.dart b/pkg/scrape/example/strings.dart
new file mode 100644
index 0000000..a89fcef
--- /dev/null
+++ b/pkg/scrape/example/strings.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:scrape/scrape.dart';
+
+final quoteRegExp = RegExp('\\\\?[\'"]');
+
+void main(List<String> arguments) {
+  Scrape()
+    ..addHistogram('Directive')
+    ..addHistogram('Expression')
+    ..addHistogram('Escapes')
+    ..addVisitor(() => StringVisitor())
+    ..runCommandLine(arguments);
+}
+
+class StringVisitor extends ScrapeVisitor {
+  @override
+  void visitSimpleStringLiteral(SimpleStringLiteral node) {
+    _record('Expression', node);
+    _recordEscapes(node);
+    super.visitSimpleStringLiteral(node);
+  }
+
+  @override
+  void visitStringInterpolation(StringInterpolation node) {
+    // Entire expression containing interpolation elements.
+    _record('Expression', node);
+
+    // TODO: Analyze escaped quotes inside strings.
+
+    // TODO: Analyze string literals nested inside interpolation.
+    super.visitStringInterpolation(node);
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    if (node.uri != null) _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  void _record(String histogram, StringLiteral string) {
+    record(histogram, _quoteType(string.beginToken.lexeme));
+  }
+
+  void _recordEscapes(StringLiteral string) {
+    var quote = _quoteType(string.beginToken.lexeme);
+
+    // Ignore the rarer quote styles.
+    if (quote != "'" && quote != '"') return;
+
+    var contents = string.toSource();
+    contents = contents.substring(1, contents.length - 1);
+
+    var quotes = quoteRegExp
+        .allMatches(contents)
+        .map((match) => match[0])
+        .toSet()
+        .toList();
+    quotes.sort();
+
+    if (quotes.isNotEmpty) {
+      record('Escapes', '$quote containing ${quotes.join(" ")}');
+    }
+  }
+
+  String _quoteType(String lexeme) {
+    const types = ['"""', "'''", 'r"""', "r'''", '"', "'", 'r"', "r'"];
+
+    for (var type in types) {
+      if (lexeme.startsWith(type)) return type;
+    }
+
+    log('Unknown string quote in $lexeme');
+    return '';
+  }
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 3b1cca4..570aa15 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2960,24 +2960,20 @@
   return completer.future;
 }
 
-class MainError extends Error implements NoSuchMethodError {
-  final String _message;
-
-  MainError(this._message);
-
-  String toString() => 'NoSuchMethodError: $_message';
-}
-
-void missingMain() {
-  throw new MainError("No top-level function named 'main'.");
-}
-
-void badMain() {
-  throw new MainError("'main' is not a function.");
-}
-
-void mainHasTooManyParameters() {
-  throw new MainError("'main' expects too many parameters.");
+/// Converts a raw JavaScript array into a `List<String>`.
+/// Called from generated code.
+List<String> convertMainArgumentList(Object? args) {
+  List<String> result = [];
+  if (args == null) return result;
+  if (args is JSArray) {
+    for (int i = 0; i < args.length; i++) {
+      JS('', '#.push(String(#[#]))', result, args, i);
+    }
+    return result;
+  }
+  // Single non-Array element. Convert to a String.
+  JS('', '#.push(String(#))', result, args);
+  return result;
 }
 
 class _AssertionError extends AssertionError {
diff --git a/sdk/lib/_internal/js_runtime/lib/preambles/d8.js b/sdk/lib/_internal/js_runtime/lib/preambles/d8.js
index 0174d95..6604c8a 100644
--- a/sdk/lib/_internal/js_runtime/lib/preambles/d8.js
+++ b/sdk/lib/_internal/js_runtime/lib/preambles/d8.js
@@ -10,7 +10,7 @@
 var self = this;
 if (typeof global != "undefined") self = global;  // Node.js.
 
-(function(self) {
+(function(self, scriptArguments) {
   // Using strict mode to avoid accidentally defining global variables.
   "use strict"; // Should be first statement of this function.
 
@@ -270,9 +270,9 @@
   // Global properties. "self" refers to the global object, so adding a
   // property to "self" defines a global variable.
   self.self = self;
-  self.dartMainRunner = function(main, args) {
+  self.dartMainRunner = function(main, ignored_args) {
     // Initialize.
-    var action = function() { main(args); }
+    var action = function() { main(scriptArguments, null); }
     eventLoop(action);
   };
   self.setTimeout = addTimer;
@@ -345,4 +345,4 @@
   // so pretend they don't exist.
   // TODO(30217): Try to use D8's worker.
   delete self.Worker;
-})(self);
+})(self, arguments);
diff --git a/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js b/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js
index a6b41c4..48f60cd 100644
--- a/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js
+++ b/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js
@@ -4,7 +4,7 @@
 
 // Javascript preamble, that lets the output of dart2js run on JSShell.
 
-(function(self) {
+(function(self, scriptArguments) {
   // Using strict mode to avoid accidentally defining global variables.
   "use strict"; // Should be first statement of this function.
 
@@ -262,9 +262,9 @@
     }
   }
 
-  self.dartMainRunner = function(main, args) {
+  self.dartMainRunner = function(main, ignored_args) {
     // Initialize.
-    var action = function() { main(args); }
+    var action = function() { main(scriptArguments, null); }
     eventLoop(action);
   };
   self.setTimeout = addTimer;
@@ -329,7 +329,7 @@
       array[i] = Math.random() * 256;
     }
   }};
-})(this)
+})(this, typeof scriptArgs == "undefined" ? [] : scriptArgs)
 
 var getKeys = function(obj){
    var keys = [];
diff --git a/tests/language/nonfunction_type_aliases/usage_object_error_test.dart b/tests/language/nonfunction_type_aliases/usage_object_error_test.dart
index 2ea105c..cd7c78b 100644
--- a/tests/language/nonfunction_type_aliases/usage_object_error_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_object_error_test.dart
@@ -15,7 +15,12 @@
   final T v12;
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
+}
+
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
 }
 
 abstract class D2 extends C with T {}
diff --git a/tools/VERSION b/tools/VERSION
index 857b325..58c42d0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 144
+PRERELEASE 145
 PRERELEASE_PATCH 0
\ No newline at end of file