diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index e76fc95093bf16a2d6f26a38037de92a8649f469..0fc43d76f76d50befc532eda2c78c1badf5dbbc8 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -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> ®imes_bind, const vector<string> ®imes_relax) +DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, const vector<string> ®imes_bind, const vector<string> ®imes_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)); } } } diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index c35718213424df79fc2f9092ceff217504b98765..1dc73424036534bf65d38ac3a7e461373da7028d 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -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> ®imes_bind, const vector<string> ®imes_relax); + void addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, const vector<string> ®imes_bind, const vector<string> ®imes_relax); //! Writes LaTeX file with the equations of the dynamic model void writeLatexFile(const string &basename, bool write_equation_tags) const; diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 40d636bfce1f7f28d251f1612fe7d852069400d5..f3ca426557a2fc70f11332a67bdac607e5f0aaa8 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -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); } ; diff --git a/src/ModelTree.cc b/src/ModelTree.cc index b7a510fd10260e7bd997ca629c84f97e8025a852..d02438a8a9479f2f718e81ed05316e158bdc713e 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -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)); } diff --git a/src/ModelTree.hh b/src/ModelTree.hh index 6169ba74c900a11a2691d2808574d22430a20cb1..88a2b11491b4e8dbf2355c8747c4945cd341349d 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -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 diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index 18abd332e2c3324dbf37a78cceea36b5e0d35b25..6a61a54d86f20f48d79e5b23cc7fc42a34deb98b 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -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 diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index f9a47ac18153df3218e83f304721ac76df8c2f3a..f75b39b6c82fee0db5b6830c37d22ba9fbfd6488 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -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