Commit 1d1a9123 authored by Houtan Bastani's avatar Houtan Bastani

preprocessor: support echomacrovars(save). closes #1564

parent 8d9de2d5
......@@ -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
......
/*
* 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())
......
/*
* 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 <int_val> INTEGER
%token <string_val> 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
......
......@@ -37,10 +37,13 @@ MacroDriver::~MacroDriver()
}
void
MacroDriver::parse(const string &f, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro,
map<string, string> defines, vector<string> path)
MacroDriver::parse(const string &f, const string &fb, const string &modfiletxt,
ostream &out, bool debug, bool no_line_macro_arg, map<string, string> defines,
vector<string> 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<string, const MacroValue *>::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<string, const MacroValue *>::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();
}
......@@ -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<string, string> defines, vector<string> 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);
......
......@@ -236,7 +236,8 @@ CONT \\\\
<STMT>line { return token::LINE; }
<STMT>define { return token::DEFINE; }
<STMT>echomacrovars{SPC}*{EOL} { driver.printvars(*yylloc); BEGIN(INITIAL); }
<STMT>echomacrovars { return token::ECHOMACROVARS; }
<STMT>save { return token::SAVE; }
<STMT>for { reading_for_statement = true; return token::FOR; }
<STMT>endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); }
......
......@@ -407,7 +407,7 @@ StringMV::toString() const
string
StringMV::print() const
{
return toString();
return "'" + value + "'";
}
const MacroValue *
......
......@@ -23,6 +23,7 @@
#include <string>
#include <vector>
#include <sstream>
#include <boost/lexical_cast.hpp>
using namespace std;
......@@ -344,16 +345,36 @@ template<typename T>
string
ArrayMV<T>::print() const
{
bool printStrArr = false;
try
{
typename vector<T>::const_iterator it = values.begin();
boost::lexical_cast<int>(*it);
}
catch (boost::bad_lexical_cast &)
{
printStrArr= true;
}
ostringstream ss;
ss << "[";
if (printStrArr)
ss << "{";
else
ss << "[";
for (typename vector<T>::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();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment