From 32c3910e185b67980c13b38d0b0dbf81fbbfc203 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Thu, 19 Dec 2019 14:48:55 +0100
Subject: [PATCH] allow symbol list to accept auxiliary variables

dynare#1355
---
 src/ComputingTasks.cc | 239 +++++++++++++++++++++++++++++++++++-------
 src/ComputingTasks.hh |  12 ++-
 src/DynareBison.yy    |  11 +-
 src/ModFile.cc        |   5 -
 src/ParsingDriver.cc  |  15 +--
 src/ParsingDriver.hh  |   4 -
 src/SymbolList.cc     |  33 ++++++
 src/SymbolList.hh     |  12 +++
 8 files changed, 264 insertions(+), 67 deletions(-)

diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index 35e5cb09..ec534f81 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -643,6 +643,16 @@ StochSimulStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli
     }
 
   symbol_list.removeDuplicates("stoch_simul", warnings);
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: stoch_simul: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -684,6 +694,20 @@ ForecastStatement::ForecastStatement(SymbolList symbol_list_arg,
 {
 }
 
+void
+ForecastStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
+{
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: forecast: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 void
 ForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
@@ -917,10 +941,10 @@ RamseyConstraintsStatement::writeJsonOutput(ostream &output) const
 }
 
 RamseyPolicyStatement::RamseyPolicyStatement(const SymbolTable &symbol_table_arg,
-                                             vector<string> ramsey_policy_list_arg,
+                                             SymbolList symbol_list_arg,
                                              OptionsList options_list_arg) :
   symbol_table{symbol_table_arg},
-  ramsey_policy_list{move(ramsey_policy_list_arg)},
+  symbol_list{move(symbol_list_arg)},
   options_list{move(options_list_arg)}
 {
 }
@@ -964,23 +988,15 @@ RamseyPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConso
   if (auto it = options_list.symbol_list_options.find("instruments");
       it != options_list.symbol_list_options.end())
     mod_file_struct.instruments = it->second;
-}
 
-void
-RamseyPolicyStatement::checkRamseyPolicyList()
-{
-  for (const auto & it : ramsey_policy_list)
+  try
     {
-      if (!symbol_table.exists(it))
-        {
-          cerr << "ERROR: ramsey_policy: " << it << " was not declared." << endl;
-          exit(EXIT_FAILURE);
-        }
-      if (symbol_table.getType(it) != SymbolType::endogenous)
-        {
-          cerr << "ERROR: ramsey_policy: " << it << " is not endogenous." << endl;
-          exit(EXIT_FAILURE);
-        }
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: ramsey_policy: " << e.message << endl;
+      exit(EXIT_FAILURE);
     }
 }
 
@@ -995,16 +1011,8 @@ RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool
     output << "options_.k_order_solver = true;" << endl;
 
   options_list.writeOutput(output);
-  output << "var_list_ = {";
-  for (auto it = ramsey_policy_list.begin();
-       it != ramsey_policy_list.end(); ++it)
-    {
-      if (it != ramsey_policy_list.begin())
-        output << ";";
-      output << "'" << *it << "'";
-    }
-  output << "};" << endl
-         << "ramsey_policy(var_list_);" << endl;
+  symbol_list.writeOutput("var_list_", output);
+  output << "ramsey_policy(var_list_);" << endl;
 }
 
 void
@@ -1016,16 +1024,12 @@ RamseyPolicyStatement::writeJsonOutput(ostream &output) const
       output << ", ";
       options_list.writeJsonOutput(output);
     }
-  output << R"(, "ramsey_policy_list": [)";
-  for (auto it = ramsey_policy_list.begin();
-       it != ramsey_policy_list.end(); ++it)
+  if (!symbol_list.empty())
     {
-      if (it != ramsey_policy_list.begin())
-        output << ",";
-      output << R"(")" << *it << R"(")";
+      output << ", ";
+      symbol_list.writeJsonOutput(output);
     }
-  output << "]"
-         << "}";
+  output << "}";
 }
 
 void
