diff --git a/mex/build/bytecode.am b/mex/build/bytecode.am
index f9fa7190266f0a5bec07b50c6bd094484c952941..d4c535657aa2f4a68b8f02a58cf5d32ad55372a6 100644
--- a/mex/build/bytecode.am
+++ b/mex/build/bytecode.am
@@ -9,7 +9,8 @@ nodist_bytecode_SOURCES = \
 	Interpreter.cc \
 	Mem_Mngr.cc \
 	SparseMatrix.cc \
-	Evaluate.cc
+	Evaluate.cc \
+	BasicSymbolTable.cc
 
 BUILT_SOURCES = $(nodist_bytecode_SOURCES)
 CLEANFILES = $(nodist_bytecode_SOURCES)
diff --git a/mex/sources/bytecode/BasicSymbolTable.cc b/mex/sources/bytecode/BasicSymbolTable.cc
new file mode 100644
index 0000000000000000000000000000000000000000..820cc7ef91bba0afe3b2b954c714ace04bf799a8
--- /dev/null
+++ b/mex/sources/bytecode/BasicSymbolTable.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2007-2022 Dynare Team
+ *
+ * This file is part of Dynare.
+ *
+ * Dynare is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Dynare is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "BasicSymbolTable.hh"
+
+#include "dynmex.h"
+
+BasicSymbolTable::BasicSymbolTable()
+{
+  mxArray *M_ = mexGetVariable("global", "M_");
+  if (!M_)
+    mexErrMsgTxt("Can't find global variable M_");
+
+  auto get_field_names = [&](const char *field_name, SymbolType type)
+  {
+    vector<string> r;
+    if (mxGetFieldNumber(M_, field_name) != -1)
+      {
+        auto M_field = mxGetFieldByNumber(M_, 0, mxGetFieldNumber(M_, field_name));
+        if (!mxIsCell(M_field))
+          mexErrMsgTxt(("M_."s + field_name + " is not a cell array").c_str());
+        for (size_t i {0}; i < mxGetNumberOfElements(M_field); i++)
+          {
+            const mxArray *cell_mx = mxGetCell(M_field, i);
+            if (!(cell_mx && mxIsChar(cell_mx)))
+              mexErrMsgTxt(("M_."s + field_name + " contains a cell which is not a character array").c_str());
+            r.emplace_back(mxArrayToString(cell_mx));
+          }
+      }
+
+    // Fill the reverse map
+    for (size_t i {0}; i < r.size(); i++)
+      name_to_id_and_type.emplace(r[i], pair{type, i});
+
+    return r;
+  };
+  endo_names = get_field_names("endo_names", SymbolType::endogenous);
+  param_names = get_field_names("param_names", SymbolType::parameter);
+  exo_names = get_field_names("exo_names", SymbolType::exogenous);
+  exo_det_names = get_field_names("exo_det_names", SymbolType::exogenousDet);
+}
+
+string
+BasicSymbolTable::getName(SymbolType type, int tsid) const
+{
+  try
+    {
+      switch (type)
+        {
+        case SymbolType::endogenous:
+          return endo_names.at(tsid);
+        case SymbolType::exogenous:
+          return exo_names.at(tsid);
+        case SymbolType::exogenousDet:
+          return exo_det_names.at(tsid);
+        case SymbolType::parameter:
+          return param_names.at(tsid);
+        default:
+          mexErrMsgTxt(("Unsupported symbol type: " + to_string(static_cast<int>(type)) + "\n").c_str());
+        }
+    }
+  catch (out_of_range &)
+    {
+      mexErrMsgTxt(("Unknown symbol with ID " + to_string(tsid) + " and type " + to_string(static_cast<int>(type)) + "\n").c_str());
+    }
+  exit(EXIT_FAILURE); // Silence GCC warning
+}
+
+pair<SymbolType, int>
+BasicSymbolTable::getIDAndType(const string &name) const
+{
+  try
+    {
+      return name_to_id_and_type.at(name);
+    }
+  catch (out_of_range &)
+    {
+      mexErrMsgTxt(("Unknown symbol: " + name + "\n").c_str());
+    }
+  exit(EXIT_FAILURE); // Silence GCC warning
+}
+
+size_t
+BasicSymbolTable::maxEndoNameLength() const
+{
+  size_t r {0};
+  for (const auto &n : endo_names)
+    r = max(r, n.size());
+  return r;
+}
diff --git a/mex/sources/bytecode/BasicSymbolTable.hh b/mex/sources/bytecode/BasicSymbolTable.hh
new file mode 100644
index 0000000000000000000000000000000000000000..fa078c5bde639f77587fe9ae82cadf3c167a63e1
--- /dev/null
+++ b/mex/sources/bytecode/BasicSymbolTable.hh
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2007-2022 Dynare Team
+ *
+ * This file is part of Dynare.
+ *
+ * Dynare is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Dynare is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef _BASIC_SYMBOL_TABLE_HH
+#define _BASIC_SYMBOL_TABLE_HH
+
+#include <string>
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "Bytecode.hh"
+
+using namespace std;
+
+class BasicSymbolTable
+{
+public:
+  BasicSymbolTable();
+  string getName(SymbolType type, int tsid) const;
+  pair<SymbolType, int> getIDAndType(const string &name) const;
+  size_t maxEndoNameLength() const;
+private:
+  vector<string> endo_names, param_names, exo_names, exo_det_names;
+  map<string, pair<SymbolType, int>> name_to_id_and_type;
+};
+
+#endif // _BASIC_SYMBOL_TABLE_HH
diff --git a/mex/sources/bytecode/ErrorHandling.hh b/mex/sources/bytecode/ErrorHandling.hh
index 884541547b43edcc866a5474a7597d603c683adb..971d0e21afe9c9b2c4d3efdb8f771e4daea4938a 100644
--- a/mex/sources/bytecode/ErrorHandling.hh
+++ b/mex/sources/bytecode/ErrorHandling.hh
@@ -38,6 +38,8 @@
 #define BYTECODE_MEX
 #include "Bytecode.hh"
 
