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 |