Convenience function to parse a list of experimental flags

Change-Id: Iaf25e53136bbe740756c7b047976a2483a12c8df
Reviewed-on: https://dart-review.googlesource.com/c/88840
Commit-Queue: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 1475ce7..85222be 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -8,7 +8,7 @@
 
 import 'diagnostic_message.dart' show DiagnosticMessageHandler;
 
-import 'experimental_flags.dart' show ExperimentalFlag;
+import 'experimental_flags.dart' show ExperimentalFlag, parseExperimentalFlag;
 
 import 'file_system.dart' show FileSystem;
 
@@ -196,3 +196,31 @@
   /// Whether to write a file (e.g. a dill file) when reporting a crash.
   bool writeFileOnCrashReport = true;
 }
+
+/// Parse experimental flags from a list of strings, each of which is either a
+/// flag name or a flag name prefixed by 'no-'. Return a map of flags to their
+/// values that can be passed to [experimentalFlags].
+///
+/// If an unknown flag is mentioned, or a flag is mentioned more than once,
+/// the supplied error handler is called with an error message.
+Map<ExperimentalFlag, bool> parseExperimentalFlags(
+    Iterable<String> experiments, void onError(String message)) {
+  Map<ExperimentalFlag, bool> flags = <ExperimentalFlag, bool>{};
+  if (experiments == null) return flags;
+  for (String experiment in experiments) {
+    bool value = true;
+    if (experiment.startsWith("no-")) {
+      value = false;
+      experiment = experiment.substring(3);
+    }
+    ExperimentalFlag flag = parseExperimentalFlag(experiment);
+    if (flag == null) {
+      onError("Unknown experiment: " + experiment);
+    } else if (flags.containsKey(flag)) {
+      onError("Experiment mentioned more than once: " + experiment);
+    } else {
+      flags[flag] = value;
+    }
+  }
+  return flags;
+}
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 436d523..d4ccb3a 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -12,10 +12,10 @@
     show SingleRootFileSystem;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions;
+    show CompilerOptions, parseExperimentalFlags;
 
 import 'package:front_end/src/api_prototype/experimental_flags.dart'
-    show ExperimentalFlag, parseExperimentalFlag;
+    show ExperimentalFlag;
 
 import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;
 
@@ -268,6 +268,10 @@
   "/h": "--help",
 };
 
+void throwCommandLineProblem(String message) {
+  throw new CommandLineProblem.deprecated(message);
+}
+
 ProcessedOptions analyzeCommandLine(
     String programName,
     ParsedArguments parsedArguments,
@@ -342,24 +346,8 @@
     });
   }
 
-  Map<ExperimentalFlag, bool> experimentalFlags = <ExperimentalFlag, bool>{};
-  for (String experiment in options["--enable-experiment"] ?? <String>[]) {
-    bool value = true;
-    if (experiment.startsWith("no-")) {
-      value = false;
-      experiment = experiment.substring(3);
-    }
-    ExperimentalFlag flag = parseExperimentalFlag(experiment);
-    if (flag == null) {
-      throw new CommandLineProblem.deprecated(
-          "Unknown experiment: " + experiment);
-    }
-    if (experimentalFlags.containsKey(flag)) {
-      throw new CommandLineProblem.deprecated(
-          "Experiment mentioned more than once: " + experiment);
-    }
-    experimentalFlags[flag] = value;
-  }
+  Map<ExperimentalFlag, bool> experimentalFlags = parseExperimentalFlags(
+      options["--enable-experiment"], throwCommandLineProblem);
 
   if (programName == "compile_platform") {
     if (arguments.length != 5) {