From 1d1a91239e7d00189e6a52b9d50ba04e881b69c6 Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Mon, 4 Dec 2017 14:16:42 +0100 Subject: [PATCH] preprocessor: support echomacrovars(save). closes #1564 --- doc/dynare.texi | 7 +++++++ preprocessor/DynareMain1.cc | 4 ++-- preprocessor/macro/MacroBison.yy | 8 ++++++-- preprocessor/macro/MacroDriver.cc | 31 ++++++++++++++++++++++++------- preprocessor/macro/MacroDriver.hh | 10 ++++++++-- preprocessor/macro/MacroFlex.ll | 3 ++- preprocessor/macro/MacroValue.cc | 2 +- preprocessor/macro/MacroValue.hh | 27 ++++++++++++++++++++++++--- 8 files changed, 74 insertions(+), 18 deletions(-) diff --git a/doc/dynare.texi b/doc/dynare.texi index 9bbeacb18..924eb95d9 100644 --- a/doc/dynare.texi +++ b/doc/dynare.texi @@ -10763,6 +10763,13 @@ Asks the preprocessor to display some error message on standard output and to abort. The argument must evaluate to a string. @end deffn +@deffn {Macro directive} @@#echomacrovars @var{MACRO_EXPRESSION} +@deffnx {Macro directive} @@#echomacrovars(save) @var{MACRO_EXPRESSION} +Asks the preprocessor to display the value of all macro variables up until this +point. If the @code{save} option is passed, the values of the macro variables +are saved to @code{options_.macrovars}. +@end deffn + @node Typical usages @subsection Typical usages diff --git a/preprocessor/DynareMain1.cc b/preprocessor/DynareMain1.cc index fe87ba83b..838122846 100644 --- a/preprocessor/DynareMain1.cc +++ b/preprocessor/DynareMain1.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Dynare Team + * Copyright (C) 2015-2017 Dynare Team * * This file is part of Dynare. * @@ -29,7 +29,7 @@ main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool sa // Do macro processing MacroDriver m; - m.parse(modfile, modfiletxt, macro_output, debug, no_line_macro, defines, path); + m.parse(modfile, basename, modfiletxt, macro_output, debug, no_line_macro, defines, path); if (save_macro) { if (save_macro_file.empty()) diff --git a/preprocessor/macro/MacroBison.yy b/preprocessor/macro/MacroBison.yy index 27c0e4b28..a2523356c 100644 --- a/preprocessor/macro/MacroBison.yy +++ b/preprocessor/macro/MacroBison.yy @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2016 Dynare Team + * Copyright (C) 2008-2017 Dynare Team * * This file is part of Dynare. * @@ -74,7 +74,7 @@ class MacroDriver; } %token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR IFDEF IFNDEF -%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH +%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH ECHOMACROVARS SAVE %token INTEGER %token NAME STRING @@ -121,6 +121,10 @@ statement : expr { TYPERR_CATCH(driver.error(@$, $2), @$); } | LINE STRING INTEGER /* Ignore @#line declarations */ + | ECHOMACROVARS + { driver.printvars(@$, true); } + | ECHOMACROVARS LPAREN SAVE RPAREN + { out << driver.printvars(@$, false); } ; expr : INTEGER diff --git a/preprocessor/macro/MacroDriver.cc b/preprocessor/macro/MacroDriver.cc index 1375e3e46..1633b8132 100644 --- a/preprocessor/macro/MacroDriver.cc +++ b/preprocessor/macro/MacroDriver.cc @@ -37,10 +37,13 @@ MacroDriver::~MacroDriver() } void -MacroDriver::parse(const string &f, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro, - map defines, vector path) +MacroDriver::parse(const string &f, const string &fb, const string &modfiletxt, + ostream &out, bool debug, bool no_line_macro_arg, map defines, + vector path) { file = f; + basename = fb; + no_line_macro = no_line_macro_arg; /* Copy the file into a stringstream, and add an extra end-of-line. This is a @@ -206,12 +209,26 @@ MacroDriver::error(const Macro::parser::location_type &l, const MacroValue *valu error(l, sval->value); } -void -MacroDriver::printvars(const Macro::parser::location_type &l) const +string +MacroDriver::printvars(const Macro::parser::location_type &l, const bool tostdout) const { - cout << "Macroprocessor: Printing macro variable values at line " << l << endl; + if (tostdout) + { + cout << "Macroprocessor: Printing macro variable values from " << file + << " at line " << l.begin.line << endl; + for (map::const_iterator it = env.begin(); + it != env.end(); it++) + cout << " " << it->first << " = " << it->second->print() << endl; + cout << endl; + return ""; + } + + stringstream intomfile; + if (!no_line_macro) + intomfile << "@#line \"" << file << "\" " << l.begin.line << endl; + for (map::const_iterator it = env.begin(); it != env.end(); it++) - cout << "|- " << it->first << " = " << it->second->print() << endl; - cout << endl; + intomfile<< "options_.macrovars." << it->first << " = " << it->second->print() << ";" << endl; + return intomfile.str(); } diff --git a/preprocessor/macro/MacroDriver.hh b/preprocessor/macro/MacroDriver.hh index 08c5d3882..53b1271d8 100644 --- a/preprocessor/macro/MacroDriver.hh +++ b/preprocessor/macro/MacroDriver.hh @@ -182,12 +182,18 @@ public: //! Starts parsing a file, returns output in out /*! \param no_line_macro should we omit the @#line statements ? */ - void parse(const string &f, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro, + void parse(const string &f, const string &fb, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro_arg, map defines, vector path); //! Name of main file being parsed string file; + //! Basename of main file being parsed + string basename; + + //! Whether or not to print @#line + bool no_line_macro; + //! Reference to the lexer class MacroFlex *lexer; @@ -198,7 +204,7 @@ public: void error(const Macro::parser::location_type &l, const string &m) const; //! Print variables - void printvars(const Macro::parser::location_type &l) const; + string printvars(const Macro::parser::location_type &l, const bool save) const; //! Set a variable void set_variable(const string &name, const MacroValue *value); diff --git a/preprocessor/macro/MacroFlex.ll b/preprocessor/macro/MacroFlex.ll index 503dc7bf3..5125ffa73 100644 --- a/preprocessor/macro/MacroFlex.ll +++ b/preprocessor/macro/MacroFlex.ll @@ -236,7 +236,8 @@ CONT \\\\ line { return token::LINE; } define { return token::DEFINE; } -echomacrovars{SPC}*{EOL} { driver.printvars(*yylloc); BEGIN(INITIAL); } +echomacrovars { return token::ECHOMACROVARS; } +save { return token::SAVE; } for { reading_for_statement = true; return token::FOR; } endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); } diff --git a/preprocessor/macro/MacroValue.cc b/preprocessor/macro/MacroValue.cc index 05a331eef..db8c8ac29 100644 --- a/preprocessor/macro/MacroValue.cc +++ b/preprocessor/macro/MacroValue.cc @@ -407,7 +407,7 @@ StringMV::toString() const string StringMV::print() const { - return toString(); + return "'" + value + "'"; } const MacroValue * diff --git a/preprocessor/macro/MacroValue.hh b/preprocessor/macro/MacroValue.hh index 9bcf71bbd..ced291895 100644 --- a/preprocessor/macro/MacroValue.hh +++ b/preprocessor/macro/MacroValue.hh @@ -23,6 +23,7 @@ #include #include #include +#include using namespace std; @@ -344,16 +345,36 @@ template string ArrayMV::print() const { + bool printStrArr = false; + try + { + typename vector::const_iterator it = values.begin(); + boost::lexical_cast(*it); + } + catch (boost::bad_lexical_cast &) + { + printStrArr= true; + } ostringstream ss; - ss << "["; + if (printStrArr) + ss << "{"; + else + ss << "["; for (typename vector::const_iterator it = values.begin(); it != values.end(); it++) { if (it != values.begin()) ss << ", "; - ss << *it; + + if (printStrArr) + ss << "'" << *it << "'"; + else + ss << *it; } - ss << "]"; + if (printStrArr) + ss << "}"; + else + ss << "]"; return ss.str(); }