+#include "BasicSymbolTable.hh"
+
 using namespace std;
 
 constexpr int NO_ERROR_ON_EXIT = 0, ERROR_ON_EXIT = 1;
@@ -166,48 +168,12 @@ extern "C" bool utIsInterruptPending();
 class ErrorMsg
 {
 protected:
-  ExpressionType EQN_type;
-  int EQN_equation, EQN_block, EQN_block_number, EQN_dvar1;
-  size_t endo_name_length; // Maximum length of endogenous names
-  vector<string> P_endo_names;
-private:
-  bool is_load_variable_list;
-  vector<string> P_exo_names, P_param_names;
-  vector<tuple<string, SymbolType, unsigned int>> Variable_list;
-
-public:
-  ErrorMsg() : is_load_variable_list {false}
+  ErrorMsg(BasicSymbolTable &symbol_table_arg) : symbol_table {symbol_table_arg}
   {
-    mxArray *M_ = mexGetVariable("global", "M_");
-    if (!M_)
-      mexErrMsgTxt("Can't find global variable M_");
-
-    auto get_field_names = [&](const char *symbol_type)
-    {
-      vector<string> r;
-      if (mxGetFieldNumber(M_, symbol_type) != -1)
-        {
-          auto M_field = mxGetFieldByNumber(M_, 0, mxGetFieldNumber(M_, symbol_type));
-          if (!mxIsCell(M_field))
-            mexErrMsgTxt(("M_."s + symbol_type + " is not a cell array").c_str());
-          for (size_t i = 0; i < mxGetNumberOfElements(M_field); i++)
-            {
-              const mxArray *cell_mx = mxGetCell(M_field, i);
-              if (!(cell_mx && mxIsChar(cell_mx)))
-                mexErrMsgTxt(("M_."s + symbol_type + " contains a cell which is not a character array").c_str());
-              r.emplace_back(mxArrayToString(cell_mx));
-            }
-        }
-      return r;
-    };
-    P_endo_names = get_field_names("endo_names");
-    P_exo_names = get_field_names("exo_names");
-    P_param_names = get_field_names("param_names");
-
-    endo_name_length = 0;
-    for (const auto &n : P_endo_names)
-      endo_name_length = max(endo_name_length, n.size());
   }
+  BasicSymbolTable &symbol_table;
+  ExpressionType EQN_type;
+  int EQN_equation, EQN_block, EQN_block_number, EQN_dvar1;
 
 private:
   /* Given a string which possibly contains a floating-point exception
@@ -241,72 +207,7 @@ private:
     return line1 + "\n" + line2;
   }
 
-  void
-  load_variable_list()
-  {
-    if (exchange(is_load_variable_list, true))
-      return;
-    for (size_t variable_num {0}; variable_num < P_endo_names.size(); variable_num++)
-      Variable_list.emplace_back(P_endo_names[variable_num], SymbolType::endogenous, variable_num);
-    for (size_t variable_num {0}; variable_num < P_exo_names.size(); variable_num++)
-      Variable_list.emplace_back(P_exo_names[variable_num], SymbolType::exogenous, variable_num);
-  }
-
-public:
-  int
-  get_ID(const string &variable_name, SymbolType *variable_type)
-  {
-    load_variable_list();
-    size_t n = Variable_list.size();
-    int i = 0;
-    bool notfound = true;
-    while (notfound && i < static_cast<int>(n))
-      {
-        if (variable_name == get<0>(Variable_list[i]))
-          {
-            notfound = false;
-            *variable_type = get<1>(Variable_list[i]);
-            return get<2>(Variable_list[i]);
-          }
-        i++;
-      }
-    return -1;
-  }
-
 protected:
-  string
-  get_variable(SymbolType variable_type, unsigned int variable_num) const
-  {
-    switch (variable_type)
-      {
-      case SymbolType::endogenous:
-        if (variable_num < P_endo_names.size())
-          return P_endo_names[variable_num];
-        else
-          mexPrintf("=> Unknown endogenous variable # %d", variable_num);
-        break;
-      case SymbolType::exogenous:
-        if (variable_num < P_exo_names.size())
-          return P_exo_names[variable_num];
-        else
-          mexPrintf("=> Unknown exogenous variable # %d", variable_num);
-        break;
-      case SymbolType::exogenousDet:
-        mexErrMsgTxt("get_variable: exogenous deterministic not supported");
-        break;
-      case SymbolType::parameter:
-        if (variable_num < P_param_names.size())
-          return P_param_names[variable_num];
-        else
-          mexPrintf("=> Unknown parameter # %d", variable_num);
-        break;
-      default:
-        break;
-      }
-    cerr << "ErrorHandling::get_variable: Internal error";
-    exit(EXIT_FAILURE); // Silence GCC warning
-  }
-
   string
   error_location(it_code_type expr_begin, it_code_type faulty_op, bool steady_state, int it_)
   {
@@ -335,16 +236,16 @@ protected:
       case ExpressionType::ModelEquation:
         break;
       case ExpressionType::FirstEndoDerivative:
-        Error_loc << " with respect to endogenous variable " << get_variable(SymbolType::endogenous, EQN_dvar1);
+        Error_loc << " with respect to endogenous variable " << symbol_table.getName(SymbolType::endogenous, EQN_dvar1);
         break;
       case ExpressionType::FirstOtherEndoDerivative:
-        Error_loc << " with respect to other endogenous variable " << get_variable(SymbolType::endogenous, EQN_dvar1);
+        Error_loc << " with respect to other endogenous variable " << symbol_table.getName(SymbolType::endogenous, EQN_dvar1);
         break;
       case ExpressionType::FirstExoDerivative:
-        Error_loc << " with respect to exogenous variable " << get_variable(SymbolType::exogenous, EQN_dvar1);
+        Error_loc << " with respect to exogenous variable " << symbol_table.getName(SymbolType::exogenous, EQN_dvar1);
         break;
       case ExpressionType::FirstExodetDerivative:
-        Error_loc << " with respect to deterministic exogenous variable " << get_variable(SymbolType::exogenousDet, EQN_dvar1);
+        Error_loc << " with respect to deterministic exogenous variable " << symbol_table.getName(SymbolType::exogenousDet, EQN_dvar1);
         break;
       }
     if (!steady_state)
@@ -447,7 +348,7 @@ protected:
                 case SymbolType::endogenous:
                 case SymbolType::exogenous:
                 case SymbolType::exogenousDet:
-                  Stack.emplace(get_variable(type, var) + lag_to_string(lag), 100, nullopt);
+                  Stack.emplace(symbol_table.getName(type, var) + lag_to_string(lag), 100, nullopt);
                   break;
                 default:
                   throw FatalExceptionHandling{"FLDV: Unknown variable type\n"};
@@ -464,7 +365,7 @@ protected:
                 case SymbolType::endogenous:
                 case SymbolType::exogenous:
                 case SymbolType::exogenousDet:
-                  Stack.emplace(get_variable(type, var), 100, nullopt);
+                  Stack.emplace(symbol_table.getName(type, var), 100, nullopt);
                   break;
                 default:
                   throw FatalExceptionHandling{"FLDSV: Unknown variable type\n"};
@@ -481,7 +382,7 @@ protected:
                 case SymbolType::endogenous:
                 case SymbolType::exogenous:
                 case SymbolType::exogenousDet:
-                  Stack.emplace(get_variable(type, var), 100, nullopt);
+                  Stack.emplace(symbol_table.getName(type, var), 100, nullopt);
                   break;
                 default:
                   throw FatalExceptionHandling{"FLDVS: Unknown variable type\n"};
@@ -520,7 +421,7 @@ protected:
                 case SymbolType::endogenous:
                 case SymbolType::exogenous:
                 case SymbolType::exogenousDet:
-                  assign_lhs(get_variable(type, var) + lag_to_string(lag));
+                  assign_lhs(symbol_table.getName(type, var) + lag_to_string(lag));
                   break;
                 default:
                   throw FatalExceptionHandling{"FSTPV: Unknown variable type\n"};
@@ -537,7 +438,7 @@ protected:
                 case SymbolType::endogenous:
                 case SymbolType::exogenous:
                 case SymbolType::exogenousDet:
-                  assign_lhs(get_variable(type, var));
+                  assign_lhs(symbol_table.getName(type, var));
                   break;
                 default:
                   throw FatalExceptionHandling{"FSTPSV: Unknown variable type\n"};
diff --git a/mex/sources/bytecode/Evaluate.cc b/mex/sources/bytecode/Evaluate.cc
index a5cc260a2f300a05a4888497e88bb156cab62f94..f9a4cf1a78237ec358e723d631d9597933c041ed 100644
--- a/mex/sources/bytecode/Evaluate.cc
+++ b/mex/sources/bytecode/Evaluate.cc
@@ -28,7 +28,8 @@
 extern "C" bool utIsInterruptPending();
 #endif
 
-Evaluate::Evaluate(int y_size_arg, int y_kmin_arg, int y_kmax_arg, bool print_it_arg, bool steady_state_arg, int periods_arg, int minimal_solving_periods_arg) :
+Evaluate::Evaluate(int y_size_arg, int y_kmin_arg, int y_kmax_arg, bool print_it_arg, bool steady_state_arg, int periods_arg, int minimal_solving_periods_arg, BasicSymbolTable &symbol_table_arg) :
+  ErrorMsg {symbol_table_arg},
   print_it(print_it_arg), minimal_solving_periods(minimal_solving_periods_arg)
 {
   symbol_table_endo_nbr = 0;
diff --git a/mex/sources/bytecode/Evaluate.hh b/mex/sources/bytecode/Evaluate.hh
index 9c8f665918dd3983ed1bf25041e82027ba0d98b6..99173f50765a2a68d4ae130e96ac27dde12c6cc3 100644
--- a/mex/sources/bytecode/Evaluate.hh
+++ b/mex/sources/bytecode/Evaluate.hh
@@ -86,7 +86,7 @@ protected:
   bool Gaussian_Elimination, is_linear;
 public:
   bool steady_state;
-  Evaluate(int y_size_arg, int y_kmin_arg, int y_kmax_arg, bool print_it_arg, bool steady_state_arg, int periods_arg, int minimal_solving_periods_arg);
+  Evaluate(int y_size_arg, int y_kmin_arg, int y_kmax_arg, bool print_it_arg, bool steady_state_arg, int periods_arg, int minimal_solving_periods_arg, BasicSymbolTable &symbol_table_arg);
   void set_block(int size_arg, BlockSimulationType type_arg, string file_name_arg, string bin_base_name_arg, int block_num_arg,
                  bool is_linear_arg, int symbol_table_endo_nbr_arg, int Block_List_Max_Lag_arg, int Block_List_Max_Lead_arg, int u_count_int_arg, int block_arg);
   void evaluate_complete(bool no_derivatives);
diff --git a/mex/sources/bytecode/Interpreter.cc b/mex/sources/bytecode/Interpreter.cc
index 98544030fab9553c0abf3edbca932f386262f419..d9b80e4614487a65633b0c902cc0c0ec09ef73e6 100644
--- a/mex/sources/bytecode/Interpreter.cc
+++ b/mex/sources/bytecode/Interpreter.cc
@@ -31,8 +31,8 @@ Interpreter::Interpreter(double *params_arg, double *y_arg, double *ya_arg, doub
                          int maxit_arg_, double solve_tolf_arg, size_t size_of_direction_arg, int y_decal_arg, double markowitz_c_arg,
                          string &filename_arg, int minimal_solving_periods_arg, int stack_solve_algo_arg, int solve_algo_arg,
                          bool global_temporary_terms_arg, bool print_arg, bool print_error_arg, mxArray *GlobalTemporaryTerms_arg,
-                         bool steady_state_arg, bool print_it_arg, int col_x_arg, int col_y_arg)
-: dynSparseMatrix(y_size_arg, y_kmin_arg, y_kmax_arg, print_it_arg, steady_state_arg, periods_arg, minimal_solving_periods_arg)
+                         bool steady_state_arg, bool print_it_arg, int col_x_arg, int col_y_arg, BasicSymbolTable &symbol_table_arg)
+: dynSparseMatrix {y_size_arg, y_kmin_arg, y_kmax_arg, print_it_arg, steady_state_arg, periods_arg, minimal_solving_periods_arg, symbol_table_arg}
 {
   params = params_arg;
   y = y_arg;
@@ -456,7 +456,7 @@ Interpreter::simulate_a_block(const vector_table_conditional_local_type &vector_
                 copy_n(y_save, y_size*(periods+y_kmax+y_kmin), y);
               u_count = u_count_saved;
               int prev_iter = iter;
-              Simulate_Newton_Two_Boundaries(block_num, symbol_table_endo_nbr, y_kmin, y_kmax, size, periods, cvg, minimal_solving_periods, stack_solve_algo, P_endo_names, vector_table_conditional_local);
+              Simulate_Newton_Two_Boundaries(block_num, symbol_table_endo_nbr, y_kmin, y_kmax, size, periods, cvg, minimal_solving_periods, stack_solve_algo, vector_table_conditional_local);
               iter++;
               if (iter > prev_iter)
                 {
@@ -481,7 +481,7 @@ Interpreter::simulate_a_block(const vector_table_conditional_local_type &vector_
           end_code = it_code;
 
           cvg = false;
-          Simulate_Newton_Two_Boundaries(block_num, symbol_table_endo_nbr, y_kmin, y_kmax, size, periods, cvg, minimal_solving_periods, stack_solve_algo, P_endo_names, vector_table_conditional_local);
+          Simulate_Newton_Two_Boundaries(block_num, symbol_table_endo_nbr, y_kmin, y_kmax, size, periods, cvg, minimal_solving_periods, stack_solve_algo, vector_table_conditional_local);
           max_res = 0; max_res_idx = 0;
         }
       slowc = 1; // slowc is modified when stack_solve_algo=4, so restore it
@@ -579,8 +579,8 @@ Interpreter::check_for_controlled_exo_validity(FBEGINBLOCK_ *fb, const vector<s_
       if (find(endogenous.begin(), endogenous.end(), it.exo_num) != endogenous.end()
           && find(exogenous.begin(), exogenous.end(), it.var_num) == exogenous.end())
         throw FatalExceptionHandling("\n the conditional forecast involving as constrained variable "
-                                     + get_variable(SymbolType::endogenous, it.exo_num)
-                                     + " and as endogenized exogenous " + get_variable(SymbolType::exogenous, it.var_num)
+                                     + symbol_table.getName(SymbolType::endogenous, it.exo_num)
+                                     + " and as endogenized exogenous " + symbol_table.getName(SymbolType::exogenous, it.var_num)
                                      + " that do not appear in block=" + to_string(Block_Count+1)
                                      + ")\n You should not use block in model options\n");
       else if (find(endogenous.begin(), endogenous.end(), it.exo_num) != endogenous.end()
@@ -593,7 +593,7 @@ Interpreter::check_for_controlled_exo_validity(FBEGINBLOCK_ *fb, const vector<s_
                != previous_block_exogenous.end())
         throw FatalExceptionHandling("\n the conditional forecast involves in the block "
                                      + to_string(Block_Count+1) + " the endogenized exogenous "
-                                     + get_variable(SymbolType::exogenous, it.var_num)
+                                     + symbol_table.getName(SymbolType::exogenous, it.var_num)
                                      + " that appear also in a previous block\n You should not use block in model options\n");
     }
   for (auto it : exogenous)
@@ -830,7 +830,7 @@ Interpreter::extended_path(const string &file_name, const string &bin_basename,
   vector_table_conditional_local_type vector_table_conditional_local;
   vector_table_conditional_local.clear();
 
-  int endo_name_length_l = endo_name_length;
+  int endo_name_length_l = static_cast<int>(symbol_table.maxEndoNameLength());
   for (int j = 0; j < col_x* nb_row_x; j++)
     {
       x_save[j] = x[j];
@@ -898,7 +898,7 @@ Interpreter::extended_path(const string &file_name, const string &bin_basename,
         {
           ostringstream res1;
           res1 << std::scientific << max_res;
-          mexPrintf("%s|%s| %4d  |  x  |\n", elastic(P_endo_names[max_res_idx], endo_name_length_l+2, true).c_str(), elastic(res1.str(), real_max_length+2, false).c_str(), iter);
+          mexPrintf("%s|%s| %4d  |  x  |\n", elastic(symbol_table.getName(SymbolType::endogenous, max_res_idx), endo_name_length_l+2, true).c_str(), elastic(res1.str(), real_max_length+2, false).c_str(), iter);
           mexPrintf(line.c_str());
           mexEvalString("drawnow;");
         }
diff --git a/mex/sources/bytecode/Interpreter.hh b/mex/sources/bytecode/Interpreter.hh
index 785285198052c8f947f924a3f4912f6d24489e8a..8564772afa3b71b466fa567b6dd91005a1c56eb3 100644
--- a/mex/sources/bytecode/Interpreter.hh
+++ b/mex/sources/bytecode/Interpreter.hh
@@ -49,7 +49,7 @@ public:
               int maxit_arg_, double solve_tolf_arg, size_t size_of_direction_arg, int y_decal_arg, double markowitz_c_arg,
               string &filename_arg, int minimal_solving_periods_arg, int stack_solve_algo_arg, int solve_algo_arg,
               bool global_temporary_terms_arg, bool print_arg, bool print_error_arg, mxArray *GlobalTemporaryTerms_arg,
-              bool steady_state_arg, bool print_it_arg, int col_x_arg, int col_y_arg);
+              bool steady_state_arg, bool print_it_arg, int col_x_arg, int col_y_arg, BasicSymbolTable &symbol_table_arg);
   bool extended_path(const string &file_name, const string &bin_basename, bool evaluate, int block, int &nb_blocks, int nb_periods, const vector<s_plan> &sextended_path, const vector<s_plan> &sconstrained_extended_path, const vector<string> &dates, const table_conditional_global_type &table_conditional_global);
   bool compute_blocks(const string &file_name, const string &bin_basename, bool evaluate, int block, int &nb_blocks);
   void check_for_controlled_exo_validity(FBEGINBLOCK_ *fb, const vector<s_plan> &sconstrained_extended_path);
diff --git a/mex/sources/bytecode/Mem_Mngr.cc b/mex/sources/bytecode/Mem_Mngr.cc
index 6f35702bb0ebe0f01383c02e70b88eed6a6f7d49..c004ed6fe620e09e8f45891b88a43cbf20ddd005 100644
--- a/mex/sources/bytecode/Mem_Mngr.cc
+++ b/mex/sources/bytecode/Mem_Mngr.cc
@@ -71,19 +71,19 @@ Mem_Mngr::mxMalloc_NZE()
       CHUNK_SIZE += CHUNK_BLCK_SIZE;
       Nb_CHUNK++;
       NZE_Mem = static_cast<NonZeroElem *>(mxMalloc(CHUNK_BLCK_SIZE*sizeof(NonZeroElem))); /*The block of memory allocated*/
-      error_msg.test_mxMalloc(NZE_Mem, __LINE__, __FILE__, __func__, CHUNK_BLCK_SIZE*sizeof(NonZeroElem));
+      ErrorMsg::test_mxMalloc(NZE_Mem, __LINE__, __FILE__, __func__, CHUNK_BLCK_SIZE*sizeof(NonZeroElem));
       NZE_Mem_Allocated.push_back(NZE_Mem);
       if (!NZE_Mem)
         mexPrintf("Not enough memory available\n");
       if (NZE_Mem_add)
         {
           NZE_Mem_add = static_cast<NonZeroElem **>(mxRealloc(NZE_Mem_add, CHUNK_SIZE*sizeof(NonZeroElem *))); /*We have to redefine the size of pointer on the memory*/
-          error_msg.test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__, CHUNK_SIZE*sizeof(NonZeroElem *));
+          ErrorMsg::test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__, CHUNK_SIZE*sizeof(NonZeroElem *));
         }
       else
         {
           NZE_Mem_add = static_cast<NonZeroElem **>(mxMalloc(CHUNK_SIZE*sizeof(NonZeroElem *))); /*We have to define the size of pointer on the memory*/
-          error_msg.test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__, CHUNK_SIZE*sizeof(NonZeroElem *));
+          ErrorMsg::test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__, CHUNK_SIZE*sizeof(NonZeroElem *));
         }
 
       if (!NZE_Mem_add)
