19#include "libmesh/parallel.h"
20#include "libmesh/fparser.hh"
31 std::string func_text;
34 auto n_errs = exp.errors.size();
38 fp.AddConstant(
"e", std::exp(Real(1)));
39 std::vector<std::string> var_names;
40 auto ret = fp.ParseAndDeduceVariables(func_text, var_names);
43 exp.errors.emplace_back(
44 "fparse error: " + std::string(fp.ErrorMsg()) +
" in '" + n->fullpath() +
"'", n);
48 std::vector<double> var_vals;
49 for (
auto & var : var_names)
53 while ((curr = curr->parent()))
55 auto src = curr->find(var);
56 if (src && src != n && src->type() == hit::NodeType::Field)
58 exp.used.push_back(hit::pathJoin({curr->fullpath(), var}));
59 var_vals.push_back(curr->param<
double>(var));
65 exp.errors.emplace_back(
"no variable '" + var +
66 "' found for use in function parser expression in '" +
71 if (exp.errors.size() != n_errs)
75 ss << std::setprecision(17) << fp.Eval(var_vals.data());
78 n->setVal(n->val(), hit::Field::Kind::Float);
84 const std::list<std::string> & args,
85 hit::BraceExpander & exp)
87 std::vector<std::string> argv;
88 argv.insert(argv.begin(), args.begin(), args.end());
93 n->setVal(n->val(), hit::Field::Kind::Float);
98 if (argv.size() != 4 || (argv.size() >= 3 && argv[2] !=
"->"))
100 exp.errors.emplace_back(
"units error: Expected 4 arguments ${units number from_unit -> "
101 "to_unit} or 2 arguments ${units number unit} in '" +
110 if (!from_unit.conformsTo(to_unit))
112 std::ostringstream err;
113 err <<
"units error: " << argv[1] <<
" (" << from_unit <<
") does not convert to " << argv[3]
114 <<
" (" << to_unit <<
") in '" << n->fullpath() <<
"'";
115 exp.errors.emplace_back(err.str(), n);
120 Real num = MooseUtils::convert<Real>(argv[0]);
123 std::stringstream ss;
124 ss << std::setprecision(17) << to_unit.convert(num, from_unit);
139 n->setVal(n->val(), hit::Field::Kind::Float);
146 std::vector<std::string> argv;
147 argv.insert(argv.begin(), args.begin(), args.end());
149 if (argv.size() != 3)
151 exp.errors.emplace_back(
152 "enumerate error: Expected 3 arguments ${enumerate prefix first_index last_index} in '" +
158 const auto & prefix = argv[0];
159 std::array<int, 2> index;
160 for (
const auto i : make_range(2))
162 const auto & arg = argv[i + 1];
163 if (arg.empty() || arg.find_first_not_of(
"0123456789") != std::string::npos)
165 exp.errors.emplace_back(
"enumerate error: index '" + arg +
166 "' is not a non-negative integer in '" + n->fullpath() +
"'",
170 index[i] = MooseUtils::convert<int>(arg);
173 if (index[1] < index[0])
175 exp.errors.emplace_back(
"enumerate error: last index " + argv[2] +
176 " is smaller than first index " + argv[1] +
" in '" +
182 std::vector<std::string> names;
183 for (
const auto i : make_range(index[0], index[1] + 1))
184 names.push_back(prefix + std::to_string(i));
192 std::vector<std::string> argv;
193 argv.insert(argv.begin(), args.begin(), args.end());
195 if (argv.size() != 2)
197 exp.errors.emplace_back(
198 "repeat error: Expected 2 arguments ${repeat name count} in '" + n->fullpath() +
"'", n);
202 const auto & count_arg = argv[1];
203 if (count_arg.empty() || count_arg.find_first_not_of(
"0123456789") != std::string::npos)
205 exp.errors.emplace_back(
"repeat error: count '" + count_arg +
206 "' is not a non-negative integer in '" + n->fullpath() +
"'",
211 const std::vector<std::string>
values(MooseUtils::convert<int>(count_arg), argv[0]);
216 const std::optional<std::vector<std::string>> & input_text )
218 _input_filenames(input_filenames),
219 _input_text(input_text ? *input_text :
std::vector<
std::string>()),
221 _throw_on_error(false)
224 mooseError(
"Parser: Input text not the same length as input filenames");
228 const std::optional<std::string> & input_text )
230 input_text ? std::optional<std::vector<std::string>>({*input_text})
231 :
std::optional<
std::vector<
std::string>>())
238 const auto it =
_have.try_emplace(fullpath, n);
241 const std::string type = n->type() == hit::NodeType::Field ?
"parameter" :
"section";
242 const std::string error = type +
" '" + fullpath +
"' supplied multiple times";
245 const auto existing = it.first->second;
246 if (std::find_if(
errors.begin(),
248 [&existing](
const auto & err)
249 { return err.node == existing; }) ==
errors.end())
250 errors.emplace_back(error, existing);
252 errors.emplace_back(error, n);
258 const std::string & ,
261 if (n->type() == hit::NodeType::Field)
267 const std::string & ,
270 const auto it =
_map.find(fullpath);
271 if (it !=
_map.end())
275 "' overrides the same parameter in ",
276 it->second->filename(),
278 it->second->line()));
282BadActiveWalker ::walk(
const std::string & fullpath,
283 const std::string & ,
286 auto actives = section->find(
"active");
287 auto inactives = section->find(
"inactive");
289 if (actives && inactives && actives->type() == hit::NodeType::Field &&
290 inactives->type() == hit::NodeType::Field && actives->parent() == inactives->parent())
293 "'active' and 'inactive' parameters both provided in section '" + fullpath +
"'", section);
298 if (actives && actives->type() == hit::NodeType::Field && actives->parent() == section)
300 auto vars = section->param<std::vector<std::string>>(
"active");
301 std::string msg =
"";
302 for (
auto & var :
vars)
304 if (!section->find(var))
309 msg = msg.substr(0, msg.size() - 2);
310 errors.emplace_back(
"variables listed as active (" + msg +
") in section '" +
311 section->fullpath() +
"' not found in input",
316 if (inactives && inactives->type() == hit::NodeType::Field && inactives->parent() == section)
318 auto vars = section->param<std::vector<std::string>>(
"inactive");
319 std::string msg =
"";
320 for (
auto & var :
vars)
322 if (!section->find(var))
327 msg = msg.substr(0, msg.size() - 2);
328 errors.emplace_back(
"variables listed as inactive (" + msg +
") in section '" +
329 section->fullpath() +
"' not found in input",
339 walk(
const std::string & ,
const std::string & , hit::Node * n)
override
341 if (n && n->type() == hit::NodeType::Field && n->fullpath() ==
"Application/type")
361 mooseError(
"Parser::getLastInputFileName(): No inputs are set");
379 const std::string use_rel_paths_str =
380 std::getenv(
"MOOSE_RELATIVE_FILEPATHS") ? std::getenv(
"MOOSE_RELATIVE_FILEPATHS") :
"false";
381 const auto use_real_paths = use_rel_paths_str ==
"0" || use_rel_paths_str ==
"false";
382 std::vector<std::string> filenames;
388 for (
const auto & filename : filenames)
391 std::ifstream f(filename);
393 std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()));
402 std::vector<hit::ErrorMessage> dw_errors;
406 const auto & filename = filenames[i];
413 std::vector<hit::ErrorMessage> syntax_errors;
414 std::unique_ptr<hit::Node> root(hit::parse(filename, input, &syntax_errors));
417 root->
walk(&dw, hit::NodeType::Field);
421 _root = std::move(root);
424 root->walk(&opw, hit::NodeType::Field);
425 hit::merge(root.get(), &
getRoot());
428 if (!syntax_errors.empty())
431 getRoot().walk(&cpw, hit::NodeType::Field);
433 catch (hit::Error & err)
446 _root.reset(hit::parse(
"EMPTY",
""));
463 if (dw_errors.size())
467 const auto joined_params =
471 _cli_root.reset(hit::parse(
"CLI_ARGS", joined_params));
474 catch (hit::Error & err)
479 std::vector<hit::ErrorMessage> errors;
487 hit::ReplaceEvaler repl;
492 hit::BraceExpander exw;
493 exw.registerEvaler(
"raw", raw);
494 exw.registerEvaler(
"env", env);
495 exw.registerEvaler(
"fparse", fparse_ev);
496 exw.registerEvaler(
"replace", repl);
497 exw.registerEvaler(
"units", units_ev);
498 exw.registerEvaler(
"enumerate", enumerate_ev);
499 exw.registerEvaler(
"repeat", repeat_ev);
501 for (
auto & var : exw.used)
528 mooseError(
"Parser::getRoot(): root is not set");
536 mooseError(
"Parser::getCommandLineRoot(): command line root is not set");
543 return const_cast<hit::Node &
>(std::as_const(*this).getCommandLineRoot());
548 const std::vector<hit::ErrorMessage> & from)
550 to.insert(to.end(), from.begin(), from.end());
562 std::vector<std::string>
values;
563 for (
const auto & em : error_messages)
564 values.push_back(em.prefixed_message);
586 for (
auto & em : messages)
589 em = hit::ErrorMessage(em.message,
"CLI_ARGS");
void mooseInfoRepeated(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
void mooseInfo(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
std::array< Real, 2 > values
std::vector< hit::ErrorMessage > errors
virtual void walk(const std::string &, const std::string &, hit::Node *section) override
std::map< std::string, hit::Node * > ParamMap
virtual void walk(const std::string &fullpath, const std::string &, hit::Node *n) override
std::map< std::string, hit::Node * > _have
virtual void walk(const std::string &fullpath, const std::string &, hit::Node *n) override
std::vector< hit::ErrorMessage > errors
virtual std::string eval(hit::Field *n, const std::list< std::string > &args, hit::BraceExpander &exp)
std::optional< std::string > _app_type
const std::optional< std::string > & getApp()
void walk(const std::string &, const std::string &, hit::Node *n) override
virtual std::string eval(hit::Field *n, const std::list< std::string > &args, hit::BraceExpander &exp)
Physical unit management class with runtime unit string parsing, unit checking, unit conversion,...
const CompileParamWalker::ParamMap & _map
std::vector< std::string > warnings
void walk(const std::string &fullpath, const std::string &, hit::Node *n) override
Class for parsing input files.
std::set< std::string > _extracted_vars
Variables that have been extracted during brace expansion.
static void appendErrorMessages(std::vector< hit::ErrorMessage > &to, const std::vector< hit::ErrorMessage > &from)
Helper for accumulating errors from a walker into an accumulation of errors.
const std::string & getLastInputFileName() const
void setAppType(const std::string &app_type)
const hit::Node & getCommandLineRoot() const
const hit::Node * queryRoot() const
void setCommandLineParams(const std::vector< std::string > ¶ms)
Sets the HIT parameters from the command line.
const std::vector< std::string > & getInputText() const
std::vector< std::string > _input_text
The input text (may be filled during parse())
const std::vector< std::string > & getInputFileNames() const
const std::vector< std::string > _input_filenames
The input file names.
std::optional< std::vector< std::string > > _command_line_params
The command line HIT parameters (if any)
std::unique_ptr< hit::Node > _cli_root
The root node for command line hit arguments.
std::unique_ptr< hit::Node > _root
The root node, which owns the whole tree.
void parseError(std::vector< hit::ErrorMessage > messages) const
Helper for throwing an error with the given messages.
bool _throw_on_error
Whether or not to throw on error.
const hit::Node * queryCommandLineRoot() const
void parse()
Parses the inputs.
Parser(const std::vector< std::string > &input_filenames, const std::optional< std::vector< std::string > > &input_text={})
Constructor given a list of input files, given in input_filenames.
static std::string joinErrorMessages(const std::vector< hit::ErrorMessage > &error_messages)
Helper for combining error messages into a single, newline separated message.
virtual std::string eval(hit::Field *n, const std::list< std::string > &args, hit::BraceExpander &exp)
virtual std::string eval(hit::Field *n, const std::list< std::string > &args, hit::BraceExpander &exp)
std::string realpath(const std::string &path)
std::string stringJoin(const std::vector< std::string > &values, const std::string &separator=" ")
Concatenates value into a single string separated by separator.
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
std::string stringify(const T &t)
conversion to string