Refactor parsing of equation tags in a more functional way

Incidentally, makes tag names case-insensitive in “model_replace” and
“model_remove”, which is consistent with tag declarations.
master
Sébastien Villemot 2023-11-14 15:55:30 +01:00
parent ac35ef6101
commit 1ad7dd9672
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
7 changed files with 55 additions and 52 deletions

View File

@ -3425,12 +3425,12 @@ DynamicModel::fillEvalContext(eval_context_t &eval_context) const
}
void
DynamicModel::addStaticOnlyEquation(expr_t eq, optional<int> lineno, const map<string, string> &eq_tags)
DynamicModel::addStaticOnlyEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags)
{
auto beq = dynamic_cast<BinaryOpNode *>(eq);
assert(beq && beq->op_code == BinaryOpcode::equal);
static_only_equations_equation_tags.add(static_only_equations.size(), eq_tags);
static_only_equations_equation_tags.add(static_only_equations.size(), move(eq_tags));
static_only_equations.push_back(beq);
static_only_equations_lineno.push_back(move(lineno));
}
@ -3448,7 +3448,7 @@ DynamicModel::dynamicOnlyEquationsNbr() const
}
void
DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, const map<string, string> &eq_tags, const vector<string> &regimes_bind, const vector<string> &regimes_relax)
DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, const vector<string> &regimes_bind, const vector<string> &regimes_relax)
{
auto beq = dynamic_cast<BinaryOpNode *>(eq);
assert(beq && beq->op_code == BinaryOpcode::equal);
@ -3501,9 +3501,8 @@ DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, const map<strin
}
else
{
auto eq_tags_static = eq_tags;
eq_tags_static["static"] = "";
addStaticOnlyEquation(AddEqual(basic_term, Zero), lineno, eq_tags_static);
eq_tags["static"] = "";
addStaticOnlyEquation(AddEqual(basic_term, Zero), lineno, move(eq_tags));
}
}
}

View File

@ -417,7 +417,7 @@ public:
void replaceMyEquations(DynamicModel &dynamic_model) const;
//! Adds an equation marked as [static]
void addStaticOnlyEquation(expr_t eq, optional<int> lineno, const map<string, string> &eq_tags);
void addStaticOnlyEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags);
//! Returns number of static only equations
size_t staticOnlyEquationsNbr() const;
@ -430,7 +430,7 @@ public:
auxiliary parameters have already been added to the symbol table.
It also assumes that the bind and relax tags have been cleared from
eq_tags. */
void addOccbinEquation(expr_t eq, optional<int> lineno, const map<string, string> &eq_tags, const vector<string> &regimes_bind, const vector<string> &regimes_relax);
void addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, const vector<string> &regimes_bind, const vector<string> &regimes_relax);
//! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string &basename, bool write_equation_tags) const;

View File

@ -78,6 +78,16 @@ class ParsingDriver;
* current lexer object of the driver context. */
#undef yylex
#define yylex driver.lexer->lex
#include <cctype>
string
str_tolower(string s)
{
// Converting to unsigned char is needed, see https://en.cppreference.com/w/cpp/string/byte/tolower
transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); });
return s;
}
}
%token AIM_SOLVER ANALYTIC_DERIVATION ANALYTIC_DERIVATION_MODE AR POSTERIOR_SAMPLING_METHOD
@ -224,8 +234,9 @@ class ParsingDriver;
%type <vector<int>> vec_int_elem vec_int_1 vec_int vec_int_number
%type <PriorDistributions> prior_pdf prior_distribution
%type <pair<expr_t,expr_t>> calibration_range
%type <pair<string,string>> partition_elem subsamples_eq_opt integer_range_w_inf
%type <pair<string,string>> partition_elem subsamples_eq_opt integer_range_w_inf tag_pair
%type <vector<pair<string,string>>> partition partition_1 tag_pair_list_for_selection symbol_list_with_tex
%type <map<string, string>> tag_pair_list
%type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt
%type <vector<pair<int, int>>> period_list
%type <vector<expr_t>> matched_moments_list value_list
@ -982,23 +993,30 @@ equation_list : equation_list equation
;
equation : hand_side EQUAL hand_side ';'
{ $$ = driver.add_model_equal($1, $3); }
{ $$ = driver.add_model_equal($1, $3, {}); }
| hand_side ';'
{ $$ = driver.add_model_equal_with_zero_rhs($1); }
| '[' tags_list ']' hand_side EQUAL hand_side ';'
{ $$ = driver.add_model_equal($4, $6); }
| '[' tags_list ']' hand_side ';'
{ $$ = driver.add_model_equal_with_zero_rhs($4); }
{ $$ = driver.add_model_equal_with_zero_rhs($1, {}); }
| '[' tag_pair_list ']' hand_side EQUAL hand_side ';'
{ $$ = driver.add_model_equal($4, $6, $2); }
| '[' tag_pair_list ']' hand_side ';'
{ $$ = driver.add_model_equal_with_zero_rhs($4, $2); }
;
tags_list : tags_list COMMA tag_pair
| tag_pair
;
tag_pair_list : tag_pair_list COMMA tag_pair
{
$$ = $1;
auto [it, success] = $$.emplace($3);
if (!success)
driver.error("Tag '" + $3.first + "' cannot be used twice for the same equation");
}
| tag_pair
{ $$ = { $1 }; }
;
tag_pair : symbol EQUAL QUOTED_STRING
{ driver.add_equation_tags($1, $3); }
{ $$ = { str_tolower($1), $3 }; }
| symbol
{ driver.add_equation_tags($1, ""); }
{ $$ = { str_tolower($1), "" }; }
;
hand_side : '(' hand_side ')'
@ -1138,17 +1156,17 @@ model_options : MODEL_OPTIONS '(' model_options_list ')' ';'
tag_pair_list_for_selection : QUOTED_STRING
{ $$ = { { "name", $1 } }; }
| symbol EQUAL QUOTED_STRING
{ $$ = { { $1, $3 } }; }
| tag_pair
{ $$ = { $1 }; }
| tag_pair_list_for_selection COMMA QUOTED_STRING
{
$$ = $1;
$$.emplace_back("name", $3);
}
| tag_pair_list_for_selection COMMA symbol EQUAL QUOTED_STRING
| tag_pair_list_for_selection COMMA tag_pair
{
$$ = $1;
$$.emplace_back($3, $5);
$$.push_back($3);
}
;