@@ -1088,6 +1092,16 @@ DiscretionaryPolicyStatement::checkPass(ModFileStructure &mod_file_struct, Warni
   if (auto it = options_list.symbol_list_options.find("instruments");
       it != options_list.symbol_list_options.end())
     mod_file_struct.instruments = it->second;
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: discretionary_policy: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -1199,6 +1213,16 @@ EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli
       cerr << "ERROR: The mode_file option of the estimation statement is incompatible with the use_calibration option of the estimated_params_init block." << endl;
       exit(EXIT_FAILURE);
     }
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: estimation: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -1969,6 +1993,16 @@ OsrStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation
       (it != options_list.num_options.end() && it->second == "true")
       || mod_file_struct.order_option >= 3)
     mod_file_struct.k_order_solver = true;
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: osr: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -2083,6 +2117,20 @@ DynaSaveStatement::DynaSaveStatement(SymbolList symbol_list_arg,
 {
 }
 
+void
+DynaSaveStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
+{
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: dynasave: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 void
 DynaSaveStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
@@ -2111,6 +2159,20 @@ DynaTypeStatement::DynaTypeStatement(SymbolList symbol_list_arg,
 {
 }
 
+void
+DynaTypeStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
+{
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: dynatype: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 void
 DynaTypeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
@@ -2498,6 +2560,16 @@ MSSBVARIrfStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli
            << "filtered_probabilities to ms_irf" << endl;
       exit(EXIT_FAILURE);
     }
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: ms_irf: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -2765,6 +2837,16 @@ ShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, Warnin
   if (auto it = options_list.num_options.find("shock_decomp.with_epilogue");
       it != options_list.num_options.end() && it->second == "true")
     mod_file_struct.with_epilogue_option = true;
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: shock_decomposition: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -2805,6 +2887,16 @@ RealtimeShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct
   if (auto it = options_list.num_options.find("shock_decomp.with_epilogue");
       it != options_list.num_options.end() && it->second == "true")
     mod_file_struct.with_epilogue_option = true;
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: realtime_shock_decomposition: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -2878,6 +2970,16 @@ InitialConditionDecompositionStatement::checkPass(ModFileStructure &mod_file_str
   if (auto it = options_list.num_options.find("initial_condition_decomp.with_epilogue");
       it != options_list.num_options.end() && it->second == "true")
     mod_file_struct.with_epilogue_option = true;
+
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: initial_condition_decomposition: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -2911,6 +3013,21 @@ SqueezeShockDecompositionStatement::SqueezeShockDecompositionStatement(SymbolLis
 {
 }
 
+void
+SqueezeShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct,
+                                              WarningConsolidation &warnings)
+{
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: squeeze_shock_decomposition: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 void
 SqueezeShockDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
@@ -2975,6 +3092,21 @@ PlotConditionalForecastStatement::PlotConditionalForecastStatement(int periods_a
 {
 }
 
+void
+PlotConditionalForecastStatement::checkPass(ModFileStructure &mod_file_struct,
+                                            WarningConsolidation &warnings)
+{
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: plot_conditional_forecast: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 void
 PlotConditionalForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
@@ -4538,6 +4670,15 @@ void
 CalibSmootherStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
 {
   mod_file_struct.calib_smoother_present = true;
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: calib_smoother: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
 }
 
 void
@@ -4658,6 +4799,20 @@ GMMEstimationStatement::GMMEstimationStatement(SymbolList symbol_list_arg,
 {
 }
 
+void
+GMMEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
+{
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: gmm_estimation: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 void
 GMMEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
@@ -4691,6 +4846,20 @@ SMMEstimationStatement::SMMEstimationStatement(SymbolList symbol_list_arg,
 {
 }
 
+void
+SMMEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
+{
+  try
+    {
+      symbol_list.checkPass(warnings);
+    }
+  catch (SymbolList::SymbolListException &e)
+    {
+      cerr << "ERROR: smm_estimation: " << e.message << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 void
 SMMEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh
index 82c77210..47f647a1 100644
--- a/src/ComputingTasks.hh
+++ b/src/ComputingTasks.hh
@@ -106,7 +106,6 @@ public:
   DetCondForecast(SymbolList symbol_list_arg,
                   OptionsList options_list_arg,
                   const bool linear_decompositiontion_arg);
-  //virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
 };
 
@@ -203,6 +202,7 @@ private:
 public:
   ForecastStatement(SymbolList symbol_list_arg,
                     OptionsList options_list_arg);
+  void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
 };
@@ -242,11 +242,11 @@ class RamseyPolicyStatement : public Statement
 {
 private:
   const SymbolTable &symbol_table;
-  const vector<string> ramsey_policy_list;
+  const SymbolList symbol_list;
   const OptionsList options_list;
 public:
   RamseyPolicyStatement(const SymbolTable &symbol_table_arg,
-                        vector<string> ramsey_policy_list_arg,
+                        SymbolList symbol_list_arg,
                         OptionsList options_list_arg);
   void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void checkRamseyPolicyList();
@@ -410,6 +410,7 @@ private:
 public:
   DynaTypeStatement(SymbolList symbol_list_arg,
                     string filename_arg);
+  void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
 };
@@ -422,6 +423,7 @@ private:
 public:
   DynaSaveStatement(SymbolList symbol_list_arg,
                     string filename_arg);
+  void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
 };
@@ -769,6 +771,7 @@ private:
   const SymbolList symbol_list;
 public:
   SqueezeShockDecompositionStatement(SymbolList symbol_list_arg);
+  void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
 };
@@ -792,6 +795,7 @@ private:
   const SymbolList symbol_list;
 public:
   PlotConditionalForecastStatement(int periods_arg, SymbolList symbol_list_arg);
+  void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
 };
@@ -1145,6 +1149,7 @@ private:
   const OptionsList options_list;
 public:
   GMMEstimationStatement(SymbolList symbol_list_arg, OptionsList options_list_arg);
+  void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
 };
@@ -1156,6 +1161,7 @@ private:
   const OptionsList options_list;
 public:
   SMMEstimationStatement(SymbolList symbol_list_arg, OptionsList options_list_arg);
+  void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
 };
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 047f81ac..971b9e98 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -2322,19 +2322,12 @@ ramsey_policy : RAMSEY_POLICY ';'
                 { driver.ramsey_policy(); }
               | RAMSEY_POLICY '(' ramsey_policy_options_list ')' ';'
                 { driver.ramsey_policy(); }
-              | RAMSEY_POLICY ramsey_policy_list ';'
+              | RAMSEY_POLICY symbol_list ';'
                 { driver.ramsey_policy(); }
-              | RAMSEY_POLICY '(' ramsey_policy_options_list ')' ramsey_policy_list ';'
+              | RAMSEY_POLICY '(' ramsey_policy_options_list ')' symbol_list ';'
                 { driver.ramsey_policy(); }
               ;
 
-ramsey_policy_list : ramsey_policy_list ramsey_policy_element
-                   | ramsey_policy_element
-                   ;
-
-ramsey_policy_element : symbol { driver.add_to_ramsey_policy_list($1); }
-                      ;
-
 ramsey_constraints : RAMSEY_CONSTRAINTS ';' ramsey_constraints_list END ';'
                      { driver.add_ramsey_constraints_statement(); }
 		   ;
diff --git a/src/ModFile.cc b/src/ModFile.cc
index 2e26a507..06cb68fe 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -690,11 +690,6 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
       exit(EXIT_FAILURE);
     }
 
-  if (mod_file_struct.ramsey_policy_present)
-    for (auto & statement : statements)
-      if (auto rps = dynamic_cast<RamseyPolicyStatement *>(statement.get()); rps)
-        rps->checkRamseyPolicyList();
-
   if (mod_file_struct.identification_present && symbol_table.exo_det_nbr() > 0)
     {
       cerr << "ERROR: identification is incompatible with deterministic exogenous variables" << endl;
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index bf55ac51..e80c146d 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -91,7 +91,7 @@ ParsingDriver::parse(istream &in, bool debug)
 {
   mod_file = make_unique<ModFile>(warnings);
 
-  symbol_list.clear();
+  symbol_list.setSymbolTable(mod_file->symbol_table);
 
   reset_data_tree();
   estim_params.init(*data_tree);
@@ -1464,8 +1464,6 @@ ParsingDriver::linear()
 void
 ParsingDriver::add_in_symbol_list(const string &tmp_var)
 {
-  if (tmp_var != ":")
-    check_symbol_existence(tmp_var);
   symbol_list.addSymbol(tmp_var);
 }
 
@@ -2208,18 +2206,13 @@ ParsingDriver::ramsey_policy()
   else if (planner_discount)
     error("ramsey_policy: the 'planner_discount' option cannot be used when the 'optimal_policy_discount_factor' parameter is explicitly declared.");
 
-  mod_file->addStatement(make_unique<RamseyPolicyStatement>(mod_file->symbol_table, ramsey_policy_list, options_list));
+  mod_file->addStatement(make_unique<RamseyPolicyStatement>(mod_file->symbol_table,
+                                                            symbol_list, options_list));
   options_list.clear();
-  ramsey_policy_list.clear();
+  symbol_list.clear();
   planner_discount = nullptr;
 }
 
-void
-ParsingDriver::add_to_ramsey_policy_list(string name)
-{
-  ramsey_policy_list.push_back(move(name));
-}
-
 void
 ParsingDriver::evaluate_planner_objective()
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index f711e9dd..a8f1d72f 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -237,8 +237,6 @@ private:
   vector<ShockGroupsStatement::Group> shock_groups;
   //! Temporary storage for init2shocks
   vector<pair<int, int>> init2shocks;
-  //! Temporary storage for ramsey policy. Workaround for issue #1355
-  vector<string> ramsey_policy_list;
   /* Temporary storage for planner_discount and planner_discount_latex_name
      options of ramsey_model and ramsey_policy */
   expr_t planner_discount{nullptr};
@@ -888,8 +886,6 @@ public:
   void add_init2shocks(const string &endo_name, const string &exo_name);
   //! End init2shocks declaration
   void end_init2shocks(const string &name);
-  //! Add an element to the ramsey policy list
-  void add_to_ramsey_policy_list(string name);
   void smoother2histval();
   void histval_file(const string &filename);
   void perfect_foresight_setup();
diff --git a/src/SymbolList.cc b/src/SymbolList.cc
index aada6062..e05d1d41 100644
--- a/src/SymbolList.cc
+++ b/src/SymbolList.cc
@@ -17,14 +17,47 @@
  * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <regex>
+
 #include "SymbolList.hh"
 
+void
+SymbolList::setSymbolTable(const SymbolTable &symbol_table_arg)
+{
+  symbol_table = &symbol_table_arg;
+}
+
 void
 SymbolList::addSymbol(const string &symbol)
 {
   symbols.push_back(symbol);
 }
 
+void
+SymbolList::checkPass(WarningConsolidation &warnings) const noexcept(false)
+{
+  smatch m;
+  regex re("^(AUX_EXPECT_|AUX_ENDO_|MULT_)");
+  for (const auto & symbol : symbols)
+    {
+      if (!symbol_table->exists(symbol))
+        {
+          if (regex_search(symbol, m, re))
+            {
+              warnings << "WARNING: symbol_list variable " << symbol << " has not yet been declared. "
+                       << "This is being ignored because the variable name corresponds to a possible "
+                       << "auxiliary variable name." << endl;
+              return;
+            }
+          else
+            throw SymbolListException{"Variable " + symbol +  " was not declared."};
+        }
+
+      if (symbol_table->getType(symbol) != SymbolType::endogenous)
+        throw SymbolListException{"Variable " + symbol +  " is not endogenous."};
+    }
+}
+
 void
 SymbolList::writeOutput(const string &varname, ostream &output) const
 {
diff --git a/src/SymbolList.hh b/src/SymbolList.hh
index a3100d8e..87657d9c 100644
--- a/src/SymbolList.hh
+++ b/src/SymbolList.hh
@@ -26,6 +26,7 @@
 #include <algorithm>
 
 #include "WarningConsolidation.hh"
+#include "SymbolTable.hh"
 
 using namespace std;
 
@@ -36,11 +37,22 @@ class SymbolList
 private:
   //! Internal container for symbol list
   vector<string> symbols;
+  const SymbolTable *symbol_table;
 public:
+  class SymbolListException
+  {
+  public:
+    const string message;
+    SymbolListException(string message_arg) : message{move(message_arg)} {};
+  };
+  //! Set symbol table pointer
+  void setSymbolTable(const SymbolTable &symbol_table_arg);
   //! Adds a symbol to the list
   void addSymbol(const string &symbol);
   //! Removed duplicate symbols
   void removeDuplicates(const string &dynare_command, WarningConsolidation &warnings);
+  //! Check symbols to ensure variables have been declared and are endogenous
+  void checkPass(WarningConsolidation &warnings) const noexcept(false);
   //! Output content in Matlab format
   /*! Creates a string array for Matlab, stored in variable "varname" */
   void writeOutput(const string &varname, ostream &output) const;
-- 
GitLab