diff --git a/src/ModFile.cc b/src/ModFile.cc index 6a378ecd62186acc169140f5555f15c33c458c21..5a0f38c064303bd443954d5588db13bb595eb68a 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -1311,8 +1311,8 @@ ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global, if (!no_warn) { - if (warnings.countWarnings() > 0) - mOutputFile << "disp('Note: " << warnings.countWarnings() + if (int num_warnings {warnings.numWarnings()}; num_warnings > 0) + mOutputFile << "disp('Note: " << num_warnings << " warning(s) encountered in the preprocessor')" << endl; mOutputFile << "if ~isempty(lastwarn)" << endl diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index 7933280afbedab14e0847c67e69afbb2bf368e4a..d8191d747312b767824290128c10a840420b1856 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -28,6 +28,8 @@ #include "ExprNode.hh" #include "ParsingDriver.hh" #include "Statement.hh" +/* NB: the following also imports our specialization of operator<< for location class, + used below in error() and undeclared_model_variable_error() */ #include "WarningConsolidation.hh" bool @@ -113,7 +115,7 @@ ParsingDriver::parse(istream& in, bool debug) void ParsingDriver::error(const Dynare::parser::location_type& l, const string& m) { - create_error_string(l, m, cerr); + cerr << "ERROR: " << l << ": " << m << endl; exit(EXIT_FAILURE); } @@ -123,54 +125,12 @@ 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::create_error_string(const Dynare::parser::location_type& l, const string& m, - const string& var) -{ - ostringstream stream; - create_error_string(l, m, stream); - model_errors.emplace_back(var, stream.str()); -} - -void -ParsingDriver::model_error(const string& m, const string& var) -{ - create_error_string(location, m, var); -} - void ParsingDriver::undeclared_model_variable_error(const string& m, const string& var) { ostringstream stream; if (!nostrict) - { - stream << "ERROR: " << *location.begin.filename << ": line " << location.begin.line; - if (location.begin.line == location.end.line) - if (location.begin.column == location.end.column - 1) - stream << ", col " << location.begin.column; - else - stream << ", cols " << location.begin.column << "-" << location.end.column - 1; - else - stream << ", col " << location.begin.column << " -" - << " line " << location.end.line << ", col " << location.end.column - 1; - stream << ": "; - } + stream << "ERROR: " << location << ": "; stream << m; if (nostrict) stream << " automatically declared exogenous."; @@ -913,13 +873,6 @@ void ParsingDriver::end_model() { bool exit_after_write = false; - if (model_errors.size() > 0) - for (auto& it : model_errors) - { - if (it.first.empty()) - exit_after_write = true; - cerr << it.second; - } if (undeclared_model_variable_errors.size() > 0) for (auto& it : undeclared_model_variable_errors) diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index a33642677f693b07c8945edb9caba3866f480c19..d1b7a1b191c1fb588670d77d299b0c5a944aba6e 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -272,7 +272,6 @@ private: bool nostrict; - vector<pair<string, string>> model_errors; vector<pair<string, string>> undeclared_model_variable_errors; //! True when parsing the epilogue block @@ -327,15 +326,8 @@ public: //! Error handler with explicit location (used in model block, accumulating error messages to be //! printed later) - void model_error(const string& m, const string& var); void undeclared_model_variable_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 bool symbol_exists_and_is_not_modfile_local_or_external_function(const string& s); //! Sets mode of ModelTree class to use C output diff --git a/src/WarningConsolidation.cc b/src/WarningConsolidation.cc index 4f584df700dd24e239f4599975e0603ed46e132c..0f51ee5cac7f7a8c220dc8fff1bfbae1617a6d7c 100644 --- a/src/WarningConsolidation.cc +++ b/src/WarningConsolidation.cc @@ -1,5 +1,5 @@ /* - * Copyright © 2012-2022 Dynare Team + * Copyright © 2012-2024 Dynare Team * * This file is part of Dynare. * @@ -18,39 +18,33 @@ */ #include "WarningConsolidation.hh" -#include <ostream> -WarningConsolidation& -operator<<(WarningConsolidation& wcc, const string& warning) +ostream& +operator<<(ostream& stream, const Dynare::location& l) { - if (wcc.no_warn) - return wcc; - - cerr << warning; - wcc.addWarning(warning); - return wcc; -}; + stream << *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; + + return stream; +} -WarningConsolidation& -operator<<(WarningConsolidation& wcc, const Dynare::location& loc) +void +WarningConsolidation::incrementWarnings(const string& msg) { - if (wcc.no_warn) - return wcc; - - stringstream ostr; - Dynare::position last = loc.end - 1; - ostr << loc.begin; - if (last.filename && (!loc.begin.filename || *loc.begin.filename != *last.filename)) - ostr << '-' << last; - else if (loc.begin.line != last.line) - ostr << '-' << last.line << '.' << last.column; - else if (loc.begin.column != last.column) - ostr << '-' << last.column; - - cerr << ostr.str(); - wcc.addWarning(ostr.str()); - return wcc; -}; + size_t p {0}; + while ((p = msg.find('\n', p)) != string::npos) + { + p++; + num_warnings++; + } +} WarningConsolidation& operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&)) @@ -58,49 +52,12 @@ operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&)) if (wcc.no_warn) return wcc; - cerr << pf; - wcc.addWarning(pf); - return wcc; -} - -void -WarningConsolidation::writeOutput(ostream& output) const -{ - if (warnings.str().empty()) - return; + ostringstream ostr; + ostr << pf; - output << "disp([char(10) 'Dynare Preprocessor Warning(s) Encountered:']);" << endl; - - bool writedisp = true; - string warningsstr = warnings.str(); - for (size_t i = 0; i < warningsstr.length(); i++) - { - if (writedisp) - { - output << "disp(' "; - writedisp = false; - } + cerr << ostr.str(); - if (warningsstr[i] != '\n') - output << warningsstr[i]; - else - { - output << "');" << endl; - if (i + 1 < warningsstr.length()) - writedisp = true; - } - } -} + wcc.incrementWarnings(ostr.str()); -int -WarningConsolidation::countWarnings() const -{ - size_t p = 0; - int n = 0; - while ((p = warnings.str().find('\n', p)) != string::npos) - { - p++; - n++; - } - return n; + return wcc; } diff --git a/src/WarningConsolidation.hh b/src/WarningConsolidation.hh index ac01f82526c8c098b99765344cc12527816c2f53..1285ffdb69fdcd52b611187e18682b1123580550 100644 --- a/src/WarningConsolidation.hh +++ b/src/WarningConsolidation.hh @@ -1,5 +1,5 @@ /* - * Copyright © 2012-2023 Dynare Team + * Copyright © 2012-2024 Dynare Team * * This file is part of Dynare. * @@ -21,45 +21,64 @@ #define WARNING_CONSOLIDATION_HH #include "DynareBisonLocation.hh" + +#include <iostream> +#include <ostream> #include <sstream> #include <string> using namespace std; -//! Stores Warnings issued by the Preprocessor +/* Provide our implementation of operator<< with locations in DynareBison.hh. Note that the + following is a template specialization of the version provided in DynareBisonLocation.hh. + + Ideally it should go into DynareBisonLocation.hh, but there does not seem to be a way to achieve + that. */ +ostream& operator<<(ostream& stream, const Dynare::location& l); + class WarningConsolidation { private: - stringstream warnings; - bool no_warn; + const bool no_warn; + int num_warnings {0}; + + // Increases the warning counter by as many newlines as there are in the message + void incrementWarnings(const string& msg); public: explicit WarningConsolidation(bool no_warn_arg) : no_warn {no_warn_arg} { } - //! Add A Warning to the StringStream - friend WarningConsolidation& operator<<(WarningConsolidation& wcc, const string& warning); - friend WarningConsolidation& operator<<(WarningConsolidation& wcc, const Dynare::location& loc); + // Generic function to print something to the warning stream + friend WarningConsolidation& operator<<(WarningConsolidation& wcc, auto&& warning); + + /* Print std::endl to the warning stream. Unfortunately, since std::endl is a template of + functions, it cannot be bound to the universal reference of the generic function, hence the + need for this specialization. */ friend WarningConsolidation& operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&)); - void - addWarning(const string& w) - { - warnings << w; - }; - void - addWarning(ostream& (*pf)(ostream&)) + int + numWarnings() const { - warnings << pf; + return num_warnings; }; - - //! Write Warnings to m file - void writeOutput(ostream& output) const; - //! Count warnings - /*! This is done in a very lousy way, by counting newlines in the - stringstream... */ - int countWarnings() const; }; +WarningConsolidation& +operator<<(WarningConsolidation& wcc, auto&& warning) +{ + if (wcc.no_warn) + return wcc; + + ostringstream ostr; + ostr << warning; + + cerr << ostr.str(); + + wcc.incrementWarnings(ostr.str()); + + return wcc; +} + #endif