diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index aa81f678434398aebfacc17b1c84798c0d865fa0..34efdb7881d872b2ea9f002abf63428fc3954ad8 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -4062,6 +4062,21 @@ DynamicModel::writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputTyp
     }
 }
 
+void
+DynamicModel::updateAfterVariableChange(DynamicModel &dm)
+{
+  variable_node_map.clear();
+  unary_op_node_map.clear();
+  binary_op_node_map.clear();
+  trinary_op_node_map.clear();
+  external_function_node_map.clear();
+  first_deriv_external_function_node_map.clear();
+  second_deriv_external_function_node_map.clear();
+
+  cloneDynamic(dm);
+  dm.replaceMyEquations(*this);
+}
+
 void
 DynamicModel::cloneDynamic(DynamicModel &dynamic_model) const
 {
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index dd60739b5c093b15bc1ad5d899b376180ea747b9..7ff8475f4b83b0d86fbc0d054c5cc639ba1f3e9b 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -335,6 +335,9 @@ public:
   /*! It assumes that the dynamic model given in argument has just been allocated */
   void cloneDynamic(DynamicModel &dynamic_model) const;
 
+  //! update equations after variable type change in model block
+  void updateAfterVariableChange(DynamicModel &dynamic_model);
+
   //! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
   void computeRamseyPolicyFOCs(const StaticModel &static_model, const bool nopreprocessoroutput);
   //! Replaces the model equations in dynamic_model with those in this model
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 97e59db1b9009e4a8b5f10e95109d6347701acc7..2ce25fea883fddbd4919360847f8d72dfd2d1b7d 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -122,7 +122,7 @@ class ParsingDriver;
 %token PERFECT_FORESIGHT_SETUP PERFECT_FORESIGHT_SOLVER NO_POSTERIOR_KERNEL_DENSITY FUNCTION
 %token PRINT PRIOR_MC PRIOR_TRUNC PRIOR_MODE PRIOR_MEAN POSTERIOR_MODE POSTERIOR_MEAN POSTERIOR_MEDIAN MLE_MODE PRUNING
 %token <string_val> QUOTED_STRING
-%token QZ_CRITERIUM QZ_ZERO_THRESHOLD FULL DSGE_VAR DSGE_VARLAG DSGE_PRIOR_WEIGHT TRUNCATE
+%token QZ_CRITERIUM QZ_ZERO_THRESHOLD FULL DSGE_VAR DSGE_VARLAG DSGE_PRIOR_WEIGHT TRUNCATE PIPE_E PIPE_X PIPE_P
 %token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY
 %token SHOCKS SHOCK_DECOMPOSITION SHOCK_GROUPS USE_SHOCK_GROUPS SIGMA_E SIMUL SIMUL_ALGO SIMUL_SEED ENDOGENOUS_TERMINAL_PERIOD
 %token SMOOTHER SMOOTHER2HISTVAL SQUARE_ROOT_SOLVER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO SOLVER_PERIODS ROBUST_LIN_SOLVE
@@ -878,6 +878,12 @@ hand_side : '(' hand_side ')'
             { $$ = $2;}
           | symbol
             { $$ = driver.add_model_variable($1); }
+          | symbol PIPE_E
+            { $$ = driver.declare_or_change_type(eEndogenous, $1); }
+          | symbol PIPE_X
+            { $$ = driver.declare_or_change_type(eExogenous, $1); }
+          | symbol PIPE_P
+            { $$ = driver.declare_or_change_type(eParameter, $1); }
           | non_negative_number
             { $$ = driver.add_non_negative_constant($1); }
           | hand_side PLUS hand_side
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 51a2b48a7fcd881845aa09323ddd19cbbc7036a9..39dd78364fabc212c25dd1db0bc28ce95ef0a8ca 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -905,6 +905,10 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
                     }
 <DATES_STATEMENT>.  { yylval->string_val->append(yytext); }
 
