ROSE  0.11.145.0
util/Sawyer/CommandLine.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 /* Command-line switch parsing. */
9 #ifndef Sawyer_CommandLine_H
10 #define Sawyer_CommandLine_H
11 
12 #include <Sawyer/Assert.h>
13 #include <Sawyer/BitFlags.h>
14 #include <Sawyer/DocumentMarkup.h>
15 #include <Sawyer/IntervalSet.h>
16 #include <Sawyer/Map.h>
17 #include <Sawyer/Message.h>
18 #include <Sawyer/Optional.h>
19 #include <Sawyer/Sawyer.h>
20 #include <Sawyer/Set.h>
21 #include <Sawyer/SharedPointer.h>
22 
23 #include <boost/algorithm/string/case_conv.hpp>
24 #include <boost/any.hpp>
25 #include <boost/cstdint.hpp>
26 #include <boost/foreach.hpp>
27 #include <boost/lexical_cast.hpp>
28 #include <boost/numeric/conversion/cast.hpp>
29 #include <cerrno>
30 #include <ctype.h>
31 #include <list>
32 #include <regex>
33 #include <set>
34 #include <stdexcept>
35 #include <string>
36 #include <vector>
37 
38 namespace Sawyer { // documented in Sawyer.h
39 
164 namespace CommandLine {
165 
166 SAWYER_EXPORT extern const std::string STR_NONE;
167 class Switch;
168 class SwitchGroup;
169 class Parser;
170 class ParserResult;
171 
173 enum SortOrder {
183 };
184 
186 enum Canonical {
191 };
192 
199 };
200 
206 };
207 
209 // Program argument cursor
211 
216 struct SAWYER_EXPORT Location {
217  size_t idx;
218  size_t offset;
222  Location(): idx(0), offset(0) {}
223 
225  Location(size_t idx, size_t offset): idx(idx), offset(offset) {}
226 
229  bool operator==(const Location &other) const { return idx==other.idx && offset==other.offset; }
230 
233  bool operator!=(const Location &other) const { return !(*this==other); }
234 
237  bool operator<(const Location &other) const { return idx<other.idx || (idx==other.idx && offset<other.offset); }
238 
241  bool operator<=(const Location &other) const { return *this<other || *this==other; }
242 };
243 
245 SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const Location&);
246 
250 SAWYER_EXPORT extern const Location NOWHERE;
251 
255 class SAWYER_EXPORT Cursor {
256 #include <Sawyer/WarningsOff.h>
257  std::vector<std::string> strings_;
258  Location loc_;
259 #include <Sawyer/WarningsRestore.h>
260 public:
263  Cursor(const std::vector<std::string> &strings): strings_(strings) { location(Location()); }
264 
267  Cursor(const std::string &string): strings_(1, string) { location(Location()); }
268 
270  Cursor() {}
271 
273  const std::vector<std::string>& strings() const { return strings_; }
274 
292  const Location& location() const { return loc_; }
293  Cursor& location(const Location &loc);
298  bool atArgBegin() const { return loc_.idx<strings_.size() && 0==loc_.offset; }
299 
302  bool atArgEnd() const { return loc_.idx<strings_.size() && loc_.offset>=strings_[loc_.idx].size(); }
303 
308  bool atEnd() const { return atEnd(loc_); }
309  bool atEnd(const Location &location) const { return location.idx >= strings_.size(); }
316  const std::string& arg() const { return arg(loc_); }
317  const std::string& arg(const Location &location) const;
324  std::string rest() const { return rest(loc_); }
325  std::string rest(const Location &location) const;
333  std::string substr(const Location &limit, const std::string &separator=" ") const { return substr(loc_, limit, separator); }
334  std::string substr(const Location &limit1, const Location &limit2, const std::string &separator=" ") const;
339  void replace(const std::vector<std::string>&);
340 
344  void consumeChars(size_t nchars);
345 
350  void consumeArgs(size_t nargs) {
351  loc_.idx = std::min(strings_.size(), loc_.idx+nargs);
352  loc_.offset = 0;
353  }
354  void consumeArg() { consumeArgs(1); }
362  size_t linearDistance() const;
363 };
364 
368  Cursor &cursor_;
369  Location loc_;
370  bool canceled_;
371 public:
374  ExcursionGuard(Cursor &cursor): cursor_(cursor), loc_(cursor.location()), canceled_(false) {} // implicit
375  ~ExcursionGuard() { if (!canceled_) cursor_.location(loc_); }
376 
379  void cancel() { canceled_ = true; }
380 
383  const Location &startingLocation() const { return loc_; }
384 };
385 
386 
388 // Switch value savers
390 
391 // used internally
392 class SAWYER_EXPORT ValueSaver: public SharedObject {
393 protected:
394  ValueSaver() {}
395 public:
397  virtual ~ValueSaver() {}
398  virtual void save(const boost::any&, const std::string &switchKey) = 0;
399 };
400 
401 // used internally
402 template<typename T>
403 class TypedSaver: public ValueSaver {
404  T &storage_;
405 protected:
406  TypedSaver(T &storage): storage_(storage) {}
407 public:
409  static Ptr instance(T &storage) { return Ptr(new TypedSaver(storage)); }
410  virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ {
411  storage_ = boost::any_cast<T>(value);
412  }
413 };
414 
415 // Partial specialization of TypedSaver, saving a value of any type T into a container of type CONTAINER_TEMPLATE calling the
416 // containers INSERT_METHOD with one argument: the value. The CONTAINER_TEMPLATE is the name of a class template that
417 // takes one argument: type type of value stored by the container.
418 #define SAWYER_COMMANDLINE_SEQUENCE_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
419  template<typename T> \
420  class TypedSaver<CONTAINER_TEMPLATE<T> >: public ValueSaver { \
421  CONTAINER_TEMPLATE<T> &storage_; \
422  protected: \
423  TypedSaver(CONTAINER_TEMPLATE<T> &storage): storage_(storage) {} \
424  public: \
425  static Ptr instance(CONTAINER_TEMPLATE<T> &storage) { return Ptr(new TypedSaver(storage)); } \
426  virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ { \
427  T typed = boost::any_cast<T>(value); \
428  storage_.INSERT_METHOD(typed); \
429  } \
430  }
431 
432 // Partial specialization of TypedSaver for saving values into map-like containers. The CONTAINER_TEMPLATE should take two
433 // parameters: the key type (always std::string) and the value type (not part of this specialization). The value is stored by
434 // invoking the INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to
435 // save.
436 #define SAWYER_COMMANDLINE_MAP_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
437  template<typename T> \
438  class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
439  CONTAINER_TEMPLATE<std::string, T> &storage_; \
440  protected: \
441  TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
442  public: \
443  static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
444  virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
445  T typed = boost::any_cast<T>(value); \
446  storage_.INSERT_METHOD(switchKey, typed); \
447  } \
448  }
449 
450 // Partial specialization of TypedSaver for saving values into set-like containers. The CONTAINER_TEMPLATE should take one
451 // parameter: the value type (not part of this specialization). The value is stored by invoking the INSERT_METHOD with one
452 // argument: the value to save. The value is always an interval.
453 #define SAWYER_COMMANDLINE_INTERVALSET_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
454  template<typename Interval> \
455  class TypedSaver<CONTAINER_TEMPLATE<Interval> >: public ValueSaver { \
456  CONTAINER_TEMPLATE<Interval> &storage_; \
457  protected: \
458  TypedSaver(CONTAINER_TEMPLATE<Interval> &storage): storage_(storage) {} \
459  public: \
460  static Ptr instance(CONTAINER_TEMPLATE<Interval> &storage) { return Ptr(new TypedSaver(storage)); } \
461  virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ { \
462  Interval typed = boost::any_cast<Interval>(value); \
463  storage_.INSERT_METHOD(typed); \
464  } \
465  }
466 
467 // Partial specialization of TypedSaver for saving values into map-like containers using the STL approach where the insert
468 // operator takes an std::pair(key,value) rather than two arguments. The CONTAINER_TEMPLATE should take two parameters: the key
469 // type (always std::string) and the value type (not part of this specialization). The value is stored by invoking the
470 // INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to save.
471 #define SAWYER_COMMANDLINE_MAP_PAIR_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
472  template<typename T> \
473  class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
474  CONTAINER_TEMPLATE<std::string, T> &storage_; \
475  protected: \
476  TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
477  public: \
478  static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
479  virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
480  T typed = boost::any_cast<T>(value); \
481  storage_.INSERT_METHOD(std::make_pair(switchKey, typed)); \
482  } \
483  }
484 
485 SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::vector, push_back);
486 SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::list, push_back);
487 SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::set, insert);
488 SAWYER_COMMANDLINE_SEQUENCE_SAVER(Sawyer::Container::Set, insert);
489 SAWYER_COMMANDLINE_SEQUENCE_SAVER(Optional, operator=);
490 SAWYER_COMMANDLINE_SEQUENCE_SAVER(BitFlags, set);
491 SAWYER_COMMANDLINE_MAP_PAIR_SAVER(std::map, insert);
492 SAWYER_COMMANDLINE_MAP_SAVER(Sawyer::Container::Map, insert);
493 SAWYER_COMMANDLINE_INTERVALSET_SAVER(Sawyer::Container::IntervalSet, insert);
494 
496 // Parsed value
498 
505 class SAWYER_EXPORT ParsedValue {
506 #include <Sawyer/WarningsOff.h>
507  boost::any value_;
508  Location valueLocation_;
509  std::string valueString_;
510  std::string switchKey_;
511  Location switchLocation_;
512  std::string switchString_;
513  size_t keySequence_;
514  size_t switchSequence_;
515  ValueSaver::Ptr valueSaver_;
516 #include <Sawyer/WarningsRestore.h>
517 
518 public:
520  ParsedValue(): keySequence_(0), switchSequence_(0) {}
521 
531  ParsedValue(const boost::any value, const Location &loc, const std::string &str, const ValueSaver::Ptr &saver)
532  : value_(value), valueLocation_(loc), valueString_(str), keySequence_(0), switchSequence_(0), valueSaver_(saver) {}
533 
536  ParsedValue& switchInfo(const std::string &key, const Location &loc, const std::string &str) {
537  switchKey_ = key;
538  switchLocation_ = loc;
539  switchString_ = str;
540  return *this;
541  }
542 
543 private:
544  friend class ParserResult;
545  void sequenceInfo(size_t keySequence, size_t switchSequence) {
546  keySequence_ = keySequence;
547  switchSequence_ = switchSequence;
548  }
549 
550 public:
556  const boost::any& value() const { return value_; }
557  void value(const boost::any &v) { value_ = v; }
563  Location valueLocation() const { return valueLocation_; }
564  ParsedValue& valueLocation(const Location &loc) { valueLocation_ = loc; return *this; }
568  const std::string &string() const { return valueString_; }
569 
575  int asInt() const;
576  unsigned asUnsigned() const;
577  long asLong() const;
578  unsigned long asUnsignedLong() const;
579  boost::int64_t asInt64() const;
580  boost::uint64_t asUnsigned64() const;
581  double asDouble() const;
582  float asFloat() const;
583  bool asBool() const;
584  std::string asString() const;
589  template<typename T> T as() const { return boost::any_cast<T>(value_); }
590 
593  ParsedValue& switchKey(const std::string &s) { switchKey_ = s; return *this; }
594  const std::string& switchKey() const { return switchKey_; }
604  const std::string& switchString() const { return switchString_; }
605 
609  Location switchLocation() const { return switchLocation_; }
610 
613  size_t keySequence() const { return keySequence_; }
614 
617  size_t switchSequence() const { return switchSequence_; }
618 
621  const ValueSaver::Ptr valueSaver() const { return valueSaver_; }
622 
625  void save() const;
626 
628  bool isEmpty() const { return value_.empty(); }
629 
631  void print(std::ostream&) const;
632 };
633 
635 SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const ParsedValue&);
636 
638 typedef std::vector<ParsedValue> ParsedValues;
639 
640 
641 
642 
644 // Switch argument parsers
646 
699 class SAWYER_EXPORT ValueParser: public SharedObject, public SharedFromThis<ValueParser> {
700 #include <Sawyer/WarningsOff.h>
701  ValueSaver::Ptr valueSaver_;
702 #include <Sawyer/WarningsRestore.h>
703 protected:
706 
708  explicit ValueParser(const ValueSaver::Ptr &valueSaver): valueSaver_(valueSaver) {}
709 public:
712 
713  virtual ~ValueParser() {}
714 
718  ParsedValue matchString(const std::string&) /*final*/;
719 
724  ParsedValue match(Cursor&) /*final*/;
725 
740  Ptr valueSaver(const ValueSaver::Ptr &f) { valueSaver_ = f; return sharedFromThis(); }
741  const ValueSaver::Ptr valueSaver() const { return valueSaver_; }
744 private:
747  virtual ParsedValue operator()(Cursor&);
748  virtual ParsedValue operator()(const char *input, const char **endptr, const Location&);
750 };
751 
752 // used internally to convert from one type to another via boost::lexical_cast or throw a runtime_error with a decent message.
753 template<typename T>
754 struct LexicalCast {
755  static T convert(const std::string &src) {
756  try {
757  return boost::lexical_cast<T>(src);
758  } catch (const boost::bad_lexical_cast &e) {
759  throw std::runtime_error(e.what());
760  }
761  }
762 };
763 
764 template<>
765 struct LexicalCast<boost::regex> {
766  static boost::regex convert(const std::string &src) {
767  return boost::regex(src);
768  }
769 };
770 
771 template<>
772 struct LexicalCast<std::regex> {
773  static std::regex convert(const std::string &src) {
774  return std::regex(src);
775  }
776 };
777 
778 template<>
779 struct LexicalCast<boost::filesystem::path> {
780  static boost::filesystem::path convert(const std::string &src) {
781  return boost::filesystem::path(src);
782  }
783 };
784 
785 template<>
786 struct LexicalCast<boost::any> {
787  static boost::any convert(const std::string &src) {
788  return src;
789  }
790 };
791 
792 template<typename T>
793 struct LexicalCast<Optional<T> > {
794  static T convert(const std::string &src) {
795  return LexicalCast<T>::convert(src);
796  }
797 };
798 
799 template<typename T>
801  static T convert(const std::string &src) {
802  return LexicalCast<T>::convert(src);
803  }
804 };
805 
806 template<typename T>
807 struct LexicalCast<Sawyer::Container::Map<std::string, T> > {
808  static T convert(const std::string &src) {
809  return LexicalCast<T>::convert(src);
810  }
811 };
812 
813 template<typename T>
814 struct LexicalCast<std::vector<T> > {
815  static T convert(const std::string &src) {
816  return LexicalCast<T>::convert(src);
817  }
818 };
819 
820 template<typename T>
821 struct LexicalCast<std::set<T> > {
822  static T convert(const std::string &src) {
823  return LexicalCast<T>::convert(src);
824  }
825 };
826 
827 template<typename T>
828 struct LexicalCast<std::list<T> > {
829  static T convert(const std::string &src) {
830  return LexicalCast<T>::convert(src);
831  }
832 };
833 
834 template<typename T>
835 struct LexicalCast<std::map<std::string, T> > {
836  static T convert(const std::string &src) {
837  return LexicalCast<T>::convert(src);
838  }
839 };
840 
864 template<typename T>
865 class AnyParser: public ValueParser {
866 protected:
869 
872 public:
875 
879  static Ptr instance() { return Ptr(new AnyParser); }
880 
884  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new AnyParser(valueSaver)); }
885 private:
886  virtual ParsedValue operator()(Cursor &cursor) /*override*/ {
887  if (cursor.atEnd())
888  throw std::runtime_error("string expected");
889  Location startLoc = cursor.location();
890  std::string s = cursor.rest();
891  cursor.consumeChars(s.size());
892  return ParsedValue(LexicalCast<T>::convert(s), startLoc, s, valueSaver());
893  }
894 };
895 
896 // used internally to cast one numeric type to another and throw a range_error with a decent message.
897 template<typename Target, typename Source>
898 struct NumericCast {
899  static Target convert(Source from, const std::string &parsed) {
900  try {
901  return boost::numeric_cast<Target>(from);
902  } catch (const boost::numeric::positive_overflow&) {
903  std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::highest());
904  throw std::range_error("parsed string \""+parsed+"\" is greater than "+bound);
905  } catch (const boost::numeric::negative_overflow&) {
906  std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::lowest());
907  throw std::range_error("parsed string \""+parsed+"\" is less than "+bound);
908  } catch (const boost::numeric::bad_numeric_cast&) {
909  throw std::range_error("cannot cast \""+parsed+"\" to destination type");
910  }
911  }
912 };
913 
914 // partial specialization for Sawyer::Optional<Target>
915 template<typename Target, typename Source>
916 struct NumericCast<Optional<Target>, Source> {
917  static Target convert(Source from, const std::string &parsed) {
918  return NumericCast<Target, Source>::convert(from, parsed);
919  }
920 };
921 
922 // partial specialization for std::vector<Target>
923 template<typename Target, typename Source>
924 struct NumericCast<std::vector<Target>, Source> {
925  static Target convert(Source from, const std::string &parsed) {
926  return NumericCast<Target, Source>::convert(from, parsed);
927  }
928 };
929 
930 // partial specialization for std::list<Target>
931 template<typename Target, typename Source>
932 struct NumericCast<std::list<Target>, Source> {
933  static Target convert(Source from, const std::string &parsed) {
934  return NumericCast<Target, Source>::convert(from, parsed);
935  }
936 };
937 
938 // partial specialization for std::set<Target>
939 template<typename Target, typename Source>
940 struct NumericCast<std::set<Target>, Source> {
941  static Target convert(Source from, const std::string &parsed) {
942  return NumericCast<Target, Source>::convert(from, parsed);
943  }
944 };
945 
946 // partial specialization for Sawyer::Container::Set<Target>
947 template<typename Target, typename Source>
948 struct NumericCast<Sawyer::Container::Set<Target>, Source> {
949  static Target convert(Source from, const std::string &parsed) {
950  return NumericCast<Target, Source>::convert(from, parsed);
951  }
952 };
953 
954 // partial specialization for std::map<std::string, Target>
955 template<typename Target, typename Source>
956 struct NumericCast<std::map<std::string, Target>, Source> {
957  static Target convert(Source from, const std::string &parsed) {
958  return NumericCast<Target, Source>::convert(from, parsed);
959  }
960 };
961 
962 // partial specialization for Sawyer::Container::Map<std::string, Target>
963 template<typename Target, typename Source>
964 struct NumericCast<Sawyer::Container::Map<std::string, Target>, Source> {
965  static Target convert(Source from, const std::string &parsed) {
966  return NumericCast<Target, Source>::convert(from, parsed);
967  }
968 };
969 
979 template<typename T>
980 class IntegerParser: public ValueParser {
981 protected:
984 
986  explicit IntegerParser(const ValueSaver::Ptr &valueSaver): ValueParser(valueSaver) {}
987 public:
990 
997  static Ptr instance() { return Ptr(new IntegerParser); }
998 
1005  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new IntegerParser(valueSaver)); }
1006 private:
1007  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1008  errno = 0;
1009  boost::int64_t big = strtoll(input, (char**)rest, 0);
1010  if (*rest==input)
1011  throw std::runtime_error("integer expected");
1012  while (isspace(**rest)) ++*rest;
1013  std::string parsed(input, *rest-input);
1014  if (ERANGE==errno)
1015  throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1016  return ParsedValue(NumericCast<T, boost::int64_t>::convert(big, parsed), loc, parsed, valueSaver());
1017  }
1018 };
1019 
1030 template<typename T>
1032 protected:
1035 
1038 public:
1041 
1045  static Ptr instance() { return Ptr(new NonNegativeIntegerParser); }
1046 
1050  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new NonNegativeIntegerParser(valueSaver)); }
1051 private:
1052  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1053  errno = 0;
1054  while (isspace(*input)) ++input;
1055  if ('+'!=*input && !isdigit(*input))
1056  throw std::runtime_error("unsigned integer expected");
1057  boost::uint64_t big = strtoull(input, (char**)rest, 0);
1058  if (*rest==input)
1059  throw std::runtime_error("unsigned integer expected");
1060  while (isspace(**rest)) ++*rest;
1061  std::string parsed(input, *rest-input);
1062  if (ERANGE==errno)
1063  throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1064  return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1065  }
1066 };
1067 
1078 template<typename T>
1080 protected:
1083 
1086 public:
1089 
1093  static Ptr instance() { return Ptr(new PositiveIntegerParser); }
1094 
1098  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new PositiveIntegerParser(valueSaver)); }
1099 private:
1100  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1101  errno = 0;
1102  while (isspace(*input)) ++input;
1103  if ('+'!=*input && !isdigit(*input))
1104  throw std::runtime_error("positive integer expected");
1105  boost::uint64_t big = strtoull(input, (char**)rest, 0);
1106  if (*rest==input || big==0)
1107  throw std::runtime_error("positive integer expected");
1108  while (isspace(**rest)) ++*rest;
1109  std::string parsed(input, *rest-input);
1110  if (ERANGE==errno)
1111  throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1112  return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1113  }
1114 };
1115 
1125 template<typename T>
1127 protected:
1130 
1133 public:
1136 
1140  static Ptr instance() { return Ptr(new RealNumberParser); }
1141 
1145  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new RealNumberParser(valueSaver)); }
1146 private:
1147  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1148  double big = strtod(input, (char**)rest);
1149  if (*rest==input)
1150  throw std::runtime_error("real number expected");
1151  while (isspace(**rest)) ++*rest;
1152  std::string parsed(input, *rest-input);
1153  return ParsedValue(NumericCast<T, double>::convert(big, parsed), loc, parsed, valueSaver());
1154  }
1155 };
1156 
1163 template<typename T>
1165 protected:
1168 
1171 public:
1174 
1178  static Ptr instance() { return Ptr(new BooleanParser); }
1179 
1183  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new BooleanParser(valueSaver)); }
1184 private:
1185  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1186  static const char *neg[] = {"false", "off", "no", "0", "f", "n"}; // longest to shortest
1187  static const char *pos[] = {"true", "yes", "on", "1", "t", "y"};
1188  const char *start = input;
1189  while (isspace(*input)) ++input;
1190  for (int negpos=0; negpos<2; ++negpos) {
1191  const char **list = 0==negpos ? neg : pos;
1192  size_t listsz = 0==negpos ? sizeof(neg)/sizeof(*neg) : sizeof(pos)/sizeof(*pos);
1193  for (size_t i=0; i<listsz; ++i) {
1194  if (0==my_strncasecmp(list[i], input, strlen(list[i]))) {
1195  *rest = input + strlen(list[i]);
1196  while (isspace(**rest)) ++*rest;
1197  std::string parsed(start, *rest-start);
1198  return ParsedValue(NumericCast<T, bool>::convert(0!=negpos, parsed), loc, parsed, valueSaver());
1199  }
1200  }
1201  }
1202  throw std::runtime_error("Boolean expected");
1203  }
1204 
1205  // Microsoft doesn't have the POSIX.1-2001 strncasecmp function
1206  int my_strncasecmp(const char *a, const char *b, size_t nchars) {
1207  ASSERT_not_null(a);
1208  ASSERT_not_null(b);
1209  for (size_t i=0; i<nchars; ++i) {
1210  if (!a[i] || !b[i])
1211  return a[i] ? 1 : (b[i] ? -1 : 0);
1212  char achar = (char)tolower(a[i]);
1213  char bchar = (char)tolower(b[i]);
1214  if (achar != bchar)
1215  return achar < bchar ? -1 : 1;
1216  }
1217  return 0;
1218  }
1219 };
1220 
1229 class SAWYER_EXPORT StringSetParser: public ValueParser {
1230 #include <Sawyer/WarningsOff.h>
1231  std::vector<std::string> strings_;
1232 #include <Sawyer/WarningsRestore.h>
1233 protected:
1236 
1238  StringSetParser(const ValueSaver::Ptr &valueSaver): ValueParser(valueSaver) {}
1239 public:
1242 
1246  static Ptr instance() { return Ptr(new StringSetParser); }
1247 
1251  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new StringSetParser(valueSaver)); }
1252 
1255  Ptr with(const std::string &s) { return with(&s, &s+1); }
1256  Ptr with(const std::vector<std::string> sv) { return with(sv.begin(), sv.end()); }
1257  template<class InputIterator>
1258  Ptr with(InputIterator begin, InputIterator end) {
1259  strings_.insert(strings_.end(), begin, end);
1260  return sharedFromThis().dynamicCast<StringSetParser>();
1261  }
1264 private:
1265  virtual ParsedValue operator()(Cursor&) /*override*/;
1266 };
1267 
1275 template<typename T>
1276 class EnumParser: public ValueParser {
1277  StringSetParser::Ptr strParser_;
1279 protected:
1281  EnumParser(): strParser_(StringSetParser::instance()) {}
1282 
1285 public:
1288 
1292  static Ptr instance() { return Ptr(new EnumParser); }
1293 
1297  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new EnumParser(valueSaver)); }
1298 
1300  Ptr with(const std::string &name, T value) {
1301  strParser_->with(name);
1302  members_.insert(name, value);
1303  return sharedFromThis().template dynamicCast<EnumParser>();
1304  }
1305 private:
1306  virtual ParsedValue operator()(Cursor &cursor) /*override*/ {
1307  ParsedValue strVal = strParser_->match(cursor);
1308  return ParsedValue(members_[strVal.string()], strVal.valueLocation(), strVal.string(), valueSaver());
1309  }
1310 };
1311 
1319 class SAWYER_EXPORT ListParser: public ValueParser {
1320  typedef std::pair<ValueParser::Ptr, std::string> ParserSep;
1321 #include <Sawyer/WarningsOff.h>
1322  std::vector<ParserSep> elements_;
1323  size_t minLength_, maxLength_; // limits on the number of values permitted
1324 #include <Sawyer/WarningsRestore.h>
1325 protected:
1327  ListParser(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe)
1328  : minLength_(1), maxLength_((size_t)-1) {
1329  elements_.push_back(ParserSep(firstElmtType, separatorRe));
1330  }
1331 public:
1334 
1336  typedef std::list<ParsedValue> ValueList;
1337 
1345  static Ptr instance(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe="[,;:]\\s*") {
1346  return Ptr(new ListParser(firstElmtType, separatorRe));
1347  }
1348 
1355  Ptr nextMember(const ValueParser::Ptr &elmtType, const std::string &separatorRe="[,;:]\\s*") {
1356  elements_.push_back(ParserSep(elmtType, separatorRe));
1357  return sharedFromThis().dynamicCast<ListParser>();
1358  }
1359 
1366  Ptr limit(size_t minLength, size_t maxLength);
1367  Ptr limit(size_t maxLength) { return limit(std::min(minLength_, maxLength), maxLength); }
1368  Ptr exactly(size_t length) { return limit(length, length); }
1370 private:
1371  virtual ParsedValue operator()(Cursor&) /*override*/;
1372 };
1373 
1429 template<typename T>
1430 typename AnyParser<T>::Ptr anyParser(T &storage) {
1432 }
1433 template<typename T>
1435  return AnyParser<T>::instance();
1436 }
1437 SAWYER_EXPORT AnyParser<std::string>::Ptr anyParser();
1438 
1439 template<typename T>
1440 typename IntegerParser<T>::Ptr integerParser(T &storage) {
1442 }
1443 template<typename T>
1445  return IntegerParser<T>::instance();
1446 }
1447 SAWYER_EXPORT IntegerParser<int>::Ptr integerParser();
1448 
1449 template<typename T>
1452 }
1453 template<typename T>
1456 }
1457 SAWYER_EXPORT NonNegativeIntegerParser<unsigned>::Ptr nonNegativeIntegerParser();
1458 
1459 template<typename T>
1462 }
1463 template<typename T>
1466 }
1467 SAWYER_EXPORT PositiveIntegerParser<unsigned>::Ptr positiveIntegerParser();
1468 
1469 template<typename T>
1472 }
1473 template<typename T>
1476 }
1477 SAWYER_EXPORT RealNumberParser<double>::Ptr realNumberParser();
1478 
1479 template<typename T>
1480 typename BooleanParser<T>::Ptr booleanParser(T &storage) {
1482 }
1483 template<typename T>
1485  return BooleanParser<T>::instance();
1486 }
1487 SAWYER_EXPORT BooleanParser<bool>::Ptr booleanParser();
1488 
1489 template<typename T>
1490 typename EnumParser<T>::Ptr enumParser(T &storage) {
1492 }
1493 template<typename T>
1494 typename EnumParser<T>::Ptr enumParser(std::vector<T> &storage) {
1495  return EnumParser<T>::instance(TypedSaver<std::vector<T> >::instance(storage));
1496 }
1497 template<typename T>
1499  return EnumParser<T>::instance(TypedSaver<Optional<T> >::instance(storage));
1500 }
1501 template<typename T>
1503  return EnumParser<T>::instance(TypedSaver<BitFlags<T> >::instance(storage));
1504 }
1505 template<typename T>
1507  return EnumParser<T>::instance();
1508 }
1509 
1510 SAWYER_EXPORT StringSetParser::Ptr stringSetParser(std::string &storage);
1511 SAWYER_EXPORT StringSetParser::Ptr stringSetParser();
1512 
1513 SAWYER_EXPORT ListParser::Ptr listParser(const ValueParser::Ptr&, const std::string &sepRe="[,;:]\\s*");
1517 // Switch argument descriptors
1520 
1535 class SAWYER_EXPORT SwitchArgument {
1536 #include <Sawyer/WarningsOff.h>
1537  std::string name_; // argument name for synopsis
1538  ValueParser::Ptr parser_; // how to match and parse this argument
1539  ParsedValue defaultValue_; // default value if the argument is optional
1540 #include <Sawyer/WarningsRestore.h>
1541 public:
1544  explicit SwitchArgument(const std::string &name, const ValueParser::Ptr &parser = anyParser())
1545  : name_(name), parser_(parser) {}
1546 
1550  SwitchArgument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValueString)
1551  : name_(name), parser_(parser), defaultValue_(parser->matchString(defaultValueString)) {
1552  defaultValue_.valueLocation(NOWHERE);
1553  }
1554 
1556  bool isRequired() const {
1557  return defaultValue_.isEmpty();
1558  }
1559 
1562  bool isOptional() const {
1563  return !isRequired();
1564  }
1565 
1571  const std::string &name() const { return name_; }
1572 
1574  std::string nameAsText() const;
1575 
1577  const ParsedValue& defaultValue() const {
1578  return defaultValue_;
1579  }
1580 
1584  const std::string& defaultValueString() const {
1585  return defaultValue_.string();
1586  }
1587 
1589  const ValueParser::Ptr& parser() const { return parser_; }
1590 };
1591 
1592 
1594 // Switch actions
1596 
1612 class SAWYER_EXPORT SwitchAction: public SharedObject {
1613 public:
1616  virtual ~SwitchAction() {}
1617 
1619  void run(const ParserResult &parserResult) /*final*/ { (*this)(parserResult); }
1620 protected:
1621  virtual void operator()(const ParserResult&) = 0;
1622 };
1623 
1627 class SAWYER_EXPORT ShowVersion: public SwitchAction {
1628 #include <Sawyer/WarningsOff.h>
1629  std::string versionString_;
1630 #include <Sawyer/WarningsRestore.h>
1631 protected:
1633  explicit ShowVersion(const std::string &versionString): versionString_(versionString) {}
1634 public:
1637 
1642  static Ptr instance(const std::string &versionString) { return Ptr(new ShowVersion(versionString)); }
1643 protected:
1644  virtual void operator()(const ParserResult&) /*overload*/;
1645 };
1646 
1649 class SAWYER_EXPORT ShowVersionAndExit: public ShowVersion {
1650  int exitStatus_;
1651 protected:
1653  explicit ShowVersionAndExit(const std::string &versionString, int exitStatus)
1654  : ShowVersion(versionString), exitStatus_(exitStatus) {}
1655 public:
1658 
1663  static Ptr instance(const std::string &versionString, int exitStatus) {
1664  return Ptr(new ShowVersionAndExit(versionString, exitStatus));
1665  }
1666 protected:
1667  virtual void operator()(const ParserResult&) /*overload*/;
1668 };
1669 
1674 class SAWYER_EXPORT ShowHelp: public SwitchAction {
1675 protected:
1678 public:
1681 
1686  static Ptr instance() { return Ptr(new ShowHelp); }
1687 protected:
1688  virtual void operator()(const ParserResult&) /*override*/;
1689 };
1690 
1693 class SAWYER_EXPORT ShowHelpAndExit: public ShowHelp {
1694  int exitStatus_;
1695 protected:
1697  ShowHelpAndExit(int exitStatus): exitStatus_(exitStatus) {}
1698 public:
1701 
1706  static Ptr instance(int exitStatus) { return Ptr(new ShowHelpAndExit(exitStatus)); }
1707 protected:
1708  virtual void operator()(const ParserResult&) /*override*/;
1709 };
1710 
1726 class SAWYER_EXPORT ConfigureDiagnostics: public SwitchAction {
1727 #include <Sawyer/WarningsOff.h>
1728  std::string switchKey_;
1729  Message::Facilities &facilities_;
1730  bool exitOnHelp_;
1731 #include <Sawyer/WarningsRestore.h>
1732 protected:
1734  ConfigureDiagnostics(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp)
1735  : switchKey_(switchKey), facilities_(facilities), exitOnHelp_(exitOnHelp) {}
1736 public:
1739 
1744  static Ptr instance(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp=true) {
1745  return Ptr(new ConfigureDiagnostics(switchKey, facilities, exitOnHelp));
1746  }
1747 
1753  bool exitOnHelp() const { return exitOnHelp_; }
1754  void exitOnHelp(bool b) { exitOnHelp_=b; }
1756 protected:
1757  virtual void operator()(const ParserResult&) /*override*/;
1758 };
1759 
1767 class SAWYER_EXPORT ConfigureDiagnosticsQuiet: public SwitchAction {
1768 #include <Sawyer/WarningsOff.h>
1769  Message::Facilities &facilities_;
1770 #include <Sawyer/WarningsRestore.h>
1771 protected:
1773  : facilities_(facilities) {
1774  }
1775 
1776 public:
1779 
1784  static Ptr instance(Message::Facilities &facilities) {
1785  return Ptr(new ConfigureDiagnosticsQuiet(facilities));
1786  }
1787 
1788 protected:
1789  virtual void operator()(const ParserResult&) /*override*/;
1790 };
1791 
1811 template<class Functor>
1812 class UserAction: public SwitchAction {
1813  Functor &functor_;
1814 protected:
1816  UserAction(Functor &f): functor_(f) {}
1817 public:
1820 
1825  static Ptr instance(Functor &f) { return Ptr(new UserAction(f)); }
1826 protected:
1827  virtual void operator()(const ParserResult &parserResult) /*override*/ { (functor_)(parserResult); }
1828 };
1829 
1859 SAWYER_EXPORT ShowVersion::Ptr showVersion(const std::string &versionString);
1860 SAWYER_EXPORT ShowVersionAndExit::Ptr showVersionAndExit(const std::string &versionString, int exitStatus);
1861 
1862 SAWYER_EXPORT ShowHelp::Ptr showHelp();
1863 
1864 SAWYER_EXPORT ShowHelpAndExit::Ptr showHelpAndExit(int exitStatus);
1865 
1866 SAWYER_EXPORT ConfigureDiagnostics::Ptr configureDiagnostics(const std::string&, Message::Facilities&, bool exitOnHelp=true);
1867 
1868 SAWYER_EXPORT ConfigureDiagnosticsQuiet::Ptr configureDiagnosticsQuiet(Message::Facilities&);
1869 
1870 template<class Functor>
1871 typename UserAction<Functor>::Ptr userAction(const Functor &functor) {
1872  return UserAction<Functor>::instance(functor);
1873 }
1878 // Switch value agumenters
1881 
1896 class SAWYER_EXPORT ValueAugmenter: public SharedObject {
1897 public:
1900  virtual ~ValueAugmenter() {}
1901 
1906  virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) = 0;
1907 };
1908 
1921 template<typename T>
1922 class Sum: public ValueAugmenter {
1923 protected:
1925  Sum() {}
1926 public:
1929 
1934  static Ptr instance() { return Ptr(new Sum<T>); }
1935 
1936  virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) /*override*/ {
1937  ASSERT_forbid(newValues.empty());
1938  T sum = 0;
1939  BOOST_FOREACH (const ParsedValue &pv, savedValues)
1940  sum = sum + boost::any_cast<T>(pv.value());
1941  BOOST_FOREACH (const ParsedValue &pv, newValues)
1942  sum = sum + boost::any_cast<T>(pv.value());
1943  ParsedValue pval = newValues.front(); // so we keep the same location information
1944  pval.value(sum);
1945  ParsedValues pvals;
1946  pvals.push_back(pval);
1947  return pvals;
1948  }
1949 };
1950 
1980 template<typename T>
1981 typename Sum<T>::Ptr sum() {
1982  return Sum<T>::instance();
1983 }
1988 // Switch descriptors
1991 
1992 // Used internally to pass around switch properties that are common among parsers, switch groups, and switches.
1993 struct SAWYER_EXPORT ParsingProperties {
1994 #include <Sawyer/WarningsOff.h>
1995  std::vector<std::string> longPrefixes; // Prefixes for long command-line switches
1996  bool inheritLongPrefixes; // True if this also inherits longPrefixes from a higher layer
1997  std::vector<std::string> shortPrefixes;
1998  bool inheritShortPrefixes;
1999  std::vector<std::string> valueSeparators; // What separates a long switch from its value.
2000  bool inheritValueSeparators;
2001  ShowGroupName showGroupName; // How to show group name in switch synopsis
2002 #include <Sawyer/WarningsRestore.h>
2004  : inheritLongPrefixes(true), inheritShortPrefixes(true), inheritValueSeparators(true),
2005  showGroupName(SHOW_GROUP_INHERIT) {}
2006  ParsingProperties inherit(const ParsingProperties &base) const;
2007 };
2008 
2017 };
2018 
2041 class SAWYER_EXPORT Switch {
2042 private:
2043 #include <Sawyer/WarningsOff.h>
2044  std::vector<std::string> longNames_; // Long name of switch, or empty string.
2045  std::string shortNames_; // Optional short names for this switch.
2046  std::string key_; // Unique key, usually the long name or the first short name.
2047  ParsingProperties properties_; // Properties valid at multiple levels of the hierarchy.
2048  std::string synopsis_; // User-defined synopsis or empty string.
2049  std::string documentation_; // Main documentation for the switch.
2050  std::string documentationKey_; // For sorting documentation.
2051  bool hidden_; // Whether to hide documentation.
2052  std::vector<SwitchArgument> arguments_; // Arguments with optional default values.
2053  SwitchAction::Ptr action_; // Optional action to perform during ParserResult::apply.
2054  WhichValue whichValue_; // Which switch values should be saved.
2055  ValueAugmenter::Ptr valueAugmenter_; // Used if <code>whichValue_==SAVE_AUGMENTED</code>.
2056  ParsedValue intrinsicValue_; // Value for switches that have no declared arguments.
2057  bool explosiveLists_; // Whether to expand ListParser::ValueList into separate values.
2058  SwitchSkipping skipping_; // Whether to skip over this switch without saving or acting.
2059 #include <Sawyer/WarningsRestore.h>
2060 
2061 public:
2074  explicit Switch(const std::string &longName, char shortName='\0')
2075  : hidden_(false), whichValue_(SAVE_LAST), intrinsicValue_(ParsedValue(true, NOWHERE, "true", ValueSaver::Ptr())),
2076  explosiveLists_(false), skipping_(SKIP_NEVER) {
2077  init(longName, shortName);
2078  }
2079 
2080  // FIXME[Robb Matzke 2014-03-03]: test that "--prefix=5" works when names are "pre" and "prefix" in that order
2085  Switch& longName(const std::string &name);
2086  const std::string& longName() const { return longNames_.front(); }
2087  const std::vector<std::string>& longNames() const { return longNames_; }
2095  Switch& shortName(char c) { if (c) shortNames_ += std::string(1, c); return *this; }
2096  const std::string& shortNames() const { return shortNames_; }
2101  std::string preferredName() const { return longNames_.empty() ? std::string(1, shortNames_[0]) : longNames_[0]; }
2102 
2111  Switch& key(const std::string &s) { key_ = s; return *this; }
2112  const std::string &key() const { return key_; }
2146  Switch& synopsis(const std::string &s) { synopsis_ = s; return *this; }
2147  std::string synopsis() const;
2185  Switch& doc(const std::string &s) { documentation_ = s; return *this; }
2186  const std::string& doc() const { return documentation_; }
2193  Switch& docKey(const std::string &s) { documentationKey_ = s; return *this; }
2194  const std::string &docKey() const { return documentationKey_; }
2201  Switch& hidden(bool b) { hidden_ = b; return *this; }
2202  bool hidden() const { return hidden_; }
2216  Switch& skipping(SwitchSkipping how) { skipping_ = how; return *this; }
2217  SwitchSkipping skipping() const { return skipping_; }
2231  Switch& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2232  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2233  Switch& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2234  const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2248  Switch& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2249  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2250  Switch& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2251  const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2270  Switch& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2271  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2272  Switch& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2273  const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2298  Switch& argument(const std::string &name, const ValueParser::Ptr &parser = anyParser());
2299  Switch& argument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValue);
2300  Switch& argument(const SwitchArgument &arg) { arguments_.push_back(arg); return *this; }
2301  const SwitchArgument& argument(size_t idx) const { return arguments_[idx]; }
2302  const std::vector<SwitchArgument>& arguments() const { return arguments_; }
2306  size_t nArguments() const { return arguments_.size(); }
2307 
2310  size_t nRequiredArguments() const;
2311 
2341  template<typename T>
2342  Switch& intrinsicValue(const T &value, T &storage) {
2343  intrinsicValue_ = ParsedValue(value, NOWHERE, boost::lexical_cast<std::string>(value), TypedSaver<T>::instance(storage));
2344  return *this;
2345  }
2346  Switch& intrinsicValue(const char *value, std::string &storage) {
2347  intrinsicValue_ = ParsedValue(std::string(value), NOWHERE, value, TypedSaver<std::string>::instance(storage));
2348  return *this;
2349  }
2350  Switch& intrinsicValue(const std::string &text, const ValueParser::Ptr &p) {
2351  intrinsicValue_ = p->matchString(text);
2352  intrinsicValue_.valueLocation(NOWHERE);
2353  return *this;
2354  }
2355  Switch& intrinsicValue(const std::string &text) {
2356  intrinsicValue_ = anyParser()->matchString(text);
2357  intrinsicValue_.valueLocation(NOWHERE);
2358  return *this;
2359  }
2360  Switch& intrinsicValue(const ParsedValue &value) { intrinsicValue_ = value; return *this; }
2361  ParsedValue intrinsicValue() const { return intrinsicValue_; }
2386  Switch& explosiveLists(bool b) { explosiveLists_ = b; return *this; }
2387  bool explosiveLists() const { return explosiveLists_; }
2411  Switch& action(const SwitchAction::Ptr &f) { action_ = f; return *this; }
2412  const SwitchAction::Ptr& action() const { return action_; }
2440  Switch& whichValue(WhichValue s) { whichValue_ = s; return *this; }
2441  WhichValue whichValue() const { return whichValue_; }
2452  Switch& valueAugmenter(const ValueAugmenter::Ptr &f) { valueAugmenter_ = f; return *this; }
2453  ValueAugmenter::Ptr valueAugmenter() const { return valueAugmenter_; }
2456 public:
2457  // Used internally
2458  const ParsingProperties& properties() const { return properties_; }
2459 
2460 private:
2461  friend class Parser;
2462  friend class ParserResult;
2463 
2464  void init(const std::string &longName, char shortName);
2465 
2467  std::runtime_error noSeparator(const std::string &switchString, const Cursor&, const ParsingProperties&) const;
2468 
2470  std::runtime_error extraTextAfterSwitch(const std::string &switchString, const Location &endOfSwitch, const Cursor&,
2471  const ParsingProperties&, const ParsedValues&) const;
2472 
2474  std::runtime_error extraTextAfterArgument(const Cursor&, const ParsedValue &va) const;
2475 
2477  std::runtime_error notEnoughArguments(const std::string &switchString, const Cursor&, size_t nargs) const;
2478 
2480  std::runtime_error missingArgument(const std::string &switchString, const Cursor &cursor,
2481  const SwitchArgument &sa, const std::string &reason) const;
2482 
2484  std::runtime_error malformedArgument(const std::string &switchString, const Cursor &cursor,
2485  const SwitchArgument &sa, const std::string &reason) const;
2486 
2493  size_t matchLongName(Cursor&/*in,out*/, const ParsingProperties &props,
2494  const std::string &optionalPart, const std::string &requiredPart) const;
2495 
2502  size_t matchShortName(Cursor&/*in,out*/, const ParsingProperties &props, std::string &name) const;
2503 
2505  bool explode(ParsedValues &pvals /*in,out*/) const;
2506 
2511  void matchLongArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2512  ParsedValues &result /*out*/) const;
2513 
2517  void matchShortArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2518  ParsedValues &result /*out*/, bool mayNestle) const;
2519 
2527  size_t matchArguments(const std::string &switchString, const Location &endOfSwitch, Cursor &cursor /*in,out*/,
2528  const ParsingProperties &props, ParsedValues &result /*out*/, bool isLongSwitch) const;
2529 
2531  std::string synopsisForArgument(const SwitchArgument&) const;
2532 
2533  // If the synopsis is empty, create one from an optional switch group and name space separator
2534  std::string synopsis(const ParsingProperties &swProps, const SwitchGroup *sg, const std::string &nameSpaceSeparator) const;
2535 };
2536 
2538 // Switch groups
2540 
2541 
2569 class SAWYER_EXPORT SwitchGroup {
2570 #include <Sawyer/WarningsOff.h>
2571  std::vector<Switch> switches_;
2572  ParsingProperties properties_;
2573  std::string name_; // name optionally prepended to all switches
2574  std::string title_; // title showing in documentation
2575  std::string docKey_; // for sorting
2576  std::string documentation_;
2577  SortOrder switchOrder_;
2578 #include <Sawyer/WarningsRestore.h>
2579 public:
2582 
2589  explicit SwitchGroup(const std::string &title, const std::string &docKey="")
2590  : title_(title), docKey_(docKey), switchOrder_(DOCKEY_ORDER) {}
2591 
2597  const std::string& title() const { return title_; }
2598  SwitchGroup& title(const std::string &title) { title_ = title; return *this; }
2611  const std::string& name() const { return name_; }
2612  SwitchGroup& name(const std::string &name) { name_ = name; return *this; }
2627  const std::string& docKey() const { return docKey_; }
2628  SwitchGroup& docKey(const std::string &key) { docKey_ = key; return *this; }
2643  SwitchGroup& doc(const std::string &s) { documentation_ = s; return *this; }
2644  const std::string& doc() const { return documentation_; }
2653  ShowGroupName showingGroupNames() const { return properties_.showGroupName; }
2654  void showingGroupNames(ShowGroupName x) { properties_.showGroupName = x; }
2659  SwitchGroup& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2660  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2661  SwitchGroup& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2662  const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2667  SwitchGroup& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2668  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2669  SwitchGroup& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2670  const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2675  SwitchGroup& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2676  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2677  SwitchGroup& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2678  const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2682  size_t nSwitches() const { return switches_.size(); }
2683 
2686  const std::vector<Switch>& switches() const { return switches_; }
2687 
2689  bool nameExists(const std::string &switchName);
2690 
2693  const Switch& getByName(const std::string &switchName);
2694 
2696  bool keyExists(const std::string &switchKey);
2697 
2699  const Switch& getByKey(const std::string &switchKey);
2700 
2702  SwitchGroup& insert(const Switch&);
2703 
2705  SwitchGroup& insert(const SwitchGroup&);
2706 
2708  SwitchGroup& removeByIndex(size_t n);
2709 
2712  SwitchGroup& removeByName(const std::string &switchName);
2713 
2715  SwitchGroup& removeByKey(const std::string &switchKey);
2716 
2728  const SortOrder& switchOrder() const { return switchOrder_; }
2729  SwitchGroup& switchOrder(SortOrder order) { switchOrder_ = order; return *this; }
2732 public:
2733  // Used internally
2734  const ParsingProperties& properties() const { return properties_; }
2735 
2736 private:
2737  friend class Parser;
2738  bool removeByPointer(const void*);
2739 };
2740 
2743 
2746 
2748 // Parser
2750 
2756 class SAWYER_EXPORT Parser {
2757 #include <Sawyer/WarningsOff.h>
2758  std::vector<SwitchGroup> switchGroups_;
2759  ParsingProperties properties_;
2760  std::string groupNameSeparator_;
2761  std::vector<std::string> terminationSwitches_;
2762  bool shortMayNestle_;
2763  std::vector<std::string> inclusionPrefixes_;
2764  bool skipNonSwitches_;
2765  bool skipUnknownSwitches_;
2766  mutable std::string programName_;
2767  std::string purpose_;
2768  std::string versionString_;
2769  mutable std::string dateString_;
2770  int chapterNumber_;
2771  std::string chapterName_;
2773  StringStringMap sectionDoc_;
2774  StringStringMap sectionOrder_;
2775  Message::SProxy errorStream_;
2776  Optional<std::string> exitMessage_;
2777  SortOrder switchGroupOrder_;
2778  bool reportingAmbiguities_;
2779  std::string environmentVariable_;
2780 #include <Sawyer/WarningsRestore.h>
2781 
2782 public:
2786  : groupNameSeparator_("-"), shortMayNestle_(true), skipNonSwitches_(false), skipUnknownSwitches_(false),
2787  versionString_("alpha"), chapterNumber_(1), chapterName_("User Commands"), switchGroupOrder_(INSERTION_ORDER),
2788  reportingAmbiguities_(true) {
2789  init();
2790  }
2791 
2796  switchGroups_.push_back(sg);
2797  return *this;
2798  }
2799  Parser& with(const SwitchGroup &sg, const std::string &docKey) {
2800  switchGroups_.push_back(sg);
2801  switchGroups_.back().docKey(docKey);
2802  return *this;
2803  }
2804  Parser& with(const std::vector<SwitchGroup> &sgs) {
2805  switchGroups_.insert(switchGroups_.end(), sgs.begin(), sgs.end());
2806  return *this;
2807  }
2808  Parser& with(const Switch &sw) {
2809  switchGroups_.push_back(SwitchGroup().insert(sw));
2810  return *this;
2811  }
2812  Parser& with(Switch sw, const std::string &docKey) {
2813  sw.docKey(docKey);
2814  switchGroups_.push_back(SwitchGroup().insert(sw));
2815  return *this;
2816  }
2822  const std::vector<SwitchGroup>& switchGroups() const {
2823  return switchGroups_;
2824  }
2825  std::vector<SwitchGroup>& switchGroups() {
2826  return switchGroups_;
2827  }
2833  bool switchGroupExists(const std::string &name) const;
2834 
2841  const SwitchGroup& switchGroup(const std::string &name) const;
2842  SwitchGroup& switchGroup(const std::string &name);
2849  bool eraseSwitchGroup(const std::string &name);
2850 
2862  bool reportingAmbiguities() const { return reportingAmbiguities_; }
2863  Parser& reportingAmbiguities(bool b) { reportingAmbiguities_ = b; return *this; }
2873  const std::string& groupNameSeparator() const { return groupNameSeparator_; }
2874  Parser& groupNameSeparator(const std::string &s) { groupNameSeparator_ = s; return *this; }
2886  ShowGroupName showingGroupNames() const { return properties_.showGroupName; }
2887  Parser& showingGroupNames(ShowGroupName x) { properties_.showGroupName = x; return *this; }
2894  Parser& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2895  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2896  Parser& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2897  const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2904  Parser& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2905  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2906  Parser& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2907  const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2916  Parser& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2917  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2918  Parser& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2919  const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2926  Parser& resetTerminationSwitches(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2927  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2928  Parser& terminationSwitch(const std::string &s1) { terminationSwitches_.push_back(s1); return *this; }
2929  const std::vector<std::string>& terminationSwitches() const { return terminationSwitches_; }
2939  Parser& shortMayNestle(bool b) { shortMayNestle_ = b; return *this; }
2940  bool shortMayNestle() const { return shortMayNestle_; }
2954  Parser& resetInclusionPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2955  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2956  Parser& inclusionPrefix(const std::string &s1) { inclusionPrefixes_.push_back(s1); return *this; }
2957  const std::vector<std::string>& inclusionPrefixes() const { return inclusionPrefixes_; }
2967  Parser& skippingNonSwitches(bool b) { skipNonSwitches_ = b; return *this; }
2968  bool skippingNonSwitches() const { return skipNonSwitches_; }
2977  Parser& skippingUnknownSwitches(bool b) { skipUnknownSwitches_ = b; return *this; }
2978  bool skippingUnknownSwitches() const { return skipUnknownSwitches_; }
2998  Parser& errorStream(const Message::SProxy &stream) { errorStream_ = stream; return *this; }
2999  const Message::SProxy& errorStream() const { return errorStream_; }
3008  Parser& exitMessage(const std::string &s) { exitMessage_ = s; return *this; }
3009  std::string exitMessage() const { return exitMessage_ ? *exitMessage_ : std::string(); }
3018  Parser& environmentVariable(const std::string &s) { environmentVariable_ = s; return *this; }
3019  const std::string& environmentVariable() const { return environmentVariable_; }
3025  ParserResult parse(int argc, char *argv[]);
3026 
3028  ParserResult parse(const std::vector<std::string>&);
3029 
3030 #if 0 /* [Robb Matzke 2014-03-04] */
3031 
3033  template<typename Iterator>
3034  ParserResult parse(Iterator begin, Iterator end) {
3035  std::vector<std::string> args(begin, end);
3036  return parse(args);
3037  }
3038 #endif
3039 
3043  static std::vector<std::string> splitLineIntoWords(std::string);
3044 
3050  static std::vector<std::string> readArgsFromFile(const std::string &filename);
3051 
3056  static std::vector<std::string> readArgsFromEnvVar(const std::string &varName);
3057 
3062  std::vector<std::string> expandIncludedFiles(const std::vector<std::string> &args);
3063 
3066  DEFAULT_GROUPING = 0,
3067  PROHIBIT_EMPTY_GROUPS = 0x0001,
3068  SPLIT_SINGLE_GROUP = 0x0002
3069  };
3070 
3078  std::vector<std::vector<std::string> >
3079  regroupArgs(const std::vector<std::string> &args,
3081  unsigned flags = 0 /*GroupingFlags*/);
3082 
3086  Parser& programName(const std::string& programName) { programName_ = programName; return *this; }
3087  const std::string& programName() const;
3094  Parser& purpose(const std::string &purpose) { purpose_ = purpose; return *this; }
3095  const std::string& purpose() const { return purpose_; }
3101  Parser& version(const std::string &versionString, const std::string &dateString="");
3102  Parser& version(const std::pair<std::string, std::string> &p) { return version(p.first, p.second); }
3103  std::pair<std::string, std::string> version() const;
3121  Parser& chapter(int chapterNumber, const std::string &chapterName="");
3122  Parser& chapter(const std::pair<int, std::string> &p) { return chapter(p.first, p.second); }
3123  std::pair<int, std::string> chapter() const;
3164  Parser& doc(const std::string &sectionName, const std::string &docKey, const std::string &text);
3165  Parser& doc(const std::string &sectionName, const std::string &text) { return doc(sectionName, sectionName, text); }
3166  Parser& doc(const std::pair<std::string /*sectionName*/, std::string /*text*/>&);
3167  std::vector<std::string> docSections() const;
3168  std::string docForSwitches() const;
3169  std::string docForSection(const std::string &sectionName) const;
3176  std::string documentationMarkup() const;
3177 
3181  std::string podDocumentation() const;
3182 
3184  std::string textDocumentation() const;
3185 
3187  void emitDocumentationToPager() const;
3188 
3189  template<class Grammar>
3190  void emitDocumentationToPager() const {
3191  Grammar grammar;
3192  initDocGrammar(grammar);
3193  grammar.title(programName(), boost::lexical_cast<std::string>(chapter().first), chapter().second);
3194  grammar.version(version().first, version().second);
3195  grammar.emit(documentationMarkup());
3196  }
3197 
3203  SortOrder switchGroupOrder() const { return switchGroupOrder_; }
3204  Parser& switchGroupOrder(SortOrder order) { switchGroupOrder_ = order; return *this; }
3210  void insertLongSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3211 
3215  void insertShortSwitchStrings(NamedSwitches &index /*in,out*/) const;
3216 
3221  void insertSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3222 
3226  static void printIndex(std::ostream&, const NamedSwitches&, const std::string &linePrefix = "");
3227 
3231  NamedSwitches findAmbiguities() const;
3232 
3236  NamedSwitches findUnresolvableAmbiguities() const;
3237 
3249  Sawyer::Optional<Switch> removeMatchingSwitch(const std::string &arg);
3250  Sawyer::Optional<Switch> removeMatchingSwitch(const std::vector<std::string> &args);
3253 public:
3254  // Used internally
3255  const ParsingProperties& properties() const { return properties_; }
3256 
3257 private:
3258  void init();
3259 
3260  // Implementation for the public parse methods.
3261  ParserResult parseInternal(std::vector<std::string> programArguments);
3262 
3263  // Parse one switch from the current position in the command line and return the switch descriptor. If the cursor is at
3264  // the end of the command line then return false without updating the cursor or parsed values. If the cursor is at a
3265  // termination switch (e.g., "--") then consume the terminator and return false. If the switch name is valid but the
3266  // arguments cannot be parsed, then throw an error. If the cursor is at what appears to be a switch but no matching switch
3267  // declaration can be found, then throw an error. The cursor will not be modified when an error is thrown.
3268  bool parseOneSwitch(Cursor&, const NamedSwitches &ambiguities, ParserResult&/*out*/);
3269 
3276  const Switch* parseLongSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities, Optional<std::runtime_error>&);
3277 
3286  const Switch* parseShortSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities,
3287  Optional<std::runtime_error>&, bool mayNestle);
3288 
3289  // Returns true if the program argument at the cursor looks like it might be a switch. Apparent switches are any program
3290  // argument that starts with a long or short prefix.
3291  bool apparentSwitch(const Cursor&) const;
3292 
3293  // Returns the best prefix for each switch--the one used for documentation
3294  void preferredSwitchPrefixes(Container::Map<std::string, std::string> &prefixMap /*out*/) const;
3295 
3296  // Construct an error message for an ambiguous switch, switchString, having an optional group name part (including the
3297  // separator), and the required switch name. The switchString must be present in the ambiguities table.
3298  std::string ambiguityErrorMesg(const std::string &longSwitchString, const std::string &optionalPart,
3299  const std::string &longSwitchName, const NamedSwitches &ambiguities);
3300  std::string ambiguityErrorMesg(const std::string &shortSwitchString, const NamedSwitches &ambiguities);
3301 
3302  // Initialize a documentation parser by registering things like @s, @man, etc. The argument is a subclass such as
3303  // Document::PodMarkup.
3304  void initDocGrammar(Document::Markup::Grammar& /*in,out*/) const;
3305 
3306  // FIXME[Robb Matzke 2014-02-21]: Some way to parse command-lines from a config file, or to merge parsed command-lines with
3307  // a yaml config file, etc.
3308 };
3309 
3334 class SAWYER_EXPORT ParserResult {
3335 #include <Sawyer/WarningsOff.h>
3336  Parser parser_;
3337  Cursor cursor_;
3338  ParsedValues values_;
3339 
3340  // Maps a name to indexes into the values_ vector.
3342  NameIndex keyIndex_; // Values per switch key
3343  NameIndex switchIndex_; // Values per switch preferred name
3344 
3345  // List of parsed values organized by their location on the command line. The location is for the switch itself even if
3346  // the values are spread out across subsequent argv members. We do it this way because many of the values are defaults that
3347  // don't actually have an argv location. The integers are indexes into the values_ vector. In other words, this is a
3348  // mapping from switch location to values_ elements for the switch's values.
3350  ArgvIndex argvIndex_;
3351 
3352  // Information about program arguments that the parser skipped over. Indexes into argv_.
3353  typedef std::vector<size_t> SkippedIndex;
3354  SkippedIndex skippedIndex_;
3355 
3356  // Information about terminator switches like "--". Indexes into argv_.
3357  SkippedIndex terminators_;
3358 
3361 #include <Sawyer/WarningsRestore.h>
3362 
3363 private:
3364  friend class Parser;
3365  ParserResult(const Parser &parser, const std::vector<std::string> &argv): parser_(parser), cursor_(argv) {}
3366 
3367 public:
3368  ParserResult() {}
3369 
3372  const ParserResult& apply() const;
3373 
3376  size_t have(const std::string &switchKey) const {
3377  return keyIndex_.getOrDefault(switchKey).size();
3378  }
3379 
3398  const ParsedValue& parsed(const std::string &switchKey, size_t idx) const;
3399  ParsedValues parsed(const std::string &switchKey) const;
3412  std::vector<std::string> skippedArgs() const;
3413 
3420  std::vector<std::string> unreachedArgs() const;
3421 
3436  std::vector<std::string> unparsedArgs(bool includeTerminators=false) const;
3437 
3442  std::vector<std::string> parsedArgs() const;
3443 
3448  const std::vector<std::string>& allArgs() const { return cursor_.strings(); }
3449 
3451  const Parser& parser() const { return parser_; }
3452 
3453 private:
3454  // Insert more parsed values. Values should be inserted one switch's worth at a time (or fewer)
3455  void insertValuesForSwitch(const ParsedValues&, const Parser*, const Switch*);
3456  void insertOneValue(const ParsedValue&, const Switch*, bool save=true);
3457 
3458  // Indicate that we're skipping over a program argument
3459  void skip(const Location&);
3460 
3461  // Add a terminator
3462  void terminator(const Location&);
3463 
3464  Cursor& cursor() { return cursor_; }
3465 };
3466 
3467 } // namespace
3468 } // namespace
3469 
3470 #endif
SharedPointer< RealNumberParser > Ptr
Reference counting pointer for this class.
Switch strings that are not CANONICAL.
Switch & intrinsicValue(const ParsedValue &value)
Property: value for a switch that has no declared arguments.
SharedPointer< ValueParser > Ptr
Reference counting pointer for this class.
SortOrder switchGroupOrder() const
Property: How to order switch groups in documentation.
Container::Map< const SwitchGroup *, std::set< const Switch * > > GroupedSwitches
Subset of switches grouped by their switch groups.
std::vector< ParsedValue > ParsedValues
A vector of parsed values.
Ordered set of values.
Definition: Set.h:52
static Ptr instance(int exitStatus)
Allocating constructor.
Parser & switchGroupOrder(SortOrder order)
Property: How to order switch groups in documentation.
Switch & skipping(SwitchSkipping how)
Property: whether to skip over this switch.
SharedPointer< ShowHelp > Ptr
Reference counting pointer for this class.
Switch & shortName(char c)
Property: switch short name.
ListParser(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe)
Constructor for derived classes.
SwitchGroup & name(const std::string &name)
Property: Group name.
Sum< T >::Ptr sum()
Factory for value agumenter.
const std::vector< std::string > & terminationSwitches() const
Strings that indicate the end of the argument list.
Sum()
Constructor for derived classes.
void cancel()
Cancel the excursion guard.
Sums all previous and current values.
Cursor(const std::string &string)
Constructs a cursor for a single string.
std::ostream & operator<<(std::ostream &, const Location &)
Print a location.
bool isRequired() const
Returns true if this argument is required.
IntegerParser()
Constructor for derived classes.
bool exitOnHelp() const
Property: program exit after help is displayed.
static Ptr instance()
Allocating constructor.
static Ptr instance()
Allocating constructor.
const Message::SProxy & errorStream() const
Specifies a message stream to which errors are sent.
ListParser::Ptr listParser(const ValueParser::Ptr &, const std::string &sepRe="[,;:]\\s*")
Factory for value parsers.
static Ptr instance(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe="[,;:]\\s*")
Allocating constructor.
ShowGroupName
How to show group names in switch synopsis.
Cursor()
Constructs a not-very-useful cursor to nothing.
SharedPointer< EnumParser > Ptr
Reference counting pointer for this class.
const ValueSaver::Ptr valueSaver() const
Property: functor responsible for saving a parsed value in user storage.
bool skippingNonSwitches() const
Whether to skip over non-switch arguments when parsing.
SharedPointer< AnyParser > Ptr
Reference counting pointer for this class.
const ValueSaver::Ptr valueSaver() const
How to save a value at a user-supplied location.
WhichValue
Describes how to handle switches that occur multiple times.
const std::string & arg() const
Return the entire current program argument regardless of where the cursor is in that argument...
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
void consumeChars(size_t nchars)
Advance over characters.
SwitchGroup & valueSeparator(const std::string &s1)
Property: strings that separate a long switch from its value.
bool operator<(const Location &other) const
Less than.
Entities appear in the documentation in the same order they are inserted into the container...
static Ptr instance(const std::string &versionString, int exitStatus)
Allocating constructor.
const SwitchArgument & argument(size_t idx) const
Property: switch argument.
void run(const ParserResult &parserResult)
Runs the action.
SharedPointer< Sum > Ptr
Reference counting pointer for this class.
T as() const
Convenient any_cast.
const std::string & docKey() const
Property: Documentation sort key.
bool explosiveLists() const
Property: whether to convert a list value to individual values.
Switch & shortPrefix(const std::string &s1)
Property: prefixes for short names.
Location switchLocation() const
The command-line location of the switch to which this value belongs.
Parser & inclusionPrefix(const std::string &s1)
Strings that indicate that arguments are to be read from a file.
BooleanParser()
Constructor for derived classes.
SwitchGroup(const std::string &title, const std::string &docKey="")
Construct a titled group.
const std::string & doc() const
Property: Detailed description.
bool reportingAmbiguities() const
Property: Whether to report ambiguities.
std::string exitMessage() const
Extra text to print before exit.
static Ptr instance()
Allocating constructor.
RealNumberParser< T >::Ptr realNumberParser(T &storage)
Factory for value parsers.
std::vector< SwitchGroup > & switchGroups()
List of all switch groups.
size_t offset
Character offset within a program argument string.
Parser & terminationSwitch(const std::string &s1)
Strings that indicate the end of the argument list.
The result from parsing a command line.
Describes one command-line switch.
Switch & docKey(const std::string &s)
Property: key to control order of documentation.
const std::string & doc() const
Property: detailed description.
Parser & groupNameSeparator(const std::string &s)
Property: String separating group name from switch name.
Collection of facilities.
Definition: Message.h:1736
Location()
Constructs the location of the first character of the first string.
Parses any one of a set of strings.
StringSetParser::Ptr stringSetParser(std::string &storage)
Factory for value parsers.
const std::vector< std::string > & valueSeparators() const
Strings that separate a long switch from its value.
Parser & with(const Switch &sw)
Add switch declarations.
STL namespace.
Parser & environmentVariable(const std::string &s)
Name of environment variable holding initial arguments.
Holds a value or nothing.
Definition: Optional.h:49
static Ptr instance()
Allocating constructor.
const Parser & parser() const
That parser that created this result.
A collection of related switch declarations.
ShowHelp()
Constructor for derived classes.
bool atEnd() const
Returns true when the cursor is after all arguments.
Ptr with(const std::vector< std::string > sv)
Adds string members.
const std::vector< std::string > & strings() const
All strings for the cursor.
size_t nArguments() const
Total number of arguments.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Switch & action(const SwitchAction::Ptr &f)
Property: action to occur.
SharedPointer< PositiveIntegerParser > Ptr
Reference counting pointer for this class.
const std::string & defaultValueString() const
The default value string.
Base class for value agumentors.
Parser & valueSeparator(const std::string &s1)
Strings that separate a long switch from its value.
Input stream for command line arguments.
ValueParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
PositiveIntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
SwitchGroup()
Construct an unnamed, untitled group.
std::string preferredName() const
Name by which switch prefers to be known.
const std::string & groupNameSeparator() const
Property: String separating group name from switch name.
Parser & with(const std::vector< SwitchGroup > &sgs)
Add switch declarations.
SharedPointer< BooleanParser > Ptr
Reference counting pointer for this class.
bool operator!=(const Location &other) const
Inequality.
Show name as being optional, like "--[group-]switch".
SwitchGroup & longPrefix(const std::string &s1)
Property: prefixes for long names.
Save the first value, or modify previously saved value.
Describes one argument of a command-line switch.
Group inherits value from the parser.
ShowHelp::Ptr showHelp()
Factory for switch action.
A container holding a set of values.
Definition: IntervalSet.h:55
AnyParser< T >::Ptr anyParser(T &storage)
Factory for value parsers.
Parser & version(const std::pair< std::string, std::string > &p)
Program version.
AnyParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Ptr limit(size_t maxLength)
Specify limits for the number of values parsed.
Ptr with(const std::string &name, T value)
Adds enum members.
Functor to print the Unix man page.
const std::vector< std::string > & allArgs() const
The original command line.
Canonical
Format of a switch string.
Location(size_t idx, size_t offset)
Constructs a location that points to a particular character of a particular string.
Switch & doc(const std::string &s)
Property: detailed description.
Name space for the entire library.
Definition: FeasiblePath.h:767
size_t switchSequence() const
How this value relates to others created by the same switch.
ShowVersion::Ptr showVersion(const std::string &versionString)
Factory for switch action.
static Ptr instance()
Allocating constructor.
SwitchGroup & docKey(const std::string &key)
Property: Documentation sort key.
Use only the first occurrence and ignore all previous.
IntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
Parses a positive integer and converts it to numeric type T.
size_t keySequence() const
How this value relates to others with the same key.
Process switch normally, but also add to skipped list.
const std::string & string() const
String representation.
Parser & with(const SwitchGroup &sg)
Add switch declarations.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
EnumParser< T >::Ptr enumParser(T &storage)
Factory for value parsers.
const std::string & shortNames() const
Property: switch short name.
SharedPointer< ValueParser > sharedFromThis()
Create a shared pointer from this.
const ParsedValue & defaultValue() const
The parsed default value.
Ptr nextMember(const ValueParser::Ptr &elmtType, const std::string &separatorRe="[,;:]\\s*")
Specifies element type and separator.
Ptr exactly(size_t length)
Specify limits for the number of values parsed.
Location valueLocation() const
Property: command-line location from whence this value came.
std::string rest() const
Return the part of an argument at and beyond the cursor location.
SharedPointer< StringSetParser > Ptr
Reference counting pointer for this class.
const std::vector< std::string > & valueSeparators() const
Property: strings that separate a long switch from its value.
void consumeArg()
Advance the cursor to the beginning of the next string.
static Ptr instance(const std::string &versionString)
Allocating constructor.
Switch & intrinsicValue(const std::string &text)
Property: value for a switch that has no declared arguments.
const std::vector< Switch > & switches() const
List of all declared switches.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
bool atArgEnd() const
True when the cursor is at the end of an argument.
Parses an enumerated constant.
Switch(const std::string &longName, char shortName='\0')
Constructs a switch declaration.
const std::string & docKey() const
Property: key to control order of documentation.
Functor to print a version string and exit.
Information about a parsed switch value.
Parser & chapter(const std::pair< int, std::string > &p)
Manual chapter.
The parser for a program command line.
SharedPointer< IntegerParser > Ptr
Reference counting pointer for this class.
Parses a non-negative integer and converts it to numeric type T.
bool operator<=(const Location &other) const
Less than or equal.
EnumParser()
Constructor for derived classes.
SharedPointer< NonNegativeIntegerParser > Ptr
Reference counting pointer for this class.
SwitchSkipping skipping() const
Property: whether to skip over this switch.
SharedPointer< ShowHelpAndExit > Ptr
Reference counting pointer for this class.
const std::vector< std::string > & longPrefixes() const
Property: prefixes for long names.
Switch & intrinsicValue(const char *value, std::string &storage)
Property: value for a switch that has no declared arguments.
bool isEmpty() const
True if the value is void.
ParsedValue & switchInfo(const std::string &key, const Location &loc, const std::string &str)
Update switch information.
const std::string & switchString() const
The string for the switch that caused this value to be parsed.
Switch & argument(const SwitchArgument &arg)
Property: switch argument.
const std::string & environmentVariable() const
Name of environment variable holding initial arguments.
Switch & intrinsicValue(const std::string &text, const ValueParser::Ptr &p)
Property: value for a switch that has no declared arguments.
const std::vector< std::string > & longPrefixes() const
Property: prefixes for long names.
Parser & shortMayNestle(bool b)
Indicates whether short switches can nestle together.
ParsedValue & switchKey(const std::string &s)
Property: switch key.
static Ptr instance(Functor &f)
Allocating constructor.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
static Ptr instance(Message::Facilities &facilities)
Allocating constructor.
BooleanParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Parser & longPrefix(const std::string &s1)
Prefixes to use for long command-line switches.
const SortOrder & switchOrder() const
Property: Order of switches in documentation.
Creates SharedPointer from this.
Ptr with(InputIterator begin, InputIterator end)
Adds string members.
EnumParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
GroupingFlags
Bit flags for argument grouping.
SharedPointer< ConfigureDiagnostics > Ptr
Reference counting pointer for this class.
Functor to print a version string.
Parses any argument as plain text.
const Location & location() const
Property: current position of the cursor.
SharedPointer< class UserAction > Ptr
Reference counting pointer for this class.
const std::vector< SwitchArgument > & arguments() const
Property: switch argument.
Switch & whichValue(WhichValue s)
Property: how to handle multiple occurrences.
Parser & purpose(const std::string &purpose)
Program purpose.
Parser & with(const SwitchGroup &sg, const std::string &docKey)
Add switch declarations.
SwitchArgument(const std::string &name, const ValueParser::Ptr &parser=anyParser())
Construct a new required argument.
Switch & hidden(bool b)
Property: whether this switch appears in documentation.
Switch & explosiveLists(bool b)
Property: whether to convert a list value to individual values.
WhichValue whichValue() const
Property: how to handle multiple occurrences.
bool hidden() const
Property: whether this switch appears in documentation.
static Ptr instance()
Allocating constructor.
const std::string & name() const
Argument name.
StringSetParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
const std::vector< std::string > & shortPrefixes() const
Prefixes to use for short command-line switches.
ShowVersionAndExit(const std::string &versionString, int exitStatus)
Constructor for derived classes.
void value(const boost::any &v)
Property: the parsed value.
ExcursionGuard(Cursor &cursor)
Construct a guard for a cursor.
SortOrder
The order in which things are sorted in the documentation.
ShowVersionAndExit::Ptr showVersionAndExit(const std::string &versionString, int exitStatus)
Factory for switch action.
SharedPointer< U > dynamicCast() const
Dynamic cast.
This namespace contains template functions that operate on the ROSE AST.
Definition: sageFunctors.h:15
SwitchGroup & title(const std::string &title)
Property: Title of the switch group.
virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues)
Called when a switch's value is about to be stored into the ParserResult.
Parses a boolean value and converts it to numeric type T.
const Value & getOrDefault(const Key &key) const
Lookup and return a value or a default.
Definition: Sawyer/Map.h:611
const std::string & key() const
Property: value storage key.
ParsedValue & valueLocation(const Location &loc)
Property: command-line location from whence this value came.
Switch & intrinsicValue(const T &value, T &storage)
Property: value for a switch that has no declared arguments.
Parser & shortPrefix(const std::string &s1)
Prefixes to use for short command-line switches.
SharedPointer< SwitchAction > Ptr
Reference counting pointer for this class.
const std::string & longName() const
Property: switch long name.
bool isOptional() const
Returns true if this argument is not required.
AnyParser()
Constructor for derived classes.
Parses an integer and converts it to numeric type T.
ShowHelpAndExit::Ptr showHelpAndExit(int exitStatus)
Factory for switch action.
Parser & doc(const std::string &sectionName, const std::string &text)
Documentation for a section of the manual.
const std::vector< std::string > & valueSeparators() const
Property: strings that separate a long switch from its value.
Switch & longPrefix(const std::string &s1)
Property: prefixes for long names.
size_t nSwitches() const
Number of switches declared.
Parser & reportingAmbiguities(bool b)
Property: Whether to report ambiguities.
const std::vector< std::string > & inclusionPrefixes() const
Strings that indicate that arguments are to be read from a file.
bool atEnd(const Location &location) const
Returns true when the cursor is after all arguments.
Parser & skippingNonSwitches(bool b)
Whether to skip over non-switch arguments when parsing.
const Location NOWHERE
Indicates an invalid location.
ShowVersion(const std::string &versionString)
Constructor for derived classes.
SwitchGroup & shortPrefix(const std::string &s1)
Property: prefixes for short names.
const boost::any & value() const
Property: the parsed value.
Wrapper around a user functor.
ShowGroupName showingGroupNames() const
Property: How to show group names in switch documentation.
ShowGroupName showingGroupNames() const
Property: How to show group name in switch synopsis.
Switch & valueSeparator(const std::string &s1)
Property: strings that separate a long switch from its value.
RealNumberParser()
Constructor for derived classes.
Show name as being required, like "--group-switch".
Base class for reference counted objects.
Definition: SharedObject.h:64
size_t idx
Index into some vector of program argument strings.
Skip switch and its argument(s) without saving any value.
const std::vector< std::string > & shortPrefixes() const
Property: prefixes for short names.
void consumeArgs(size_t nargs)
Advance the cursor to the beginning of the next string.
const std::vector< std::string > & longPrefixes() const
Prefixes to use for long command-line switches.
Container::Map< std::string, GroupedSwitches > NamedSwitches
Subset of switches indexed by their command-line representation.
SharedPointer< ConfigureDiagnosticsQuiet > Ptr
Reference counting pointer for this class.
The switch cannot occur more than once.
const std::string & name() const
Property: Group name.
Parser & skippingUnknownSwitches(bool b)
Whether to skip over unrecognized switches.
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
Definition: Sawyer/Map.h:628
const std::string & title() const
Property: Title of the switch group.
size_t have(const std::string &switchKey) const
Returns the number of values for the specified key.
SharedPointer< ShowVersion > Ptr
Reference counting pointer for this class.
SwitchArgument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValueString)
Construct a new switch optional argument.
Entities are sorted according to their documentation keys.
StringSetParser()
Constructor for derived classes.
const Location & startingLocation() const
Starting location.
std::list< ParsedValue > ValueList
Value type for list ParsedValue.
std::enable_if< std::is_integral< IntegralType >::value, Sawyer::Result< IntegralType, std::string > >::type parse(const std::string &s)
Safely convert a string to a number.
Definition: Parse.h:60
static Ptr instance(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp=true)
Allocating constructor.
const std::vector< std::string > & shortPrefixes() const
Property: prefixes for short names.
Use only the last occurrence and ignore all previous.
Save all values as a vector.
Switch & key(const std::string &s)
Property: value storage key.
ParsedValue intrinsicValue() const
Property: value for a switch that has no declared arguments.
Ptr valueSaver(const ValueSaver::Ptr &f)
Property: functor responsible for saving a parsed value in user storage.
Cursor(const std::vector< std::string > &strings)
Construct a cursor from an ordered set of strings.
Position within a command-line.
Ptr with(const std::string &s)
Adds string members.
UserAction< Functor >::Ptr userAction(const Functor &functor)
Factory for switch action.
const std::string & purpose() const
Program purpose.
void exitOnHelp(bool b)
Property: program exit after help is displayed.
static Ptr instance()
Allocating constructor.
Base class parsing a value from input.
Switch strings that are qualified with the switch group name or which belong to a group that has no n...
const std::vector< std::string > & longNames() const
Property: switch long name.
Function to configure diagnostics to quiet mode.
NonNegativeIntegerParser< T >::Ptr nonNegativeIntegerParser(T &storage)
Factory for value parsers.
Parser & with(Switch sw, const std::string &docKey)
Add switch declarations.
IntegerParser< T >::Ptr integerParser(T &storage)
Factory for value parsers.
boost::uint64_t strtoull(const char *, char **, int)
Portable replacement for strtoull.
SharedPointer< ShowVersionAndExit > Ptr
Reference counting pointer for this class.
ConfigureDiagnosticsQuiet::Ptr configureDiagnosticsQuiet(Message::Facilities &)
Factory for switch action.
UserAction(Functor &f)
Constructor for derived classes.
static Ptr instance()
Allocating constructor.
ParsedValue(const boost::any value, const Location &loc, const std::string &str, const ValueSaver::Ptr &saver)
Construct a new value.
ValueParser()
Constructor for derived classes.
Parser & programName(const std::string &programName)
Program name for documentation.
void showingGroupNames(ShowGroupName x)
Property: How to show group name in switch synopsis.
NonNegativeIntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
bool shortMayNestle() const
Indicates whether short switches can nestle together.
const std::vector< SwitchGroup > & switchGroups() const
List of all switch groups.
boost::int64_t strtoll(const char *, char **, int)
Portable replacement for strtoll.
Parser & errorStream(const Message::SProxy &stream)
Specifies a message stream to which errors are sent.
The union of CANONICAL and NONCANONICAL.
SwitchGroup & switchOrder(SortOrder order)
Property: Order of switches in documentation.
bool atArgBegin() const
True when the cursor is at the beginning of an argument.
bool operator==(const Location &other) const
Equality.
BooleanParser< T >::Ptr booleanParser(T &storage)
Factory for value parsers.
Parses a real number and converts it to numeric type T.
const std::string & switchKey() const
Property: switch key.
ShowHelpAndExit(int exitStatus)
Constructor for derived classes.
ConfigureDiagnostics(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp)
Constructor for derived classes.
SwitchSkipping
Whether to skip a switch.
SharedPointer< ListParser > Ptr
Reference counting pointer for this class.
Switch & synopsis(const std::string &s)
Property: abstract summary of the switch syntax.
Parser & showingGroupNames(ShowGroupName x)
Property: How to show group names in switch documentation.
SharedPointer< ValueAugmenter > Ptr
Reference counting pointer for this class.
static Ptr instance()
Allocating constructor.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Functor to print the Unix man page and exit.
Container associating values with keys.
Definition: Sawyer/Map.h:66
bool initializeLibrary(size_t vmajor=0, size_t vminor=1, size_t vpatch=0, bool withThreads=0)
Explicitly initialize the library.
ValueAugmenter::Ptr valueAugmenter() const
Property: functor to agument values.
NonNegativeIntegerParser()
Constructor for derived classes.
ParsedValue()
Construct a new empty value.
RealNumberParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
Switch & valueAugmenter(const ValueAugmenter::Ptr &f)
Property: functor to agument values.
const ValueParser::Ptr & parser() const
Returns a pointer to the parser.
ConfigureDiagnostics::Ptr configureDiagnostics(const std::string &, Message::Facilities &, bool exitOnHelp=true)
Factory for switch action.
Stores a vector of enum bit flags.
const SwitchAction::Ptr & action() const
Property: action to occur.
Guards a cursor and restores it when the guard is destroyed.
static Ptr instance()
Allocating constructor.
PositiveIntegerParser< T >::Ptr positiveIntegerParser(T &storage)
Factory for value parsers.
Base class for switch actions.
PositiveIntegerParser()
Constructor for derived classes.
Parser & exitMessage(const std::string &s)
Extra text to print before exit.
SwitchGroup & doc(const std::string &s)
Property: Detailed description.
std::string substr(const Location &limit, const std::string &separator=" ") const
Returns all characters within limits.
bool skippingUnknownSwitches() const
Whether to skip over unrecognized switches.