preprocessor: macroprocessor: add @#includepath macro. #1039

time-shift
Houtan Bastani 2015-08-28 12:38:25 +02:00
parent d8eff0843f
commit 2518f6c83c
3 changed files with 93 additions and 4 deletions

View File

@ -845,12 +845,14 @@ information about the configuration file.
Defines a macro-variable from the command line (the same effect as using
the Macro directive @code{@@#define} in a model file, @pxref{Macro-processing language}).
@anchor{-I}
@item -I@var{<<path>>}
Defines a path to search for files to be included by the
macroprocessor (using the @ref{@@#include} command). Multiple
@code{-I} flags can be passed on the command line. The paths will be
searched in the order that the @code{-I} flags are passed and the
first matching file will be used.
first matching file will be used. The flags passed here take priority
over those passed to @ref{@@#includepath}.
@item nostrict
Allows Dynare to issue a warning and continue processing when
@ -8832,6 +8834,8 @@ of the line indicates that the directive is continued on the next
line. The main directives are:
@itemize
@item
@code{@@#includepath}, paths to search for files that are to be included,
@item
@code{@@#include}, for file inclusion,
@item
@code{@@#define}, for defining a macro-processor variable,
@ -8937,13 +8941,34 @@ constructed as explained above.
@node Macro directives
@subsection Macro directives
@anchor{@@#includepath}
@deffn {Macro directive} @@#includepath "@var{PATH}"
@deffnx {Macro directive} @@#includepath @var{MACRO_VARIABLE}
This directive adds the colon-separated paths contained in @var{PATH}
to the list of those to search when looking for a @code{.mod} file
specified by @ref{@@#include}. Note that these paths are added
@i{after} any paths passed using @ref{-I}.
@examplehead
@example
@@#include "/path/to/folder/containing/modfiles:/path/to/another/folder"
@@#include folders_containing_mod_files
@end example
@end deffn
@anchor{@@#include}
@deffn {Macro directive} @@#include "@var{FILENAME}"
@deffnx {Macro directive} @@#include @var{MACRO_VARIABLE}
This directive simply includes the content of another file at the
place where it is inserted. It is exactly equivalent to a copy/paste
of the content of the included file. Note that it is possible to nest
includes (@i{i.e.} to include a file from an included file).
includes (@i{i.e.} to include a file from an included file). The file
will be searched for in the current directory. If it is not found, the
file will be searched for in the folders provided by @ref{-I} and
@ref{@@#includepath}.
@examplehead

View File

@ -79,7 +79,7 @@ private:
//! Should we omit the @#line statements ?
const bool no_line_macro;
//! The paths to search when looking for .mod files
const vector<string> path;
vector<string> path;
//! True iff current context is the body of a loop
bool is_for_context;
//! If current context is the body of a loop, contains the string of the loop body
@ -122,6 +122,10 @@ private:
//! Restore last scanning context
void restore_context(Macro::parser::location_type *yylloc);
//! pushes the colon-separated paths passed to @#includepath onto the path vector
void push_path(string *includepath, Macro::parser::location_type *yylloc,
MacroDriver &driver);
//! Saves current scanning context and create a new context with content of filename
/*! Filename must be a newly allocated string which will be deleted by the lexer */
void create_include_context(string *filename, Macro::parser::location_type *yylloc,
@ -178,7 +182,7 @@ public:
//! Starts parsing a file, returns output in out
/*! \param no_line_macro should we omit the @#line statements ? */
void parse(const string &f, ostream &out, bool debug, bool no_line_macro,
map<string,string> defines, const vector<string> path);
map<string,string> defines, vector<string> path);
//! Name of main file being parsed
string file;

View File

@ -21,6 +21,9 @@
using namespace std;
#include <fstream>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/tokenizer.hpp>
#include "MacroDriver.hh"
@ -68,6 +71,47 @@ CONT \\\\
yylloc->step();
%}
<INITIAL>^{SPC}*@#{SPC}*includepath{SPC}+\"([^\"\r\n:;|<>]*){1}(:[^\"\r\n:;|<>]*)*\"{SPC}*{EOL} {
yylloc->lines(1);
yylloc->step();
// Get path
string *includepath = new string(yytext);
int dblq_idx1 = includepath->find('"');
int dblq_idx2 = includepath->find('"', dblq_idx1 + 1);
includepath->erase(dblq_idx2);
includepath->erase(0, dblq_idx1 + 1);
push_path(includepath, yylloc, driver);
BEGIN(INITIAL);
}
<INITIAL>^{SPC}*@#{SPC}*includepath{SPC}+[^\"\r\n]*{SPC}*{EOL} {
yylloc->lines(1);
yylloc->step();
// Get variable name
string pathvar = string(yytext);
int dblq_idx1 = pathvar.find("includepath");
pathvar.erase(0, dblq_idx1 + 11);
pathvar.erase(0, pathvar.find_first_not_of(" \t"));
size_t p = pathvar.find_last_not_of(" \t\n\r");
if (string::npos != p)
pathvar.erase(p+1);
string *includepath = NULL;
try
{
includepath = new string(driver.get_variable(pathvar)->toString());
}
catch(MacroDriver::UnknownVariable(&e))
{
driver.error(*yylloc, "Unknown variable: " + pathvar);
}
push_path(includepath, yylloc, driver);
BEGIN(INITIAL);
}
<INITIAL>^{SPC}*@#{SPC}*include{SPC}+\"[^\"\r\n]*\"{SPC}*{EOL} {
yylloc->lines(1);
yylloc->step();
@ -383,6 +427,22 @@ MacroFlex::restore_context(Macro::parser::location_type *yylloc)
output_line(yylloc);
}
void
MacroFlex::push_path(string *includepath, Macro::parser::location_type *yylloc,
MacroDriver &driver)
{
using namespace boost;
vector<string> tokenizedPath;
split(tokenizedPath, *includepath, is_any_of(":"), token_compress_on);
for (vector<string>::iterator it = tokenizedPath.begin();
it != tokenizedPath.end(); it++ )
if (!it->empty())
{
trim(*it);
path.push_back(*it);
}
}
void
MacroFlex::create_include_context(string *filename, Macro::parser::location_type *yylloc,
MacroDriver &driver)