diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy index 8ea9b10d2..bbae98758 100644 --- a/preprocessor/DynareBison.yy +++ b/preprocessor/DynareBison.yy @@ -696,9 +696,9 @@ model_options_list : model_options_list COMMA model_options ; model : MODEL ';' { driver.begin_model(); } - equation_list END ';' { driver.reset_data_tree(); } + equation_list END ';' { driver.end_model(); } | MODEL '(' model_options_list ')' ';' { driver.begin_model(); } - equation_list END ';' { driver.reset_data_tree(); } + equation_list END ';' { driver.end_model(); } ; equation_list : equation_list equation diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc index e68b46ccb..6853646eb 100644 --- a/preprocessor/ParsingDriver.cc +++ b/preprocessor/ParsingDriver.cc @@ -40,6 +40,13 @@ ParsingDriver::symbol_exists_and_is_not_modfile_local_or_external_function(const return (type != eModFileLocalVariable && type != eExternalFunction); } +void +ParsingDriver::check_symbol_existence_in_model_block(const string &name) +{ + if (!mod_file->symbol_table.exists(name)) + model_error("Unknown symbol: " + name); +} + void ParsingDriver::check_symbol_existence(const string &name) { @@ -106,16 +113,7 @@ ParsingDriver::parse(istream &in, bool debug) void ParsingDriver::error(const Dynare::parser::location_type &l, const string &m) { - cerr << "ERROR: " << *l.begin.filename << ": line " << l.begin.line; - if (l.begin.line == l.end.line) - if (l.begin.column == l.end.column - 1) - cerr << ", col " << l.begin.column; - else - cerr << ", cols " << l.begin.column << "-" << l.end.column - 1; - else - cerr << ", col " << l.begin.column << " -" - << " line " << l.end.line << ", col " << l.end.column - 1; - cerr << ": " << m << endl; + create_error_string(l, m, cerr); exit(EXIT_FAILURE); } @@ -125,6 +123,28 @@ ParsingDriver::error(const string &m) error(location, m); } +void +ParsingDriver::create_error_string(const Dynare::parser::location_type &l, const string &m, ostream &stream) +{ + stream << "ERROR: " << *l.begin.filename << ": line " << l.begin.line; + if (l.begin.line == l.end.line) + if (l.begin.column == l.end.column - 1) + stream << ", col " << l.begin.column; + else + stream << ", cols " << l.begin.column << "-" << l.end.column - 1; + else + stream << ", col " << l.begin.column << " -" + << " line " << l.end.line << ", col " << l.end.column - 1; + stream << ": " << m << endl; +} + +void +ParsingDriver::model_error(const string &m) +{ + create_error_string(location, m, model_errors); + model_error_encountered = true; +} + void ParsingDriver::warning(const string &m) { @@ -334,8 +354,17 @@ ParsingDriver::add_inf_constant() expr_t ParsingDriver::add_model_variable(string *name) { - check_symbol_existence(*name); - int symb_id = mod_file->symbol_table.getID(*name); + check_symbol_existence_in_model_block(*name); + int symb_id; + try + { + symb_id = mod_file->symbol_table.getID(*name); + } + catch (SymbolTable::UnknownSymbolNameException &e) + { + declare_exogenous(new string (*name)); + symb_id = mod_file->symbol_table.getID(*name); + } delete name; return add_model_variable(symb_id, 0); } @@ -652,6 +681,17 @@ ParsingDriver::begin_model() set_current_data_tree(&mod_file->dynamic_model); } +void +ParsingDriver::end_model() +{ + if (model_error_encountered) + { + cerr << model_errors.str(); + exit(EXIT_FAILURE); + } + reset_data_tree(); +} + void ParsingDriver::end_shocks(bool overwrite) { diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh index 2eadc53bc..763aae516 100644 --- a/preprocessor/ParsingDriver.hh +++ b/preprocessor/ParsingDriver.hh @@ -93,6 +93,10 @@ private: //! Checks that a given symbol exists and is a endogenous or exogenous, and stops with an error message if it isn't void check_symbol_is_endogenous_or_exogenous(string *name); + //! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to be printed at + //! the end of the model block + void check_symbol_existence_in_model_block(const string &name); + //! Helper to add a symbol declaration void declare_symbol(const string *name, SymbolType type, const string *tex_name, const vector *> *partition_value); @@ -228,8 +232,12 @@ private: bool nostrict; + bool model_error_encountered; + + ostringstream model_errors; + public: - ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg) { }; + ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg), model_error_encountered(false) { }; //! Starts parsing, and constructs the MOD file representation /*! The returned pointer should be deleted after use */ @@ -257,6 +265,12 @@ public: //! Warning handler using saved location 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); + + //! Code shared between model_error() and error() + 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 bool symbol_exists_and_is_not_modfile_local_or_external_function(const char *s); //! Sets mode of ModelTree class to use C output @@ -341,6 +355,8 @@ public: void end_homotopy(); //! Begin a model block void begin_model(); + //! End a model block, printing errors that were encountered in parsing + void end_model(); //! Writes a shocks statement void end_shocks(bool overwrite); //! Writes a mshocks statement