diff --git a/mex/sources/bytecode/Mem_Mngr.hh b/mex/sources/bytecode/Mem_Mngr.hh
index 8d3f4cb25ede5a017343ec67ad2ac49337530f66..0936e7f01dec666e56dd12837d255460d4a020be 100644
--- a/mex/sources/bytecode/Mem_Mngr.hh
+++ b/mex/sources/bytecode/Mem_Mngr.hh
@@ -48,7 +48,6 @@ public:
   Mem_Mngr();
   void fixe_file_name(string filename_arg);
   bool swp_f;
-  ErrorMsg error_msg;
 private:
   v_NonZeroElem Chunk_Stack;
   unsigned int CHUNK_SIZE, CHUNK_BLCK_SIZE, Nb_CHUNK;
diff --git a/mex/sources/bytecode/SparseMatrix.cc b/mex/sources/bytecode/SparseMatrix.cc
index a579440f99157b6c4a7d486dd98f60f8d6152162..269362b38fa3f36b30895b385095e0d63d8c053c 100644
--- a/mex/sources/bytecode/SparseMatrix.cc
+++ b/mex/sources/bytecode/SparseMatrix.cc
@@ -23,8 +23,8 @@
 #include "SparseMatrix.hh"
 
 dynSparseMatrix::dynSparseMatrix(int y_size_arg, int y_kmin_arg, int y_kmax_arg, bool print_it_arg, bool steady_state_arg, int periods_arg,
-                                 int minimal_solving_periods_arg) :
-  Evaluate(y_size_arg, y_kmin_arg, y_kmax_arg, print_it_arg, steady_state_arg, periods_arg, minimal_solving_periods_arg)
+                                 int minimal_solving_periods_arg, BasicSymbolTable &symbol_table_arg) :
+  Evaluate {y_size_arg, y_kmin_arg, y_kmax_arg, print_it_arg, steady_state_arg, periods_arg, minimal_solving_periods_arg, symbol_table_arg}
 {
   pivotva = nullptr;
   g_save_op = nullptr;
@@ -3917,7 +3917,7 @@ dynSparseMatrix::preconditioner_print_out(string s, int preconditioner, bool ss)
 }
 
 void
