| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library args.src.parser; | 5 library args.src.parser; |
| 6 | 6 |
| 7 import '../args.dart'; | 7 import '../args.dart'; |
| 8 | 8 |
| 9 final _SOLO_OPT = new RegExp(r'^-([a-zA-Z0-9])$'); | 9 final _SOLO_OPT = new RegExp(r'^-([a-zA-Z0-9])$'); |
| 10 final _ABBR_OPT = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$'); | 10 final _ABBR_OPT = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$'); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 * command. For top-level results, this returns `null`. | 21 * command. For top-level results, this returns `null`. |
| 22 */ | 22 */ |
| 23 final String commandName; | 23 final String commandName; |
| 24 | 24 |
| 25 /** | 25 /** |
| 26 * The parser for the supercommand of this command parser, or `null` if this | 26 * The parser for the supercommand of this command parser, or `null` if this |
| 27 * is the top-level parser. | 27 * is the top-level parser. |
| 28 */ | 28 */ |
| 29 final Parser parent; | 29 final Parser parent; |
| 30 | 30 |
| 31 /** If `true`, parsing will continue after a non-option argument. */ | |
| 32 final bool allowTrailingOptions; | |
| 33 | |
| 34 /** The grammar being parsed. */ | 31 /** The grammar being parsed. */ |
| 35 final ArgParser grammar; | 32 final ArgParser grammar; |
| 36 | 33 |
| 37 /** The arguments being parsed. */ | 34 /** The arguments being parsed. */ |
| 38 final List<String> args; | 35 final List<String> args; |
| 39 | 36 |
| 40 /** The remaining non-option, non-command arguments. */ | 37 /** The remaining non-option, non-command arguments. */ |
| 41 final rest = <String>[]; | 38 final rest = <String>[]; |
| 42 | 39 |
| 43 /** The accumulated parsed options. */ | 40 /** The accumulated parsed options. */ |
| 44 final Map<String, dynamic> results = <String, dynamic>{}; | 41 final Map<String, dynamic> results = <String, dynamic>{}; |
| 45 | 42 |
| 46 Parser(this.commandName, this.grammar, this.args, this.parent, rest, | 43 Parser(this.commandName, this.grammar, this.args, this.parent, rest) { |
| 47 {this.allowTrailingOptions: false}) { | |
| 48 if (rest != null) this.rest.addAll(rest); | 44 if (rest != null) this.rest.addAll(rest); |
| 49 } | 45 } |
| 50 | 46 |
| 51 | 47 |
| 52 /** The current argument being parsed. */ | 48 /** The current argument being parsed. */ |
| 53 String get current => args[0]; | 49 String get current => args[0]; |
| 54 | 50 |
| 55 /** Parses the arguments. This can only be called once. */ | 51 /** Parses the arguments. This can only be called once. */ |
| 56 ArgResults parse() { | 52 ArgResults parse() { |
| 57 var commandResults = null; | 53 var commandResults = null; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 72 args.removeAt(0); | 68 args.removeAt(0); |
| 73 break; | 69 break; |
| 74 } | 70 } |
| 75 | 71 |
| 76 // Try to parse the current argument as a command. This happens before | 72 // Try to parse the current argument as a command. This happens before |
| 77 // options so that commands can have option-like names. | 73 // options so that commands can have option-like names. |
| 78 var command = grammar.commands[current]; | 74 var command = grammar.commands[current]; |
| 79 if (command != null) { | 75 if (command != null) { |
| 80 validate(rest.isEmpty, 'Cannot specify arguments before a command.'); | 76 validate(rest.isEmpty, 'Cannot specify arguments before a command.'); |
| 81 var commandName = args.removeAt(0); | 77 var commandName = args.removeAt(0); |
| 82 var commandParser = new Parser(commandName, command, args, this, rest, | 78 var commandParser = new Parser(commandName, command, args, this, rest); |
| 83 allowTrailingOptions: allowTrailingOptions); | |
| 84 commandResults = commandParser.parse(); | 79 commandResults = commandParser.parse(); |
| 85 | 80 |
| 86 // All remaining arguments were passed to command so clear them here. | 81 // All remaining arguments were passed to command so clear them here. |
| 87 rest.clear(); | 82 rest.clear(); |
| 88 break; | 83 break; |
| 89 } | 84 } |
| 90 | 85 |
| 91 // Try to parse the current argument as an option. Note that the order | 86 // Try to parse the current argument as an option. Note that the order |
| 92 // here matters. | 87 // here matters. |
| 93 if (parseSoloOption()) continue; | 88 if (parseSoloOption()) continue; |
| 94 if (parseAbbreviation(this)) continue; | 89 if (parseAbbreviation(this)) continue; |
| 95 if (parseLongOption()) continue; | 90 if (parseLongOption()) continue; |
| 96 | 91 |
| 97 // This argument is neither option nor command, so stop parsing unless | 92 // This argument is neither option nor command, so stop parsing unless |
| 98 // the [allowTrailingOptions] option is set. | 93 // the [allowTrailingOptions] option is set. |
| 99 if (!allowTrailingOptions) break; | 94 if (!grammar.allowTrailingOptions) break; |
| 100 rest.add(args.removeAt(0)); | 95 rest.add(args.removeAt(0)); |
| 101 } | 96 } |
| 102 | 97 |
| 103 // Set unspecified multivalued arguments to their default value, | 98 // Set unspecified multivalued arguments to their default value, |
| 104 // if any, and invoke the callbacks. | 99 // if any, and invoke the callbacks. |
| 105 grammar.options.forEach((name, option) { | 100 grammar.options.forEach((name, option) { |
| 106 if (option.allowMultiple && | 101 if (option.allowMultiple && |
| 107 results[name].length == 0 && | 102 results[name].length == 0 && |
| 108 option.defaultValue != null) { | 103 option.defaultValue != null) { |
| 109 results[name].add(option.defaultValue); | 104 results[name].add(option.defaultValue); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 '"$value" is not an allowed value for option "${option.name}".'); | 284 '"$value" is not an allowed value for option "${option.name}".'); |
| 290 } | 285 } |
| 291 | 286 |
| 292 if (option.allowMultiple) { | 287 if (option.allowMultiple) { |
| 293 results[option.name].add(value); | 288 results[option.name].add(value); |
| 294 } else { | 289 } else { |
| 295 results[option.name] = value; | 290 results[option.name] = value; |
| 296 } | 291 } |
| 297 } | 292 } |
| 298 } | 293 } |
| OLD | NEW |