19 #include "libmesh/parallel.h" 20 #include "libmesh/fparser.hh" 31 std::string func_text;
34 auto n_errs =
exp.errors.size();
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);
144 const std::optional<std::vector<std::string>> & input_text )
146 _input_filenames(input_filenames),
147 _input_text(input_text ? *input_text :
std::vector<
std::string>()),
152 mooseError(
"Parser: Input text not the same length as input filenames");
156 const std::optional<std::string> & input_text )
158 input_text ? std::optional<std::vector<std::string>>({*input_text})
159 : std::optional<std::vector<std::string>>())
166 const auto it =
_have.try_emplace(fullpath, n);
169 const std::string type = n->type() == hit::NodeType::Field ?
"parameter" :
"section";
170 const std::string error = type +
" '" + fullpath +
"' supplied multiple times";
173 const auto existing = it.first->second;
174 if (std::find_if(
errors.begin(),
176 [&existing](
const auto &
err)
177 {
return err.node == existing; }) ==
errors.end())
178 errors.emplace_back(error, existing);
180 errors.emplace_back(error, n);
186 const std::string & ,
189 if (n->type() == hit::NodeType::Field)
195 const std::string & ,
198 const auto it =
_map.find(fullpath);
199 if (it !=
_map.end())
203 "' overrides the same parameter in ",
204 it->second->filename(),
206 it->second->line()));
211 const std::string & ,
214 auto actives = section->find(
"active");
215 auto inactives = section->find(
"inactive");
217 if (actives && inactives && actives->type() == hit::NodeType::Field &&
218 inactives->type() == hit::NodeType::Field && actives->parent() == inactives->parent())
221 "'active' and 'inactive' parameters both provided in section '" + fullpath +
"'", section);
226 if (actives && actives->type() == hit::NodeType::Field && actives->parent() == section)
228 auto vars = section->param<std::vector<std::string>>(
"active");
229 std::string msg =
"";
230 for (
auto & var :
vars)
232 if (!section->find(var))
237 msg = msg.substr(0, msg.size() - 2);
238 errors.emplace_back(
"variables listed as active (" + msg +
") in section '" +
239 section->fullpath() +
"' not found in input",
244 if (inactives && inactives->type() == hit::NodeType::Field && inactives->parent() == section)
246 auto vars = section->param<std::vector<std::string>>(
"inactive");
247 std::string msg =
"";
248 for (
auto & var :
vars)
250 if (!section->find(var))
255 msg = msg.substr(0, msg.size() - 2);
256 errors.emplace_back(
"variables listed as inactive (" + msg +
") in section '" +
257 section->fullpath() +
"' not found in input",
267 walk(
const std::string & ,
const std::string & , hit::Node * n)
override 269 if (n && n->type() == hit::NodeType::Field && n->fullpath() ==
"Application/type")
289 mooseError(
"Parser::getLastInputFileName(): No inputs are set");
307 const std::string use_rel_paths_str =
308 std::getenv(
"MOOSE_RELATIVE_FILEPATHS") ? std::getenv(
"MOOSE_RELATIVE_FILEPATHS") :
"false";
309 const auto use_real_paths = use_rel_paths_str ==
"0" || use_rel_paths_str ==
"false";
310 std::vector<std::string> filenames;
316 for (
const auto & filename : filenames)
319 std::ifstream f(filename);
321 std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()));
330 std::vector<hit::ErrorMessage> dw_errors;
334 const auto & filename = filenames[i];
341 std::vector<hit::ErrorMessage> syntax_errors;
342 std::unique_ptr<hit::Node> root(hit::parse(filename, input, &syntax_errors));
345 root->
walk(&dw, hit::NodeType::Field);
349 _root = std::move(root);
352 root->walk(&opw, hit::NodeType::Field);
356 if (!syntax_errors.empty())
359 getRoot().walk(&cpw, hit::NodeType::Field);
361 catch (hit::Error &
err)
374 _root.reset(hit::parse(
"EMPTY",
""));
378 getRoot().walk(&bw, hit::NodeType::Section);
385 getRoot().walk(&fw, hit::NodeType::Field);
391 if (dw_errors.size())
395 const auto joined_params =
399 _cli_root.reset(hit::parse(
"CLI_ARGS", joined_params));
402 catch (hit::Error &
err)
407 std::vector<hit::ErrorMessage> errors;
415 hit::ReplaceEvaler repl;
418 hit::BraceExpander exw;
419 exw.registerEvaler(
"raw", raw);
420 exw.registerEvaler(
"env", env);
421 exw.registerEvaler(
"fparse", fparse_ev);
422 exw.registerEvaler(
"replace", repl);
423 exw.registerEvaler(
"units", units_ev);
425 for (
auto & var : exw.used)
433 getRoot().walk(&dw, hit::NodeType::Field);
440 getRoot().walk(&bw, hit::NodeType::Section);
452 mooseError(
"Parser::getRoot(): root is not set");
460 mooseError(
"Parser::getCommandLineRoot(): command line root is not set");
467 return const_cast<hit::Node &
>(std::as_const(*this).getCommandLineRoot());
472 const std::vector<hit::ErrorMessage> & from)
474 to.insert(to.end(), from.begin(), from.end());
486 std::vector<std::string> values;
487 for (
const auto & em : error_messages)
488 values.push_back(em.prefixed_message);
510 for (
auto & em : messages)
513 em = hit::ErrorMessage(em.message,
"CLI_ARGS");
const std::vector< std::string > _input_filenames
The input file names.
void setAppType(const std::string &app_type)
const hit::Node * queryCommandLineRoot() const
void parseError(std::vector< hit::ErrorMessage > messages) const
Helper for throwing an error with the given messages.
void parse()
Parses the inputs.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
void setCommandLineParams(const std::vector< std::string > ¶ms)
Sets the HIT parameters from the command line.
virtual std::string eval(hit::Field *n, const std::list< std::string > &args, hit::BraceExpander &exp)
void walk(const std::string &, const std::string &, hit::Node *n) override
const std::string & getLastInputFileName() const
void mooseInfoRepeated(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
const std::vector< std::string > & getInputFileNames() const
std::vector< std::string > warnings
std::string realpath(const std::string &path)
Wrapper around PetscGetRealPath, which is a cross-platform replacement for realpath.
const hit::Node * queryRoot() const
std::vector< hit::ErrorMessage > errors
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.
virtual void walk(const std::string &fullpath, const std::string &, hit::Node *n) override
void mooseInfo(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
std::unique_ptr< hit::Node > _cli_root
The root node for command line hit arguments.
static std::string joinErrorMessages(const std::vector< hit::ErrorMessage > &error_messages)
Helper for combining error messages into a single, newline separated message.
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.
std::map< std::string, hit::Node * > _have
constexpr auto merge(std::index_sequence< first... >, std::index_sequence< second... >)
Merge two index sequences into one.
bool checkFileReadable(const std::string &filename, bool check_line_endings=false, bool throw_on_unreadable=true, bool check_for_git_lfs_pointer=true)
Checks to see if a file is readable (exists and permissions)
bool _throw_on_error
Whether or not to throw on error.
std::vector< std::string > _input_text
The input text (may be filled during parse())
std::string stringify(const T &t)
conversion to string
std::map< std::string, hit::Node * > ParamMap
std::set< std::string > _extracted_vars
Variables that have been extracted during brace expansion.
Physical unit management class with runtime unit string parsing, unit checking, unit conversion...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::optional< std::string > & getApp()
virtual void walk(const std::string &fullpath, const std::string &, hit::Node *n) override
std::unique_ptr< hit::Node > _root
The root node, which owns the whole tree.
void walk(const std::string &fullpath, const std::string &, hit::Node *n) override
const hit::Node & getCommandLineRoot() const
std::optional< std::string > _app_type
const std::vector< std::string > & getInputText() const
std::vector< hit::ErrorMessage > errors
std::optional< std::vector< std::string > > _command_line_params
The command line HIT parameters (if any)
bool _throw_on_error
Variable to turn on exceptions during mooseError(), should only be used within MOOSE unit tests or wh...
std::string stringJoin(const std::vector< std::string > &values, const std::string &separator=" ")
Concatenates value into a single string separated by separator.
virtual std::string eval(hit::Field *n, const std::list< std::string > &args, hit::BraceExpander &exp)
auto index_range(const T &sizable)
Class for parsing input files.
virtual void walk(const std::string &, const std::string &, hit::Node *section) override
const CompileParamWalker::ParamMap & _map