CASM  1.1.0
A Clusters Approach to Statistical Mechanics
InputParser.cc
Go to the documentation of this file.
1 #include "casm/casm_io/Help.hh"
4 
5 namespace CASM {
6 
7 namespace {
8 jsonParser const &_self(jsonParser const &_input, fs::path _path) {
9  if (_path.empty()) {
10  return _input;
11  }
12  auto it = _input.find_at(_path);
13  if (it == _input.end()) {
14  return _input;
15  }
16  return *it;
17 }
18 } // namespace
19 
20 KwargsParser::KwargsParser(jsonParser const &_input, fs::path _path,
21  bool _required)
22  : input(_input),
23  path(_path),
24  self(_self(_input, _path)),
25  required(_required),
26  type_name("") {
27  if (required && !exists()) {
28  error.insert(std::string("Error: ") + "Required property '" +
29  _path.string() + "' not found.");
30  }
31 }
32 
34  if (parent_path().empty()) {
35  return input;
36  }
37  return input[parent_path().string()];
38 }
39 
40 fs::path KwargsParser::parent_path() const { return path.parent_path(); }
41 
42 std::string KwargsParser::name() const { return path.filename().string(); }
43 
44 bool KwargsParser::exists() const {
45  return path.empty() || input.find_at(path) != input.end();
46 }
47 
48 KwargsParser::map_type::const_iterator KwargsParser::begin() const {
49  return m_subparsers.begin();
50 }
51 
52 KwargsParser::map_type::const_iterator KwargsParser::end() const {
53  return m_subparsers.end();
54 }
55 
56 bool KwargsParser::valid() const {
57  auto lambda = [](const PairType &pair) { return pair.second->valid(); };
58  return Validator::valid() && std::all_of(begin(), end(), lambda);
59 }
60 
61 std::map<fs::path, std::set<std::string>> KwargsParser::all_warnings() const {
62  std::map<fs::path, std::set<std::string>> result;
63  if (this->warning.size()) {
64  result[this->path] = this->warning;
65  }
66  for (const auto &val : *this) {
67  const auto &parser = *val.second;
68  auto all_subparser_warnings = parser.all_warnings();
69  if (all_subparser_warnings.size()) {
70  result.insert(all_subparser_warnings.begin(),
71  all_subparser_warnings.end());
72  }
73  }
74  return result;
75 }
76 
77 std::map<fs::path, std::set<std::string>> KwargsParser::all_errors() const {
78  std::map<fs::path, std::set<std::string>> result;
79  if (this->error.size()) {
80  result[this->path] = this->error;
81  }
82  for (const auto &val : *this) {
83  const auto &parser = *val.second;
84  auto all_subparser_errors = parser.all_errors();
85  if (all_subparser_errors.size()) {
86  result.insert(all_subparser_errors.begin(), all_subparser_errors.end());
87  }
88  }
89  return result;
90 }
91 
92 void KwargsParser::insert(fs::path path,
93  const std::shared_ptr<KwargsParser> &subparser) {
94  m_subparsers.emplace(path, subparser);
95 }
96 
97 void KwargsParser::insert_error(fs::path option, std::string message) {
98  auto subparser =
99  std::make_shared<KwargsParser>(this->input, this->relpath(option), false);
100  subparser->error.insert(message);
101  insert(subparser->path, subparser);
102 }
103 
104 void KwargsParser::insert_warning(fs::path option, std::string message) {
105  auto subparser =
106  std::make_shared<KwargsParser>(this->input, this->relpath(option), false);
107  subparser->warning.insert(message);
108  insert(subparser->path, subparser);
109 }
110 
111 bool KwargsParser::warn_unnecessary(const std::set<std::string> &expected) {
112  bool all_necessary = true;
113  for (auto opt_it = self.begin(); opt_it != self.end(); ++opt_it) {
114  if (expected.find(opt_it.name()) == expected.end()) {
115  warning.insert(std::string("Warning: ") + "Ignoring setting '" +
116  opt_it.name() + "' (it is unrecognized or unncessary).");
117  all_necessary = false;
118  }
119  }
120  return all_necessary;
121 }
122 
123 int parse_verbosity(KwargsParser &parser, int default_verbosity) {
124  auto it = parser.self.find("verbosity");
125  if (it != parser.self.end()) {
126  std::string verbosity_string;
127  if (it->is_string()) {
128  verbosity_string = it->get<std::string>();
129  } else if (it->is_int()) {
130  verbosity_string = std::to_string(it->get<int>());
131  } else {
132  parser.error.insert(Log::invalid_verbosity_msg(verbosity_string));
133  return default_verbosity;
134  }
135 
136  auto res = Log::verbosity_level(verbosity_string);
137  if (res.first) {
138  return res.second;
139  } else {
140  parser.error.insert(Log::invalid_verbosity_msg(verbosity_string));
141  return default_verbosity;
142  }
143  } else {
144  return default_verbosity;
145  }
146 }
147 
148 void parse(InputParser<std::nullptr_t> &parser) { return; }
149 
150 void print_warnings(KwargsParser const &parser, Log &log, std::string header) {
151  bool top = false;
152  if (!header.empty()) {
153  log.custom(header);
154  header = "";
155  top = true;
156  }
157  for (const auto &pair : parser.all_warnings()) {
158  log << std::endl;
159  std::string location = "/" + pair.first.string();
160  log.custom(std::string("Warnings at location: ") + location);
161  for (const auto &msg : pair.second) {
162  log.indent() << msg << std::endl;
163  }
164  }
165  if (top) log << std::endl;
166 }
167 
168 void print_errors(KwargsParser const &parser, Log &log, std::string header) {
169  bool top = false;
170  if (!header.empty()) {
171  log.custom(header);
172  header = "";
173  top = true;
174  }
175  for (const auto &pair : parser.all_errors()) {
176  log << std::endl;
177  std::string location = "/" + pair.first.string();
178  log.custom(std::string("Errors at location: ") + location);
179  for (const auto &msg : pair.second) {
180  log.indent() << msg << std::endl;
181  }
182  }
183  if (top) log << std::endl;
184 }
185 
186 namespace make_report_impl {
187 
188 jsonParser &get_parent(jsonParser &report, KwargsParser const &parser) {
189  if (parser.parent_path().empty()) {
190  return report;
191  } else {
192  return report[parser.parent_path().string()];
193  }
194 }
195 
196 void add_to_report(jsonParser &report, KwargsParser const &parser) {
197  std::string sep = ".";
198  if (parser.name().empty()) {
199  sep = "";
200  }
201  jsonParser &parent = get_parent(report, parser);
202  if (parser.warning.size()) {
203  parent[parser.name() + sep + "WARNING"] = parser.warning;
204  parent[parser.name() + sep + "WARNING"].set_force_column();
205  }
206  if (parser.error.size()) {
207  parent[parser.name() + sep + "ERROR"] = parser.error;
208  parent[parser.name() + sep + "ERROR"].set_force_column();
209  }
210 }
211 } // namespace make_report_impl
212 
215  jsonParser report = parser.input;
216  make_report_impl::add_to_report(report, parser);
217  for (auto const &subparser_pair : parser) {
218  make_report_impl::add_to_report(report, *subparser_pair.second);
219  }
220  return report;
221 }
222 
223 } // namespace CASM
Definition: Log.hh:48
static std::string invalid_verbosity_msg(std::string s)
Definition: Log.cc:219
void custom(const std::string &what)
Definition: Log.hh:139
Log & indent()
Definition: Log.hh:289
static std::pair< bool, int > verbosity_level(std::string s)
Read verbosity level from a string.
Definition: Log.cc:231
iterator end()
Returns iterator to end of JSON object or JSON array.
Definition: jsonParser.cc:520
iterator find(const std::string &name)
Return iterator to JSON object value with 'name'.
Definition: jsonParser.cc:543
jsonParser::iterator find_at(const fs::path &path)
Return iterator to sub-object or element, or 'end' if not found.
Definition: jsonParser.cc:556
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: io_traits.hh:172
jsonParser & get_parent(jsonParser &report, KwargsParser const &parser)
Definition: InputParser.cc:188
void add_to_report(jsonParser &report, KwargsParser const &parser)
Definition: InputParser.cc:196
Main CASM namespace.
Definition: APICommand.hh:8
std::string type_name()
Definition: TypeInfo.hh:19
Log & log()
Definition: Log.hh:424
int parse_verbosity(KwargsParser &parser, int default_verbosity=10)
Definition: InputParser.cc:123
void print_errors(KwargsParser const &parser, Log &log, std::string header="Errors")
Formatted print error messages, including all subparsers.
Definition: InputParser.cc:168
void print_warnings(KwargsParser const &parser, Log &log, std::string header="Warnings")
Formatted print warning messages, including all subparsers.
Definition: InputParser.cc:150
jsonParser make_report(KwargsParser const &parser)
Return parser.input with error and warning messages added in place.
Definition: InputParser.cc:214
void parse(InputParser< ConfigEnumOptions > &parser, std::string method_name, PrimClex const &primclex, DataFormatterDictionary< Configuration > const &dict)
std::string name() const
Name of this->self, equivalent to this->path.filename().string()
Definition: InputParser.cc:42
bool valid() const
Return true if this and and all subparsers are valid.
Definition: InputParser.cc:56
KwargsParser(jsonParser const &_input, fs::path _path, bool _required)
Definition: InputParser.cc:20
std::map< fs::path, std::set< std::string > > all_errors() const
Return error messages from this and all subparsers.
Definition: InputParser.cc:77
Validator & insert(const Validator &other)
Definition: Validator.hh:19
map_type::value_type PairType
Definition: InputParser.hh:172
map_type::const_iterator begin() const
Begin iterator over subparsers.
Definition: InputParser.cc:48
bool required
If this->input.at(this->path) is required to exist.
Definition: InputParser.hh:84
void insert_warning(fs::path option, std::string message)
Insert a subparser at location option with a single warning message
Definition: InputParser.cc:104
fs::path relpath(const fs::path &val) const
Return this->path / val, ensuring the result is a relative path.
Definition: InputParser.hh:128
jsonParser const & input
Reference to the top of the JSON document being parsed.
Definition: InputParser.hh:68
std::map< fs::path, std::set< std::string > > all_warnings() const
Return warning messages from this and all subparsers.
Definition: InputParser.cc:61
jsonParser const & self
Definition: InputParser.hh:81
const jsonParser & parent() const
Definition: InputParser.cc:33
void insert_error(fs::path option, std::string message)
Insert a subparser at location option with a single error message
Definition: InputParser.cc:97
bool exists() const
Definition: InputParser.cc:44
map_type::const_iterator end() const
End iterator over subparsers.
Definition: InputParser.cc:52
fs::path parent_path() const
Definition: InputParser.cc:40
bool warn_unnecessary(const std::set< std::string > &expected)
Insert a warning if any unexpected JSON attributes are found in self.
Definition: InputParser.cc:111
bool valid() const
Definition: Validator.hh:25
std::set< std::string > error
Definition: Validator.hh:11
std::set< std::string > warning
Definition: Validator.hh:12