Stan  2.10.0
probability, sampling & optimization
argument_parser.hpp
Go to the documentation of this file.
1 #ifndef STAN_SERVICES_ARGUMENTS_ARGUMENT_PARSER_HPP
2 #define STAN_SERVICES_ARGUMENTS_ARGUMENT_PARSER_HPP
3 
7 #include <cstring>
8 #include <string>
9 #include <vector>
10 
11 namespace stan {
12  namespace services {
13 
15  public:
16  explicit argument_parser(std::vector<argument*>& valid_args)
17  : _arguments(valid_args),
18  _help_flag(false),
19  _method_flag(false) {
20  _arguments.insert(_arguments.begin(), new arg_method());
21  }
22 
23  int parse_args(int argc,
24  const char* argv[],
27  if (argc == 1) {
28  print_usage(info, argv[0]);
29  return error_codes::USAGE;
30  }
31 
32  std::vector<std::string> args;
33 
34  // Fill in reverse order as parse_args pops from the back
35  for (int i = argc - 1; i > 0; --i)
36  args.push_back(std::string(argv[i]));
37 
38  bool good_arg = true;
39  bool valid_arg = true;
40  _help_flag = false;
41 
42  std::vector<argument*> unset_args = _arguments;
43 
44  while (good_arg) {
45  if (args.size() == 0)
46  break;
47 
48  good_arg = false;
49  std::string cat_name = args.back();
50 
51  // Check for method arguments entered without the method= prefix
52  if (!_method_flag) {
53  list_argument* method
54  = dynamic_cast<list_argument*>(_arguments.front());
55 
56  if (method->valid_value(cat_name)) {
57  cat_name = "method=" + cat_name;
58  args.back() = cat_name;
59  }
60  }
61 
62  std::string val_name;
63  std::string val;
64  argument::split_arg(cat_name, val_name, val);
65 
66  if (val_name == "method")
67  _method_flag = true;
68 
69  std::vector<argument*>::iterator arg_it;
70 
71  for (arg_it = unset_args.begin();
72  arg_it != unset_args.end(); ++arg_it) {
73  if ((*arg_it)->name() == cat_name) {
74  args.pop_back();
75  valid_arg &= (*arg_it)->parse_args(args, info, err, _help_flag);
76  good_arg = true;
77  break;
78  } else if ((*arg_it)->name() == val_name) {
79  valid_arg &= (*arg_it)->parse_args(args, info, err, _help_flag);
80  good_arg = true;
81  break;
82  }
83  }
84 
85  if (good_arg) unset_args.erase(arg_it);
86 
87  if (cat_name == "help") {
88  _help_flag |= true;
89  args.clear();
90  } else if (cat_name == "help-all") {
91  print_help(info, true);
92  _help_flag |= true;
93  args.clear();
94  }
95 
96  if (_help_flag) {
97  print_usage(info, argv[0]);
98  return error_codes::OK;
99  }
100 
101  if (!good_arg) {
102  err(cat_name + " is either mistyped or misplaced.");
103 
104  std::vector<std::string> valid_paths;
105 
106  for (size_t i = 0; i < _arguments.size(); ++i) {
107  _arguments.at(i)->find_arg(val_name, "", valid_paths);
108  }
109 
110  if (valid_paths.size()) {
111  err("Perhaps you meant one of the following "
112  "valid configurations?");
113  for (size_t i = 0; i < valid_paths.size(); ++i)
114  err(" " + valid_paths.at(i));
115  }
116  }
117  }
118 
119  if (_help_flag)
120  return error_codes::OK;
121 
122  if (!_method_flag)
123  err("A method must be specified!");
124 
125  return (valid_arg && good_arg && _method_flag)
127  }
128 
130  const std::string& prefix = "") {
131  for (size_t i = 0; i < _arguments.size(); ++i) {
132  _arguments.at(i)->print(w, 0, prefix);
133  }
134  }
135 
137  bool recurse) {
138  for (size_t i = 0; i < _arguments.size(); ++i) {
139  _arguments.at(i)->print_help(w, 1, recurse);
140  }
141  }
142 
144  const char* executable) {
145  std::string indent(2, ' ');
146  int width = 12;
147 
148  w(std::string("Usage: ") + executable
149  + " <arg1> <subarg1_1> ... <subarg1_m>"
150  + " ... <arg_n> <subarg_n_1> ... <subarg_n_m>");
151  w();
152 
153  w("Begin by selecting amongst the following inference methods"
154  " and diagnostics,");
155 
156  std::vector<argument*>::iterator arg_it = _arguments.begin();
157  list_argument* method = dynamic_cast<list_argument*>(*arg_it);
158 
159  std::stringstream ss;
160  ss << std::left;
161  for (std::vector<argument*>::iterator value_it
162  = method->values().begin();
163  value_it != method->values().end(); ++value_it) {
164  ss.str("");
165  ss << std::setw(width)
166  << indent + (*value_it)->name()
167  << indent + (*value_it)->description();
168  w(ss.str());
169  }
170  w();
171 
172  w("Or see help information with");
173  ss.str("");
174  ss << std::setw(width)
175  << indent + "help"
176  << indent + "Prints help";
177  w(ss.str());
178  ss.str("");
179  ss << std::setw(width)
180  << indent + "help-all"
181  << indent + "Prints entire argument tree";
182  w(ss.str());
183  w();
184 
185  w("Additional configuration available by specifying");
186 
187  ++arg_it;
188  for (; arg_it != _arguments.end(); ++arg_it) {
189  ss.str("");
190  ss << std::setw(width)
191  << indent + (*arg_it)->name()
192  << indent + (*arg_it)->description();
193  w(ss.str());
194  }
195 
196  w();
197  w(std::string("See ") + executable + " <arg1> [ help | help-all ] "
198  + "for details on individual arguments.");
199  w();
200  }
201 
202  argument* arg(const std::string& name) {
203  for (std::vector<argument*>::iterator it = _arguments.begin();
204  it != _arguments.end(); ++it)
205  if ( name == (*it)->name() )
206  return (*it);
207  return 0;
208  }
209 
210  bool help_printed() {
211  return _help_flag;
212  }
213 
214  protected:
215  std::vector<argument*>& _arguments;
216 
217  // We can also check for, and warn the user of, deprecated arguments
218  // std::vector<argument*> deprecated_arguments;
219  // check_arg_conflict
220  // Ensure non-zero intersection of valid and deprecated arguments
221 
224  };
225 
226  } // services
227 } // stan
228 
229 #endif
Probability, optimization and sampling library.
void print_usage(interface_callbacks::writer::base_writer &w, const char *executable)
static void split_arg(const std::string &arg, std::string &name, std::string &value)
Definition: argument.hpp:60
int parse_args(int argc, const char *argv[], interface_callbacks::writer::base_writer &info, interface_callbacks::writer::base_writer &err)
std::vector< argument * > & _arguments
void print(interface_callbacks::writer::base_writer &w, const std::string &prefix="")
std::vector< argument * > & values()
argument * arg(const std::string &name)
void print_help(interface_callbacks::writer::base_writer &w, bool recurse)
base_writer is an abstract base class defining the interface for Stan writer callbacks.
Definition: base_writer.hpp:20
bool valid_value(const std::string &name)
argument_parser(std::vector< argument * > &valid_args)
std::string name() const
Definition: argument.hpp:26

     [ Stan Home Page ] © 2011–2016, Stan Development Team.