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> &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));
         }
     }
 }
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> &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;
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