-dynSparseMatrix::Simulate_Newton_Two_Boundaries(int blck, int y_size, int y_kmin, int y_kmax,int Size, int periods, bool cvg, int minimal_solving_periods, int stack_solve_algo, const vector<string> &P_endo_names, const vector_table_conditional_local_type &vector_table_conditional_local)
+dynSparseMatrix::Simulate_Newton_Two_Boundaries(int blck, int y_size, int y_kmin, int y_kmax,int Size, int periods, bool cvg, int minimal_solving_periods, int stack_solve_algo, const vector_table_conditional_local_type &vector_table_conditional_local)
 {
   double top = 0.5;
   double bottom = 0.1;
@@ -3955,9 +3955,9 @@ dynSparseMatrix::Simulate_Newton_Two_Boundaries(int blck, int y_size, int y_kmin
                     break;
                   }
               if (select)
-                mexPrintf("-> variable %s (%d) at time %d = %f direction = %f\n", P_endo_names[j].c_str(), j+1, it_, y[j+it_*y_size], direction[j+it_*y_size]);
+                mexPrintf("-> variable %s (%d) at time %d = %f direction = %f\n", symbol_table.getName(SymbolType::endogenous, j).c_str(), j+1, it_, y[j+it_*y_size], direction[j+it_*y_size]);
               else
-                mexPrintf("   variable %s (%d) at time %d = %f direction = %f\n", P_endo_names[j].c_str(), j+1, it_, y[j+it_*y_size], direction[j+it_*y_size]);
+                mexPrintf("   variable %s (%d) at time %d = %f direction = %f\n", symbol_table.getName(SymbolType::endogenous, j).c_str(), j+1, it_, y[j+it_*y_size], direction[j+it_*y_size]);
             }
           if (iter == 0)
             throw FatalExceptionHandling(" in Simulate_Newton_Two_Boundaries, the initial values of endogenous variables are too far from the solution.\nChange them!\n");