+<DYNARE_BLOCK>\|[eE] { return token::PIPE_E; }
+<DYNARE_BLOCK>\|[xX] { return token::PIPE_X; }
+<DYNARE_BLOCK>\|[pP] { return token::PIPE_P; }
+
 <DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']+\' {
   yylval->string_val = new string(yytext + 1);
   yylval->string_val->resize(yylval->string_val->length() - 1);
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index e949294e87e72a16dc3f5abd3c3a9642347bc00f..a611e8a1eb180e69da2fa48308b4ca012260e6e6 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -44,14 +44,14 @@ void
 ParsingDriver::check_symbol_existence_in_model_block(const string &name)
 {
   if (!mod_file->symbol_table.exists(name))
-    model_error("Unknown symbol: " + name);
+    model_error("Unknown symbol: " + name + ".\nTry using 'nostrict' option to have this declared as an exogenous variable by the preprocessor.", name);
 }
 
 void
 ParsingDriver::check_symbol_existence(const string &name)
 {
   if (!mod_file->symbol_table.exists(name))
-    error("Unknown symbol: " + name);
+    error("Unknown symbol: " + name + ".\nIf referenced from the 'initval', 'endval', 'histval', or 'shocks' block, you can pass the 'nostrict' option to dynare to have this line ignored.");
 }
 
 void
@@ -139,10 +139,17 @@ ParsingDriver::create_error_string(const Dynare::parser::location_type &l, const
 }
 
 void
-ParsingDriver::model_error(const string &m)
+ParsingDriver::create_error_string(const Dynare::parser::location_type &l, const string &m, const string &var)
 {
-  create_error_string(location, m, model_errors);
-  model_error_encountered = true;
+  ostringstream stream;
+  create_error_string(l, m, stream);
+  model_errors.push_back(make_pair(var, stream.str()));
+}
+
+void
+ParsingDriver::model_error(const string &m, const string &var)
+{
+  create_error_string(location, m, var);
 }
 
 void
@@ -377,7 +384,7 @@ ParsingDriver::add_model_variable(string *name)
     {
       symb_id = mod_file->symbol_table.getID(*name);
       if (undeclared_model_vars.find(*name) != undeclared_model_vars.end())
-        model_error("Unknown symbol: " + *name);
+        model_error("Unknown symbol: " + *name + ".\nTry using 'nostrict' option to have this declared as an exogenous variable by the preprocessor.", *name);
     }
   catch (SymbolTable::UnknownSymbolNameException &e)
     {
@@ -391,6 +398,57 @@ ParsingDriver::add_model_variable(string *name)
   return add_model_variable(symb_id, 0);
 }
 
