preprocessor: allow declaration of model variables in the model block

issue#70
Houtan Bastani 2017-03-27 16:20:50 +02:00
parent ddcad84f13
commit fabbc9e9f4
6 changed files with 105 additions and 16 deletions

View File

@ -3710,6 +3710,21 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool bytecode
writeDynamicMFile(t_basename);
}
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
{

View File

@ -263,6 +263,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);
//! Replaces the model equations in dynamic_model with those in this model

View File

@ -121,7 +121,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
@ -734,6 +734,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

View File

@ -852,6 +852,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);

View File

@ -44,7 +44,7 @@ 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, name);
}
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
@ -360,7 +367,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, *name);
}
catch (SymbolTable::UnknownSymbolNameException &e)
{
@ -374,6 +381,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> >::const_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)
{
@ -689,9 +747,10 @@ ParsingDriver::begin_model()
void
ParsingDriver::end_model()
{
if (model_error_encountered)
if (model_errors.size() > 0)
{
cerr << model_errors.str();
for (vector<pair<string, string> >::const_iterator it = model_errors.begin(); it != model_errors.end(); it++)
cerr << it->second;
exit(EXIT_FAILURE);
}
reset_data_tree();
@ -2657,11 +2716,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, *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();
@ -2692,7 +2751,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, *function_name);
pair<bool, double> rv = is_there_one_integer_argument();
if (rv.first)
{

View File

@ -234,12 +234,10 @@ private:
bool nostrict;
bool model_error_encountered;
ostringstream model_errors;
vector<pair<string, string> > model_errors;
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 */
@ -268,9 +266,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
@ -330,6 +329,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