diff --git a/mex/sources/bytecode/SparseMatrix.hh b/mex/sources/bytecode/SparseMatrix.hh
index c7ae7f11b8e4ea58032a1d4a7b06412ff01b2a47..14f6fb76e8a545456e018403befaca66f5c134c0 100644
--- a/mex/sources/bytecode/SparseMatrix.hh
+++ b/mex/sources/bytecode/SparseMatrix.hh
@@ -51,8 +51,8 @@ constexpr double mem_increasing_factor = 1.1;
 class dynSparseMatrix : public Evaluate
 {
 public:
-  dynSparseMatrix(int y_size_arg, int y_kmin_arg, int y_kmax_arg, bool print_it_arg, bool steady_state_arg, int periods_arg, int minimal_solving_periods_arg);
-  void Simulate_Newton_Two_Boundaries(int blck, int y_size, int y_kmin, int y_kmax, int Size, int periods, bool cvg, int minimal_solving_periods, int stack_solve_algo, const vector<string> &P_endo_names, const vector_table_conditional_local_type &vector_table_conditional_local);
+  dynSparseMatrix(int y_size_arg, int y_kmin_arg, int y_kmax_arg, bool print_it_arg, bool steady_state_arg, int periods_arg, int minimal_solving_periods_arg, BasicSymbolTable &symbol_table_arg);
+  void Simulate_Newton_Two_Boundaries(int blck, int y_size, int y_kmin, int y_kmax, int Size, int periods, bool cvg, int minimal_solving_periods, int stack_solve_algo, const vector_table_conditional_local_type &vector_table_conditional_local);
   void Simulate_Newton_One_Boundary(bool forward);
   void fixe_u(double **u, int u_count_int, int max_lag_plus_max_lead_plus_1);
   void Read_SparseMatrix(const string &file_name, int Size, int periods, int y_kmin, int y_kmax, bool two_boundaries, int stack_solve_algo, int solve_algo);
diff --git a/mex/sources/bytecode/bytecode.cc b/mex/sources/bytecode/bytecode.cc
index c9789439acccf9364e321f13741f235c4f602284..86909afdb678122e715123c4bc5924c2aaebdf18 100644
--- a/mex/sources/bytecode/bytecode.cc
+++ b/mex/sources/bytecode/bytecode.cc
@@ -257,7 +257,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
       params = mxGetPr(mxGetFieldByNumber(M_, 0, field));
     }
 