View File

@ -1397,9 +1397,9 @@ ModelTree::findConstantEquationsWithoutMcpTag(map<VariableNode *, NumConstNode *
}
void
ModelTree::addEquation(expr_t eq, optional<int> lineno, const map<string, string> &eq_tags)
ModelTree::addEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags)
{
equation_tags.add(equations.size(), eq_tags);
equation_tags.add(equations.size(), move(eq_tags));
addEquation(eq, move(lineno));
}

View File

@ -622,7 +622,7 @@ public:
//! Declare a node as an equation of the model; also give its line number
void addEquation(expr_t eq, optional<int> lineno);
//! Declare a node as an equation of the model, also giving its tags
void addEquation(expr_t eq, optional<int> lineno, const map<string, string> &eq_tags);
void addEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags);
//! Declare a node as an auxiliary equation of the model, adding it at the end of the list of auxiliary equations
void addAuxEquation(expr_t eq);
//! Returns the number of equations in the model

View File

@ -307,19 +307,6 @@ ParsingDriver::predetermined_variables(const vector<string> &symbol_list)
}
}
void
ParsingDriver::add_equation_tags(string key, string value)
{
if (eq_tags.contains(key))
error("Tag '" + key + "' cannot be declared twice for the same equation");
eq_tags[key] = value;
transform(key.begin(), key.end(), key.begin(), ::tolower);
if (key == "endogenous")
declare_or_change_type(SymbolType::endogenous, value);
}
expr_t
ParsingDriver::add_non_negative_constant(const string &constant)
{
@ -2585,10 +2572,14 @@ ParsingDriver::extended_path()
}
expr_t
ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2)
ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_tags)
{
expr_t id = model_tree->AddEqual(arg1, arg2);
for (const auto &[key, value] : eq_tags)
if (key == "endogenous")
declare_or_change_type(SymbolType::endogenous, value);
if (eq_tags.contains("static"))
{
// If the equation is tagged [static]
@ -2625,19 +2616,18 @@ ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2)
}
eq_tags.erase("bind");
eq_tags.erase("relax");
dynamic_model->addOccbinEquation(id, location.begin.line, eq_tags, regimes_bind, regimes_relax);
dynamic_model->addOccbinEquation(id, location.begin.line, move(eq_tags), regimes_bind, regimes_relax);
}
else // General case
model_tree->addEquation(id, location.begin.line, eq_tags);
model_tree->addEquation(id, location.begin.line, move(eq_tags));
eq_tags.clear();
return id;
}
expr_t
ParsingDriver::add_model_equal_with_zero_rhs(expr_t arg)
ParsingDriver::add_model_equal_with_zero_rhs(expr_t arg, map<string, string> eq_tags)
{
return add_model_equal(arg, model_tree->Zero);
return add_model_equal(arg, model_tree->Zero, move(eq_tags));
}
void

View File

@ -239,8 +239,6 @@ private:
expr_t add_model_variable(int symb_id, int lag);
//! For parsing the graph_format option
vector<string> graph_formats;
//! Temporary storage for equation tags
map<string, string> eq_tags;
// Temporary storages for pac_target_info
string pac_target_info_name;
PacModelTable::target_component_t pac_target_info_component;
@ -390,8 +388,6 @@ public:
void declare_and_init_model_local_variable(const string &name, expr_t rhs);
//! Changes type of a symbol
void change_type(SymbolType new_type, const vector<string> &symbol_list);
//! Adds a list of tags for the current equation
void add_equation_tags(string key, string value);
//! Adds a non-negative constant to DataTree
expr_t add_non_negative_constant(const string &constant);
//! Adds a NaN constant to DataTree
@ -725,9 +721,9 @@ public:
//! Extended path
void extended_path();
//! Writes token "arg1=arg2" to model tree
expr_t add_model_equal(expr_t arg1, expr_t arg2);
expr_t add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_tags);
//! Writes token "arg=0" to model tree
expr_t add_model_equal_with_zero_rhs(expr_t arg);
expr_t add_model_equal_with_zero_rhs(expr_t arg, map<string, string> eq_tags);
//! Writes token "arg1+arg2" to model tree
expr_t add_plus(expr_t arg1, expr_t arg2);
//! Writes token "arg1-arg2" to model tree