+expr_t
+ParsingDriver::declare_or_change_type(SymbolType new_type, string *name)
+{
+  int symb_id;
+  try
+    {
+      symb_id = mod_file->symbol_table.getID(*name);
+      mod_file->symbol_table.changeType(symb_id, new_type);
+
+      // change in equations in ModelTree
+      DynamicModel *dm = new DynamicModel(mod_file->symbol_table,
+                                          mod_file->num_constants,
+                                          mod_file->external_functions_table);
+      mod_file->dynamic_model.updateAfterVariableChange(*dm);
+      delete dm;
+
+      // remove error messages
+      undeclared_model_vars.erase(*name);
+      for (vector<pair<string, string> >::iterator it = model_errors.begin();
+           it != model_errors.end();)
+        if (it->first == *name)
+          it = model_errors.erase(it);
+        else
+          it++;
+    }
+  catch (SymbolTable::UnknownSymbolNameException &e)
+    {
+      switch (new_type)
+        {
+        case eEndogenous:
+          declare_endogenous(new string(*name));
+          break;
+        case eExogenous:
+          declare_exogenous(new string(*name));
+          break;
+        case eExogenousDet:
+          declare_exogenous_det(new string(*name));
+          break;
+        case eParameter:
+          declare_parameter(new string(*name));
+          break;
+        default:
+          error("Type not yet supported");
+        }
+      symb_id = mod_file->symbol_table.getID(*name);
+    }
+  delete name;
+  return add_model_variable(symb_id, 0);
+
+}
+
 expr_t
 ParsingDriver::add_model_variable(int symb_id, int lag)
 {
@@ -702,6 +760,14 @@ ParsingDriver::initval_file(string *filename)
 void
 ParsingDriver::hist_val(string *name, string *lag, expr_t rhs)
 {
+  if (nostrict)
+    if (!mod_file->symbol_table.exists(*name))
+      {
+        warning("discarding '" + *name + "' as it was not recognized in the histavl block");
+        delete name;
+        return;
+      }
+
   check_symbol_existence(*name);
   int symb_id = mod_file->symbol_table.getID(*name);
   SymbolType type = mod_file->symbol_table.getType(symb_id);
@@ -894,10 +960,23 @@ ParsingDriver::begin_model()
 void
 ParsingDriver::end_model()
 {
-  if (model_error_encountered)
+  if (model_errors.size() > 0)
     {
-      cerr << model_errors.str();
-      exit(EXIT_FAILURE);
+      bool exit_after_write = false;
+      bool exit_after_write_undeclared_vars = true;
+      for (vector<pair<string, string> >::const_iterator it = model_errors.begin();
+           it != model_errors.end(); it++)
+        {
+          if (it->first == "")
+            exit_after_write = true;
+
+          if (mod_file->symbol_table.getType(it->first) == eExogenous)
+            exit_after_write_undeclared_vars = false;
+          else
+            cerr << it->second;
+        }
+      if (exit_after_write || exit_after_write_undeclared_vars)
+        exit(EXIT_FAILURE);
     }
   reset_data_tree();
 }
@@ -966,6 +1045,14 @@ ParsingDriver::add_det_shock(string *var, bool conditional_forecast)
 void
 ParsingDriver::add_stderr_shock(string *var, expr_t value)
 {
+  if (nostrict)
+    if (!mod_file->symbol_table.exists(*var))
+      {
+        warning("discarding shocks block declaration of the standard error of '" + *var + "' as it was not declared");
+        delete var;
+        return;
+      }
+
   check_symbol_existence(*var);
   int symb_id = mod_file->symbol_table.getID(*var);
 
@@ -981,6 +1068,14 @@ ParsingDriver::add_stderr_shock(string *var, expr_t value)
 void
 ParsingDriver::add_var_shock(string *var, expr_t value)
 {
+  if (nostrict)
+    if (!mod_file->symbol_table.exists(*var))
+      {
+        warning("discarding shocks block declaration of the variance of '" + *var + "' as it was not declared");
+        delete var;
+        return;
+      }
+
   check_symbol_existence(*var);
   int symb_id = mod_file->symbol_table.getID(*var);
 
@@ -996,6 +1091,15 @@ ParsingDriver::add_var_shock(string *var, expr_t value)
 void
 ParsingDriver::add_covar_shock(string *var1, string *var2, expr_t value)
 {
+  if (nostrict)
+    if (!mod_file->symbol_table.exists(*var1) || !mod_file->symbol_table.exists(*var2))
+      {
+        warning("discarding shocks block declaration of the covariance of '" + *var1 + "' and '" + *var2 + "' as at least one was not declared");
+        delete var1;
+        delete var2;
+        return;
+      }
+
   check_symbol_existence(*var1);
   check_symbol_existence(*var2);
   int symb_id1 = mod_file->symbol_table.getID(*var1);
@@ -1019,6 +1123,15 @@ ParsingDriver::add_covar_shock(string *var1, string *var2, expr_t value)
 void
 ParsingDriver::add_correl_shock(string *var1, string *var2, expr_t value)
 {
+  if (nostrict)
+    if (!mod_file->symbol_table.exists(*var1) || !mod_file->symbol_table.exists(*var2))
+      {
+        warning("discarding shocks block declaration of the correlation of '" + *var1 + "' and '" + *var2 + "' as at least one was not declared");
+        delete var1;
+        delete var2;
+        return;
+      }
+
   check_symbol_existence(*var1);
   check_symbol_existence(*var2);
   int symb_id1 = mod_file->symbol_table.getID(*var1);
@@ -3071,11 +3184,11 @@ ParsingDriver::add_model_var_or_external_function(string *function_name, bool in
           else
             { // e.g. model_var(lag) => ADD MODEL VARIABLE WITH LEAD (NumConstNode)/LAG (UnaryOpNode)
               if (undeclared_model_vars.find(*function_name) != undeclared_model_vars.end())
-                model_error("Unknown symbol: " + *function_name);
+                model_error("Unknown symbol: " + *function_name + ".\nTry using 'nostrict' option to have this declared as an exogenous variable by the preprocessor.", *function_name);
 
               pair<bool, double> rv = is_there_one_integer_argument();
               if (!rv.first)
-                model_error(string("Symbol ") + *function_name + string(" is being treated as if it were a function (i.e., takes an argument that is not an integer)."));
+                model_error(string("Symbol ") + *function_name + string(" is being treated as if it were a function (i.e., takes an argument that is not an integer)."), "");
 
               nid = add_model_variable(mod_file->symbol_table.getID(*function_name), (int) rv.second);
               stack_external_function_args.pop();
@@ -3106,7 +3219,7 @@ ParsingDriver::add_model_var_or_external_function(string *function_name, bool in
           // Continue processing, noting that it was not declared
           // Paring will end at the end of the model block
           undeclared_model_vars.insert(*function_name);
-          model_error("Unknown symbol: " + *function_name);
+          model_error("Unknown symbol: " + *function_name + ".\nTry using 'nostrict' option to have this declared as an exogenous variable by the preprocessor.", *function_name);
           pair<bool, double> rv = is_there_one_integer_argument();
           if (rv.first)
             {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 3b4d28ab9ca963eb244882fe9a4c43839f320e17..9ba67487876fec42e25f4f78952d383d651ecb82 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -245,9 +245,7 @@ private:
 
   bool nostrict;
 
-  bool model_error_encountered;
-
-  ostringstream model_errors;
+  vector<pair<string, string> > model_errors;
 
   //! Used by VAR restrictions
   void clear_VAR_storage();
@@ -256,9 +254,7 @@ private:
   string pac_expectation_model_name, pac_expectation_var_model_name, pac_expectation_discount, pac_expectation_growth;
 
 public:
-  ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg), model_error_encountered(false)
-  {
-  };
+  ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg) { };
 
   //! Starts parsing, and constructs the MOD file representation
   /*! The returned pointer should be deleted after use */
@@ -302,9 +298,10 @@ public:
   void warning(const string &m);
 
   //! Error handler with explicit location (used in model block, accumulating error messages to be printed later)
-  void model_error(const string &m);
+  void model_error(const string &m, const string &var);
 
   //! Code shared between model_error() and error()
+  void create_error_string(const Dynare::parser::location_type &l, const string &m, const string &var);
   void create_error_string(const Dynare::parser::location_type &l, const string &m, ostream &stream);
 
   //! Check if a given symbol exists in the parsing context, and is not a mod file local variable
@@ -368,6 +365,9 @@ public:
   expr_t add_inf_constant();
   //! Adds a model variable to ModelTree and VariableTable
   expr_t add_model_variable(string *name);
+  //! Declares a variable of type new_type OR changes a variable in the equations to type new_type
+  //! and removes any error messages that may have been issued in model_errors
+  expr_t declare_or_change_type(SymbolType new_type, string *name);
   //! Adds an Expression's variable
   expr_t add_expression_variable(string *name);
   //! Adds a "periods" statement