-  ErrorMsg emsg;
+  BasicSymbolTable symbol_table;
   vector<string> dates;
 
   if (extended_path)
@@ -416,8 +416,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
               char name[100];
               mxGetString(tmp, name, 100);
               splan[i].var = name;
-              SymbolType variable_type = SymbolType::endogenous;
-              int exo_num = emsg.get_ID(name, &variable_type);
+              auto [variable_type, exo_num] = symbol_table.getIDAndType(name);
               if (variable_type == SymbolType::exogenous)
                 splan[i].var_num = exo_num;
               else
@@ -429,8 +428,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
               char name[100];
               mxGetString(tmp, name, 100);
               splan[i].exo = name;
-              SymbolType variable_type;
-              int exo_num = emsg.get_ID(name, &variable_type);
+              auto [variable_type, exo_num] = symbol_table.getIDAndType(name);
               if (variable_type == SymbolType::endogenous)
                 splan[i].exo_num = exo_num;
               else
@@ -478,8 +476,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
               char name[100];
               mxGetString(tmp, name, 100);
               spfplan[i].var = name;
-              SymbolType variable_type = SymbolType::endogenous;
-              int exo_num = emsg.get_ID(name, &variable_type);
+              auto [variable_type, exo_num] = symbol_table.getIDAndType(name);
               if (variable_type == SymbolType::exogenous)
                 splan[i].var_num = exo_num;
               else
