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

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