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

Unified Diff: mojo/public/dart/third_party/args/lib/src/parser.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/public/dart/third_party/args/lib/src/parser.dart
diff --git a/mojo/public/dart/third_party/args/lib/src/parser.dart b/mojo/public/dart/third_party/args/lib/src/parser.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a10692d4ed84e328122ecefce672089a48dede34
--- /dev/null
+++ b/mojo/public/dart/third_party/args/lib/src/parser.dart
@@ -0,0 +1,289 @@
+// Copyright (c) 2013, 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.
+
+library args.src.parser;
+
+import 'arg_parser.dart';
+import 'arg_results.dart';
+import 'option.dart';
+
+final _SOLO_OPT = new RegExp(r'^-([a-zA-Z0-9])$');
+final _ABBR_OPT = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$');
+final _LONG_OPT = new RegExp(r'^--([a-zA-Z\-_0-9]+)(=(.*))?$');
+
+/// The actual argument parsing class.
+///
+/// Unlike [ArgParser] which is really more an "arg grammar", this is the class
+/// that does the parsing and holds the mutable state required during a parse.
+class Parser {
+ /// If parser is parsing a command's options, this will be the name of the
+ /// command. For top-level results, this returns `null`.
+ final String commandName;
+
+ /// The parser for the supercommand of this command parser, or `null` if this
+ /// is the top-level parser.
+ final Parser parent;
+
+ /// The grammar being parsed.
+ final ArgParser grammar;
+
+ /// The arguments being parsed.
+ final List<String> args;
+
+ /// The remaining non-option, non-command arguments.
+ final rest = <String>[];
+
+ /// The accumulated parsed options.
+ final Map<String, dynamic> results = <String, dynamic>{};
+
+ Parser(this.commandName, this.grammar, this.args, this.parent, rest) {
+ if (rest != null) this.rest.addAll(rest);
+ }
+
+ /// The current argument being parsed.
+ String get current => args[0];
+
+ /// Parses the arguments. This can only be called once.
+ ArgResults parse() {
+ var arguments = args.toList();
+ var commandResults = null;
+
+ // Parse the args.
+ while (args.length > 0) {
+ if (current == '--') {
+ // Reached the argument terminator, so stop here.
+ args.removeAt(0);
+ break;
+ }
+
+ // Try to parse the current argument as a command. This happens before
+ // options so that commands can have option-like names.
+ var command = grammar.commands[current];
+ if (command != null) {
+ validate(rest.isEmpty, 'Cannot specify arguments before a command.');
+ var commandName = args.removeAt(0);
+ var commandParser = new Parser(commandName, command, args, this, rest);
+ commandResults = commandParser.parse();
+
+ // All remaining arguments were passed to command so clear them here.
+ rest.clear();
+ break;
+ }
+
+ // Try to parse the current argument as an option. Note that the order
+ // here matters.
+ if (parseSoloOption()) continue;
+ if (parseAbbreviation(this)) continue;
+ if (parseLongOption()) continue;
+
+ // This argument is neither option nor command, so stop parsing unless
+ // the [allowTrailingOptions] option is set.
+ if (!grammar.allowTrailingOptions) break;
+ rest.add(args.removeAt(0));
+ }
+
+ // Invoke the callbacks.
+ grammar.options.forEach((name, option) {
+ if (option.callback == null) return;
+ option.callback(option.getOrDefault(results[name]));
+ });
+
+ // Add in the leftover arguments we didn't parse to the innermost command.
+ rest.addAll(args);
+ args.clear();
+ return newArgResults(
+ grammar, results, commandName, commandResults, rest, arguments);
+ }
+
+ /// Pulls the value for [option] from the second argument in [args].
+ ///
+ /// Validates that there is a valid value there.
+ void readNextArgAsValue(Option option) {
+ // Take the option argument from the next command line arg.
+ validate(args.length > 0, 'Missing argument for "${option.name}".');
+
+ setOption(results, option, current);
+ args.removeAt(0);
+ }
+
+ /// Tries to parse the current argument as a "solo" option, which is a single
+ /// hyphen followed by a single letter.
+ ///
+ /// We treat this differently than collapsed abbreviations (like "-abc") to
+ /// handle the possible value that may follow it.
+ bool parseSoloOption() {
+ var soloOpt = _SOLO_OPT.firstMatch(current);
+ if (soloOpt == null) return false;
+
+ var option = grammar.findByAbbreviation(soloOpt[1]);
+ if (option == null) {
+ // Walk up to the parent command if possible.
+ validate(
+ parent != null, 'Could not find an option or flag "-${soloOpt[1]}".');
+ return parent.parseSoloOption();
+ }
+
+ args.removeAt(0);
+
+ if (option.isFlag) {
+ setFlag(results, option, true);
+ } else {
+ readNextArgAsValue(option);
+ }
+
+ return true;
+ }
+
+ /// Tries to parse the current argument as a series of collapsed abbreviations
+ /// (like "-abc") or a single abbreviation with the value directly attached
+ /// to it (like "-mrelease").
+ bool parseAbbreviation(Parser innermostCommand) {
+ var abbrOpt = _ABBR_OPT.firstMatch(current);
+ if (abbrOpt == null) return false;
+
+ // If the first character is the abbreviation for a non-flag option, then
+ // the rest is the value.
+ var c = abbrOpt[1].substring(0, 1);
+ var first = grammar.findByAbbreviation(c);
+ if (first == null) {
+ // Walk up to the parent command if possible.
+ validate(
+ parent != null, 'Could not find an option with short name "-$c".');
+ return parent.parseAbbreviation(innermostCommand);
+ } else if (!first.isFlag) {
+ // The first character is a non-flag option, so the rest must be the
+ // value.
+ var value = '${abbrOpt[1].substring(1)}${abbrOpt[2]}';
+ setOption(results, first, value);
+ } else {
+ // If we got some non-flag characters, then it must be a value, but
+ // if we got here, it's a flag, which is wrong.
+ validate(abbrOpt[2] == '',
+ 'Option "-$c" is a flag and cannot handle value '
+ '"${abbrOpt[1].substring(1)}${abbrOpt[2]}".');
+
+ // Not an option, so all characters should be flags.
+ // We use "innermostCommand" here so that if a parent command parses the
+ // *first* letter, subcommands can still be found to parse the other
+ // letters.
+ for (var i = 0; i < abbrOpt[1].length; i++) {
+ var c = abbrOpt[1].substring(i, i + 1);
+ innermostCommand.parseShortFlag(c);
+ }
+ }
+
+ args.removeAt(0);
+ return true;
+ }
+
+ void parseShortFlag(String c) {
+ var option = grammar.findByAbbreviation(c);
+ if (option == null) {
+ // Walk up to the parent command if possible.
+ validate(
+ parent != null, 'Could not find an option with short name "-$c".');
+ parent.parseShortFlag(c);
+ return;
+ }
+
+ // In a list of short options, only the first can be a non-flag. If
+ // we get here we've checked that already.
+ validate(
+ option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".');
+
+ setFlag(results, option, true);
+ }
+
+ /// Tries to parse the current argument as a long-form named option, which
+ /// may include a value like "--mode=release" or "--mode release".
+ bool parseLongOption() {
+ var longOpt = _LONG_OPT.firstMatch(current);
+ if (longOpt == null) return false;
+
+ var name = longOpt[1];
+ var option = grammar.options[name];
+ if (option != null) {
+ args.removeAt(0);
+ if (option.isFlag) {
+ validate(longOpt[3] == null,
+ 'Flag option "$name" should not be given a value.');
+
+ setFlag(results, option, true);
+ } else if (longOpt[3] != null) {
+ // We have a value like --foo=bar.
+ setOption(results, option, longOpt[3]);
+ } else {
+ // Option like --foo, so look for the value as the next arg.
+ readNextArgAsValue(option);
+ }
+ } else if (name.startsWith('no-')) {
+ // See if it's a negated flag.
+ name = name.substring('no-'.length);
+ option = grammar.options[name];
+ if (option == null) {
+ // Walk up to the parent command if possible.
+ validate(parent != null, 'Could not find an option named "$name".');
+ return parent.parseLongOption();
+ }
+
+ args.removeAt(0);
+ validate(option.isFlag, 'Cannot negate non-flag option "$name".');
+ validate(option.negatable, 'Cannot negate option "$name".');
+
+ setFlag(results, option, false);
+ } else {
+ // Walk up to the parent command if possible.
+ validate(parent != null, 'Could not find an option named "$name".');
+ return parent.parseLongOption();
+ }
+
+ return true;
+ }
+
+ /// Called during parsing to validate the arguments.
+ ///
+ /// Throws a [FormatException] if [condition] is `false`.
+ void validate(bool condition, String message) {
+ if (!condition) throw new FormatException(message);
+ }
+
+ /// Validates and stores [value] as the value for [option], which must not be
+ /// a flag.
+ void setOption(Map results, Option option, String value) {
+ assert(!option.isFlag);
+
+ if (!option.isMultiple) {
+ _validateAllowed(option, value);
+ results[option.name] = value;
+ return;
+ }
+
+ var list = results.putIfAbsent(option.name, () => []);
+
+ if (option.splitCommas) {
+ for (var element in value.split(",")) {
+ _validateAllowed(option, element);
+ list.add(element);
+ }
+ } else {
+ _validateAllowed(option, value);
+ list.add(value);
+ }
+ }
+
+ /// Validates and stores [value] as the value for [option], which must be a
+ /// flag.
+ void setFlag(Map results, Option option, bool value) {
+ assert(option.isFlag);
+ results[option.name] = value;
+ }
+
+ /// Validates that [value] is allowed as a value of [option].
+ void _validateAllowed(Option option, String value) {
+ if (option.allowed == null) return;
+
+ validate(option.allowed.contains(value),
+ '"$value" is not an allowed value for option "${option.name}".');
+ }
+}
« no previous file with comments | « mojo/public/dart/third_party/args/lib/src/option.dart ('k') | mojo/public/dart/third_party/args/lib/src/usage.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698