@@ -491,8 +488,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
               char name[100];
               mxGetString(tmp, name, 100);
               spfplan[i].exo = name;
-              SymbolType variable_type;
-              int exo_num = emsg.get_ID(name, &variable_type);
+              auto [variable_type, exo_num] = symbol_table.getIDAndType(name);
               if (variable_type == SymbolType::endogenous)
                 spfplan[i].exo_num = exo_num;
               else
@@ -715,9 +711,11 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
   size_t nb_row_x = row_x;
 
   clock_t t0 = clock();
-  Interpreter interprete(params, y, ya, x, steady_yd, steady_xd, direction, y_size, nb_row_x, periods, y_kmin, y_kmax, maxit_, solve_tolf, size_of_direction, y_decal,
-                         markowitz_c, file_name, minimal_solving_periods, stack_solve_algo, solve_algo, global_temporary_terms, print, print_error, GlobalTemporaryTerms, steady_state,
-                         print_it, col_x, col_y);
+  Interpreter interprete {params, y, ya, x, steady_yd, steady_xd, direction, y_size, nb_row_x,
+                          periods, y_kmin, y_kmax, maxit_, solve_tolf, size_of_direction, y_decal,
+                          markowitz_c, file_name, minimal_solving_periods, stack_solve_algo,
+                          solve_algo, global_temporary_terms, print, print_error, GlobalTemporaryTerms,
+                          steady_state, print_it, col_x, col_y, symbol_table};
   string f(fname);
   mxFree(fname);
   int nb_blocks = 0;