v4 preprocessor/macro: added @for loops
git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@1724 ac1d8469-bf42-47a9-8791-bf33cf982152time-shift
parent
efeeb01b33
commit
98f9619003
|
@ -51,7 +51,7 @@ class MacroDriver;
|
||||||
{
|
{
|
||||||
string *string_val;
|
string *string_val;
|
||||||
int int_val;
|
int int_val;
|
||||||
MacroValue *mv;
|
const MacroValue *mv;
|
||||||
};
|
};
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
@ -64,9 +64,9 @@ class MacroDriver;
|
||||||
#undef yylex
|
#undef yylex
|
||||||
#define yylex driver.lexer->lex
|
#define yylex driver.lexer->lex
|
||||||
|
|
||||||
#define TYPERR_CATCH(st, loc) try \
|
#define TYPERR_CATCH(statement, loc) try \
|
||||||
{ \
|
{ \
|
||||||
st; \
|
statement; \
|
||||||
} \
|
} \
|
||||||
catch(MacroValue::TypeError &e) \
|
catch(MacroValue::TypeError &e) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -75,7 +75,7 @@ class MacroDriver;
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%token DEFINE LINE
|
%token DEFINE LINE FOR IN
|
||||||
%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL
|
%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL
|
||||||
|
|
||||||
%token <int_val> INTEGER
|
%token <int_val> INTEGER
|
||||||
|
@ -98,24 +98,30 @@ class MacroDriver;
|
||||||
%start statement_list_or_nothing;
|
%start statement_list_or_nothing;
|
||||||
|
|
||||||
statement_list_or_nothing : /* empty */
|
statement_list_or_nothing : /* empty */
|
||||||
| statement_list;
|
| statement_list
|
||||||
|
;
|
||||||
|
|
||||||
statement_list : statement EOL
|
statement_list : statement EOL
|
||||||
| statement_list statement EOL;
|
| statement_list statement EOL
|
||||||
|
;
|
||||||
|
|
||||||
statement : expr
|
statement : expr
|
||||||
{ *driver.out_stream << $1->toString(); delete $1; }
|
{ *driver.out_stream << $1->toString(); }
|
||||||
| DEFINE NAME EQUAL expr
|
| DEFINE NAME EQUAL expr
|
||||||
{ driver.set_variable(*$2, $4); delete $2; }
|
{ driver.set_variable(*$2, $4); delete $2; }
|
||||||
|
| FOR NAME IN expr
|
||||||
|
{ TYPERR_CATCH(driver.init_loop(*$2, $4), @$); delete $2; }
|
||||||
| LINE STRING INTEGER
|
| LINE STRING INTEGER
|
||||||
/* Ignore @line declarations */
|
/* Ignore @line declarations */
|
||||||
|
;
|
||||||
|
|
||||||
expr : INTEGER
|
expr : INTEGER
|
||||||
{ $$ = new IntMV($1); }
|
{ $$ = new IntMV(driver, $1); }
|
||||||
| STRING
|
| STRING
|
||||||
{ $$ = new StringMV(*$1); delete $1; }
|
{ $$ = new StringMV(driver, *$1); delete $1; }
|
||||||
| NAME
|
| NAME
|
||||||
{ try
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
$$ = driver.get_variable(*$1);
|
$$ = driver.get_variable(*$1);
|
||||||
}
|
}
|
||||||
|
@ -123,56 +129,58 @@ expr : INTEGER
|
||||||
{
|
{
|
||||||
error(@$, "Unknown variable: " + e.name);
|
error(@$, "Unknown variable: " + e.name);
|
||||||
}
|
}
|
||||||
delete $1; }
|
delete $1;
|
||||||
|
}
|
||||||
| LPAREN expr RPAREN
|
| LPAREN expr RPAREN
|
||||||
{ $$ = $2; }
|
{ $$ = $2; }
|
||||||
| expr PLUS expr
|
| expr PLUS expr
|
||||||
{ TYPERR_CATCH($$ = *$1 + *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 + *$3, @$); }
|
||||||
| expr MINUS expr
|
| expr MINUS expr
|
||||||
{ TYPERR_CATCH($$ = *$1 - *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 - *$3, @$); }
|
||||||
| expr TIMES expr
|
| expr TIMES expr
|
||||||
{ TYPERR_CATCH($$ = *$1 * *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 * *$3, @$); }
|
||||||
| expr DIVIDE expr
|
| expr DIVIDE expr
|
||||||
{ TYPERR_CATCH($$ = *$1 / *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 / *$3, @$); }
|
||||||
| expr LESS expr
|
| expr LESS expr
|
||||||
{ TYPERR_CATCH($$ = *$1 < *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 < *$3, @$); }
|
||||||
| expr GREATER expr
|
| expr GREATER expr
|
||||||
{ TYPERR_CATCH($$ = *$1 > *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 > *$3, @$); }
|
||||||
| expr LESS_EQUAL expr
|
| expr LESS_EQUAL expr
|
||||||
{ TYPERR_CATCH($$ = *$1 <= *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 <= *$3, @$); }
|
||||||
| expr GREATER_EQUAL expr
|
| expr GREATER_EQUAL expr
|
||||||
{ TYPERR_CATCH($$ = *$1 >= *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 >= *$3, @$); }
|
||||||
| expr EQUAL_EQUAL expr
|
| expr EQUAL_EQUAL expr
|
||||||
{ TYPERR_CATCH($$ = *$1 == *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 == *$3, @$); }
|
||||||
| expr EXCLAMATION_EQUAL expr
|
| expr EXCLAMATION_EQUAL expr
|
||||||
{ TYPERR_CATCH($$ = *$1 != *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 != *$3, @$); }
|
||||||
| expr LOGICAL_OR expr
|
| expr LOGICAL_OR expr
|
||||||
{ TYPERR_CATCH($$ = *$1 || *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 || *$3, @$); }
|
||||||
| expr LOGICAL_AND expr
|
| expr LOGICAL_AND expr
|
||||||
{ TYPERR_CATCH($$ = *$1 && *$3, @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = *$1 && *$3, @$); }
|
||||||
| MINUS expr %prec UMINUS
|
| MINUS expr %prec UMINUS
|
||||||
{ TYPERR_CATCH($$ = -*$2, @$); delete $2;}
|
{ TYPERR_CATCH($$ = -*$2, @$); }
|
||||||
| PLUS expr %prec UPLUS
|
| PLUS expr %prec UPLUS
|
||||||
{ TYPERR_CATCH($$ = +(*$2), @$); delete $2; }
|
{ TYPERR_CATCH($$ = +(*$2), @$); }
|
||||||
| EXCLAMATION expr
|
| EXCLAMATION expr
|
||||||
{ TYPERR_CATCH($$ = !*$2, @$); delete $2; }
|
{ TYPERR_CATCH($$ = !*$2, @$); }
|
||||||
| expr LBRACKET array_expr RBRACKET
|
| expr LBRACKET array_expr RBRACKET
|
||||||
{ TYPERR_CATCH($$ = (*$1)[*$3], @$)
|
{
|
||||||
|
TYPERR_CATCH($$ = (*$1)[*$3], @$)
|
||||||
catch(MacroValue::OutOfBoundsError)
|
catch(MacroValue::OutOfBoundsError)
|
||||||
{
|
{
|
||||||
error(@$, "Index out of bounds");
|
error(@$, "Index out of bounds");
|
||||||
}
|
}
|
||||||
delete $1; delete $3; }
|
}
|
||||||
| LBRACKET array_expr RBRACKET
|
| LBRACKET array_expr RBRACKET
|
||||||
{ $$ = $2; }
|
{ $$ = $2; }
|
||||||
| expr COLON expr
|
| expr COLON expr
|
||||||
{ TYPERR_CATCH($$ = IntMV::new_range(*$1, *$3), @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = IntMV::new_range(driver, $1, $3), @$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
array_expr : expr
|
array_expr : expr
|
||||||
{ $$ = $1->toArray(); delete $1; }
|
{ $$ = $1->toArray(); }
|
||||||
| array_expr COMMA expr
|
| array_expr COMMA expr
|
||||||
{ TYPERR_CATCH($$ = $3->append(*$1), @$); delete $1; delete $3; }
|
{ TYPERR_CATCH($$ = $3->append($1), @$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
|
@ -28,9 +28,9 @@ MacroDriver::MacroDriver() : trace_scanning(false), trace_parsing(false)
|
||||||
|
|
||||||
MacroDriver::~MacroDriver()
|
MacroDriver::~MacroDriver()
|
||||||
{
|
{
|
||||||
for(map<string, MacroValue *>::iterator it = env.begin();
|
for(set<const MacroValue *>::iterator it = values.begin();
|
||||||
it != env.end(); it++)
|
it != values.end(); it++)
|
||||||
delete it->second;
|
delete *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -40,6 +40,11 @@ MacroDriver::parse(const string &f, ostream &out)
|
||||||
out_stream = &out;
|
out_stream = &out;
|
||||||
|
|
||||||
ifstream in(f.c_str(), ios::binary);
|
ifstream in(f.c_str(), ios::binary);
|
||||||
|
if (in.fail())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Could not open file: " << f << endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
lexer = new MacroFlex(&in, &out);
|
lexer = new MacroFlex(&in, &out);
|
||||||
lexer->set_debug(trace_scanning);
|
lexer->set_debug(trace_scanning);
|
||||||
|
@ -58,16 +63,66 @@ MacroDriver::error(const Macro::parser::location_type &l, const string &m) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MacroDriver::set_variable(const string &name, MacroValue *value)
|
MacroDriver::set_variable(const string &name, const MacroValue *value)
|
||||||
{
|
{
|
||||||
env[name] = value;
|
env[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroDriver::get_variable(const string &name) const throw (UnknownVariable)
|
MacroDriver::get_variable(const string &name) const throw (UnknownVariable)
|
||||||
{
|
{
|
||||||
map<string, MacroValue *>::const_iterator it = env.find(name);
|
map<string, const MacroValue *>::const_iterator it = env.find(name);
|
||||||
if (it == env.end())
|
if (it == env.end())
|
||||||
throw UnknownVariable(name);
|
throw UnknownVariable(name);
|
||||||
return (it->second)->clone();
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MacroDriver::init_loop(const string &name, const MacroValue *value) throw (MacroValue::TypeError)
|
||||||
|
{
|
||||||
|
const ArrayMV<int> *mv1 = dynamic_cast<const ArrayMV<int> *>(value);
|
||||||
|
const ArrayMV<string> *mv2 = dynamic_cast<const ArrayMV<string> *>(value);
|
||||||
|
if (!mv1 && !mv2)
|
||||||
|
throw MacroValue::TypeError("Argument of @for loop must be an array expression");
|
||||||
|
loop_stack.push(make_pair(name, make_pair(value, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MacroDriver::iter_loop()
|
||||||
|
{
|
||||||
|
if (loop_stack.empty())
|
||||||
|
throw "No loop on which to iterate!";
|
||||||
|
|
||||||
|
int &i = loop_stack.top().second.second;
|
||||||
|
const MacroValue *mv = loop_stack.top().second.first;
|
||||||
|
string name = loop_stack.top().first;
|
||||||
|
|
||||||
|
const ArrayMV<int> *mv1 = dynamic_cast<const ArrayMV<int> *>(mv);
|
||||||
|
if (mv1)
|
||||||
|
{
|
||||||
|
if (i >= (int) mv1->values.size())
|
||||||
|
{
|
||||||
|
loop_stack.pop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
env[name] = new IntMV(*this, mv1->values[i++]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ArrayMV<string> *mv2 = dynamic_cast<const ArrayMV<string> *>(mv);
|
||||||
|
if (i >= (int) mv2->values.size())
|
||||||
|
{
|
||||||
|
loop_stack.pop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
env[name] = new StringMV(*this, mv2->values[i++]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "MacroBison.hh"
|
#include "MacroBison.hh"
|
||||||
#include "MacroValue.hh"
|
#include "MacroValue.hh"
|
||||||
|
@ -47,14 +48,51 @@ using namespace std;
|
||||||
*/
|
*/
|
||||||
class MacroFlex : public MacroFlexLexer
|
class MacroFlex : public MacroFlexLexer
|
||||||
{
|
{
|
||||||
|
//! Used to backup all the information related to a given scanning context
|
||||||
|
class ScanContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
istream *input;
|
||||||
|
struct yy_buffer_state *buffer;
|
||||||
|
const Macro::parser::location_type yylloc;
|
||||||
|
const string for_body;
|
||||||
|
const Macro::parser::location_type for_body_loc;
|
||||||
|
ScanContext(istream *input_arg, struct yy_buffer_state *buffer_arg,
|
||||||
|
Macro::parser::location_type &yylloc_arg, const string &for_body_arg,
|
||||||
|
Macro::parser::location_type &for_body_loc_arg) :
|
||||||
|
input(input_arg), buffer(buffer_arg), yylloc(yylloc_arg), for_body(for_body_arg),
|
||||||
|
for_body_loc(for_body_loc_arg) { }
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
//! The stack used to handle (possibly nested) includes
|
//! The stack used to keep track of nested scanning contexts
|
||||||
/*! Keeps track of buffer state and associated location, as they were just before switching to
|
stack<ScanContext> context_stack;
|
||||||
included file.
|
|
||||||
Note that we could have used yypush_buffer_state() and yypop_buffer_state()
|
|
||||||
instead of a stack for buffer states, but those functions do not exist in Flex 2.5.4 */
|
|
||||||
stack<pair<struct yy_buffer_state *, Macro::parser::location_type> > include_stack;
|
|
||||||
|
|
||||||
|
//! Input stream used for initialization of current scanning context
|
||||||
|
/*! Kept for deletion at end of current scanning buffer */
|
||||||
|
istream *input;
|
||||||
|
|
||||||
|
//! If current context is the body of a loop, contains the string of the loop body. Empty otherwise.
|
||||||
|
string for_body;
|
||||||
|
//! If current context is the body of a loop, contains the location of the beginning of the body
|
||||||
|
Macro::parser::location_type for_body_loc;
|
||||||
|
|
||||||
|
//! Temporary variable used in FOR_BODY mode
|
||||||
|
string for_body_tmp;
|
||||||
|
//! Temporary variable used in FOR_BODY mode
|
||||||
|
Macro::parser::location_type for_body_loc_tmp;
|
||||||
|
//! Temporary variable used in FOR_BODY mode. Keeps track of number of nested @for/@endfor
|
||||||
|
int nested_for_nb;
|
||||||
|
//! Set to true while parsing a FOR statement (only the statement, not the loop body)
|
||||||
|
bool reading_for_statement;
|
||||||
|
|
||||||
|
//! Output the @line declaration
|
||||||
|
void output_line(Macro::parser::location_type *yylloc);
|
||||||
|
|
||||||
|
//! Iterates over the loop body
|
||||||
|
/*! If loop is terminated, return false and do nothing.
|
||||||
|
Otherwise, set loop variable to its new value (through driver.iter_loop()),
|
||||||
|
and initialise a new scanning context with the loop body */
|
||||||
|
bool iter_loop(MacroDriver &driver, Macro::parser::location_type *yylloc);
|
||||||
public:
|
public:
|
||||||
MacroFlex(istream* in = 0, ostream* out = 0);
|
MacroFlex(istream* in = 0, ostream* out = 0);
|
||||||
|
|
||||||
|
@ -67,10 +105,16 @@ public:
|
||||||
//! Implements the macro expansion using a Flex scanner and a Bison parser
|
//! Implements the macro expansion using a Flex scanner and a Bison parser
|
||||||
class MacroDriver
|
class MacroDriver
|
||||||
{
|
{
|
||||||
|
friend class MacroValue;
|
||||||
private:
|
private:
|
||||||
//! Environment: maps macro variables to their values
|
set<const MacroValue *> values;
|
||||||
map<string, MacroValue *> env;
|
|
||||||
|
|
||||||
|
//! Environment: maps macro variables to their values
|
||||||
|
map<string, const MacroValue *> env;
|
||||||
|
|
||||||
|
//! Stack used to keep track of (possibly nested) loops
|
||||||
|
//! First element is loop variable name, second is the array over which iteration is done, and third is subscript to be used by next call of iter_loop() (beginning with 0) */
|
||||||
|
stack<pair<string, pair<const MacroValue *, int> > > loop_stack;
|
||||||
public:
|
public:
|
||||||
//! Exception thrown when value of an unknown variable is requested
|
//! Exception thrown when value of an unknown variable is requested
|
||||||
class UnknownVariable
|
class UnknownVariable
|
||||||
|
@ -88,9 +132,6 @@ public:
|
||||||
//! Starts parsing a file, returns output in out
|
//! Starts parsing a file, returns output in out
|
||||||
void parse(const string &f, ostream &out);
|
void parse(const string &f, ostream &out);
|
||||||
|
|
||||||
//! Pointer to keep track of the input file stream currently scanned
|
|
||||||
ifstream *ifs;
|
|
||||||
|
|
||||||
//! Name of main file being parsed
|
//! Name of main file being parsed
|
||||||
string file;
|
string file;
|
||||||
|
|
||||||
|
@ -113,12 +154,19 @@ public:
|
||||||
void error(const Macro::parser::location_type &l, const string &m) const;
|
void error(const Macro::parser::location_type &l, const string &m) const;
|
||||||
|
|
||||||
//! Set a variable
|
//! Set a variable
|
||||||
/*! Pointer *value must not be altered nor deleted afterwards, since it is kept by this class */
|
void set_variable(const string &name, const MacroValue *value);
|
||||||
void set_variable(const string &name, MacroValue *value);
|
|
||||||
|
|
||||||
//! Get a variable
|
//! Get a variable
|
||||||
/*! Returns a newly allocated value (clone of the value stored in environment). */
|
/*! Returns a newly allocated value (clone of the value stored in environment). */
|
||||||
MacroValue *get_variable(const string &name) const throw (UnknownVariable);
|
const MacroValue *get_variable(const string &name) const throw (UnknownVariable);
|
||||||
|
|
||||||
|
//! Initiate a for loop
|
||||||
|
/*! Does not set name = value[1]. You must call iter_loop() for that. */
|
||||||
|
void init_loop(const string &name, const MacroValue *value) throw (MacroValue::TypeError);
|
||||||
|
|
||||||
|
//! Iterate innermost loop
|
||||||
|
/*! Returns false if iteration is no more possible (end of loop); in that case it destroys the pointer given to init_loop() */
|
||||||
|
bool iter_loop();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ! MACRO_DRIVER_HH
|
#endif // ! MACRO_DRIVER_HH
|
||||||
|
|
|
@ -47,9 +47,8 @@ typedef Macro::parser::token token;
|
||||||
|
|
||||||
%option case-insensitive noyywrap nounput batch debug never-interactive
|
%option case-insensitive noyywrap nounput batch debug never-interactive
|
||||||
|
|
||||||
%x INCLUDE
|
|
||||||
%x END_INCLUDE
|
|
||||||
%x MACRO
|
%x MACRO
|
||||||
|
%x FOR_BODY
|
||||||
|
|
||||||
%{
|
%{
|
||||||
// Increments location counter for every token read
|
// Increments location counter for every token read
|
||||||
|
@ -62,43 +61,54 @@ typedef Macro::parser::token token;
|
||||||
yylloc->step();
|
yylloc->step();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
<INITIAL>^@include[ \t]+\" BEGIN(INCLUDE);
|
<INITIAL>^@include[ \t]+\"[^\"\r\n]*\"[ \t]*(\r)?\n {
|
||||||
|
yylloc->lines(1);
|
||||||
<INCLUDE>[^\"\r\n]* {
|
|
||||||
driver.ifs = new ifstream(yytext, ios::binary);
|
|
||||||
if (driver.ifs->fail())
|
|
||||||
driver.error(*yylloc, "Could not open " + string(yytext));
|
|
||||||
// Save old buffer state and location
|
|
||||||
/* We don't use yypush_buffer_state(), since it doesn't exist in
|
|
||||||
Flex 2.5.4 (see Flex 2.5.33 info file - section 11 - for code
|
|
||||||
example with yypush_buffer_state()) */
|
|
||||||
yylloc->step();
|
yylloc->step();
|
||||||
include_stack.push(make_pair(YY_CURRENT_BUFFER, *yylloc));
|
// Save old buffer state and location
|
||||||
|
context_stack.push(ScanContext(input, YY_CURRENT_BUFFER, *yylloc, for_body, for_body_loc));
|
||||||
|
// Get filename
|
||||||
|
string *filename = new string(yytext);
|
||||||
|
int dblq_idx1 = filename->find('"');
|
||||||
|
int dblq_idx2 = filename->find('"', dblq_idx1 + 1);
|
||||||
|
filename->erase(dblq_idx2);
|
||||||
|
filename->erase(0, dblq_idx1 + 1);
|
||||||
|
// Open new file
|
||||||
|
input = new ifstream(filename->c_str(), ios::binary);
|
||||||
|
if (input->fail())
|
||||||
|
driver.error(*yylloc, "Could not open " + *filename);
|
||||||
// Reset location
|
// Reset location
|
||||||
yylloc->begin.filename = yylloc->end.filename = new string(yytext);
|
yylloc->begin.filename = yylloc->end.filename = filename;
|
||||||
yylloc->begin.line = yylloc->end.line = 1;
|
yylloc->begin.line = yylloc->end.line = 1;
|
||||||
yylloc->begin.column = yylloc->end.column = 0;
|
yylloc->begin.column = yylloc->end.column = 0;
|
||||||
|
// We are not in a loop body
|
||||||
|
for_body.erase();
|
||||||
// Output @line information
|
// Output @line information
|
||||||
*yyout << "@line \"" << *yylloc->begin.filename << "\" 1" << endl;
|
output_line(yylloc);
|
||||||
// Switch to new buffer
|
// Switch to new buffer
|
||||||
yy_switch_to_buffer(yy_create_buffer(driver.ifs, YY_BUF_SIZE));
|
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
<END_INCLUDE>\"[^\r\n]*(\r)?\n {
|
|
||||||
yylloc->lines(1);
|
|
||||||
yylloc->step();
|
|
||||||
*yyout << "@line \"" << *yylloc->begin.filename << "\" "
|
|
||||||
<< yylloc->begin.line << endl;
|
|
||||||
BEGIN(INITIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
<INITIAL>@ { BEGIN(MACRO); }
|
<INITIAL>@ { BEGIN(MACRO); }
|
||||||
|
|
||||||
|
|
||||||
<MACRO>[ \t\r\f]+ { yylloc->step(); }
|
<MACRO>[ \t\r\f]+ { yylloc->step(); }
|
||||||
<MACRO>@ { BEGIN(INITIAL); return token::EOL; }
|
<MACRO>@ { BEGIN(INITIAL); return token::EOL; }
|
||||||
<MACRO>\n { BEGIN(INITIAL); yylloc->lines(1); yylloc->step(); *yyout << endl; return token::EOL; }
|
<MACRO>\n {
|
||||||
|
yylloc->lines(1);
|
||||||
|
yylloc->step();
|
||||||
|
if (reading_for_statement)
|
||||||
|
{
|
||||||
|
reading_for_statement = false;
|
||||||
|
for_body_tmp.erase();
|
||||||
|
for_body_loc_tmp = *yylloc;
|
||||||
|
nested_for_nb = 0;
|
||||||
|
BEGIN(FOR_BODY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
*yyout << endl;
|
||||||
|
return token::EOL;
|
||||||
|
}
|
||||||
|
|
||||||
<MACRO>[0-9]+ {
|
<MACRO>[0-9]+ {
|
||||||
yylval->int_val = atoi(yytext);
|
yylval->int_val = atoi(yytext);
|
||||||
|
@ -133,31 +143,68 @@ typedef Macro::parser::token token;
|
||||||
|
|
||||||
<MACRO>line { return token::LINE; }
|
<MACRO>line { return token::LINE; }
|
||||||
<MACRO>define { return token::DEFINE; }
|
<MACRO>define { return token::DEFINE; }
|
||||||
|
<MACRO>for { reading_for_statement = true; return token::FOR; }
|
||||||
|
<MACRO>in { return token::IN; }
|
||||||
|
<MACRO>endfor { driver.error(*yylloc, "@endfor is not matched by a @for statement"); }
|
||||||
|
|
||||||
<MACRO>[A-Za-z_][A-Za-z0-9_]* {
|
<MACRO>[A-Za-z_][A-Za-z0-9_]* {
|
||||||
yylval->string_val = new string(yytext);
|
yylval->string_val = new string(yytext);
|
||||||
return token::NAME;
|
return token::NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<MACRO><<EOF>> { driver.error(*yylloc, "Unexpected end of file while parsing a macro expression"); }
|
||||||
|
|
||||||
<<EOF>> {
|
<FOR_BODY>[\n]+ { yylloc->lines(yyleng); yylloc->step(); for_body_tmp.append(yytext); }
|
||||||
|
<FOR_BODY>@for { nested_for_nb++; for_body_tmp.append(yytext); }
|
||||||
|
<FOR_BODY>. { for_body_tmp.append(yytext); }
|
||||||
|
<FOR_BODY><<EOF>> { driver.error(*yylloc, "Unexpected end of file: @for loop not matched by an @endfor"); }
|
||||||
|
<FOR_BODY>@endfor[ \t]*(\r)?\n {
|
||||||
|
if (nested_for_nb)
|
||||||
|
{
|
||||||
|
nested_for_nb--;
|
||||||
|
for_body_tmp.append(yytext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yylloc->lines(1);
|
||||||
|
yylloc->step();
|
||||||
|
// Save old buffer state and location
|
||||||
|
context_stack.push(ScanContext(input, YY_CURRENT_BUFFER, *yylloc, for_body, for_body_loc));
|
||||||
|
|
||||||
|
for_body = for_body_tmp;
|
||||||
|
for_body_loc = for_body_loc_tmp;
|
||||||
|
|
||||||
|
iter_loop(driver, yylloc);
|
||||||
|
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<INITIAL><<EOF>> {
|
||||||
// Quit lexer if end of main file
|
// Quit lexer if end of main file
|
||||||
if (include_stack.empty())
|
if (context_stack.empty())
|
||||||
{
|
{
|
||||||
yyterminate();
|
yyterminate();
|
||||||
}
|
}
|
||||||
// Else restore old flex buffer
|
// Else clean current scanning context
|
||||||
/* We don't use yypop_buffer_state(), since it doesn't exist in
|
|
||||||
Flex 2.5.4 (see Flex 2.5.33 info file - section 11 - for code
|
|
||||||
example with yypop_buffer_state()) */
|
|
||||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||||
yy_switch_to_buffer(include_stack.top().first);
|
delete input;
|
||||||
// And restore old location
|
|
||||||
delete yylloc->begin.filename;
|
delete yylloc->begin.filename;
|
||||||
*yylloc = include_stack.top().second;
|
|
||||||
// Remove top of stack
|
// If we are not in a loop body, or if the loop has terminated, pop a context
|
||||||
include_stack.pop();
|
if (for_body.empty() || !iter_loop(driver, yylloc))
|
||||||
BEGIN(END_INCLUDE);
|
{
|
||||||
|
// Restore old context
|
||||||
|
input = context_stack.top().input;
|
||||||
|
yy_switch_to_buffer(context_stack.top().buffer);
|
||||||
|
*yylloc = context_stack.top().yylloc;
|
||||||
|
for_body = context_stack.top().for_body;
|
||||||
|
for_body_loc = context_stack.top().for_body_loc;
|
||||||
|
// Remove top of stack
|
||||||
|
context_stack.pop();
|
||||||
|
// Dump @line instruction
|
||||||
|
output_line(yylloc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore \r, because under Cygwin, outputting \n automatically adds another \r */
|
/* Ignore \r, because under Cygwin, outputting \n automatically adds another \r */
|
||||||
|
@ -171,10 +218,32 @@ typedef Macro::parser::token token;
|
||||||
%%
|
%%
|
||||||
|
|
||||||
MacroFlex::MacroFlex(istream* in, ostream* out)
|
MacroFlex::MacroFlex(istream* in, ostream* out)
|
||||||
: MacroFlexLexer(in, out)
|
: MacroFlexLexer(in, out), input(in), reading_for_statement(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MacroFlex::output_line(Macro::parser::location_type *yylloc)
|
||||||
|
{
|
||||||
|
*yyout << endl << "@line \"" << *yylloc->begin.filename << "\" "
|
||||||
|
<< yylloc->begin.line << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MacroFlex::iter_loop(MacroDriver &driver, Macro::parser::location_type *yylloc)
|
||||||
|
{
|
||||||
|
if (!driver.iter_loop())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
input = new stringstream(for_body);
|
||||||
|
*yylloc = for_body_loc;
|
||||||
|
yylloc->begin.filename = yylloc->end.filename = new string(*for_body_loc.begin.filename);
|
||||||
|
output_line(yylloc);
|
||||||
|
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* This implementation of MacroFlexLexer::yylex() is required to fill the
|
/* This implementation of MacroFlexLexer::yylex() is required to fill the
|
||||||
* vtable of the class MacroFlexLexer. We define the scanner's main yylex
|
* vtable of the class MacroFlexLexer. We define the scanner's main yylex
|
||||||
* function via YY_DECL to reside in the MacroFlex class instead. */
|
* function via YY_DECL to reside in the MacroFlex class instead. */
|
||||||
|
|
|
@ -17,109 +17,114 @@
|
||||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MacroValue.hh"
|
#include "MacroDriver.hh"
|
||||||
|
|
||||||
|
MacroValue::MacroValue(MacroDriver &driver_arg) : driver(driver_arg)
|
||||||
|
{
|
||||||
|
driver.values.insert(this);
|
||||||
|
}
|
||||||
|
|
||||||
MacroValue::~MacroValue()
|
MacroValue::~MacroValue()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator+() const throw (TypeError)
|
MacroValue::operator+() const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Unary operator + does not exist for this type");
|
throw TypeError("Unary operator + does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator-(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator-(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator - does not exist for this type");
|
throw TypeError("Operator - does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator-() const throw (TypeError)
|
MacroValue::operator-() const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Unary operator - does not exist for this type");
|
throw TypeError("Unary operator - does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator*(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator*(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator * does not exist for this type");
|
throw TypeError("Operator * does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator/(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator/(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator / does not exist for this type");
|
throw TypeError("Operator / does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator<(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator<(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator < does not exist for this type");
|
throw TypeError("Operator < does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator>(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator>(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator > does not exist for this type");
|
throw TypeError("Operator > does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator<=(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator<=(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator <= does not exist for this type");
|
throw TypeError("Operator <= does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator>=(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator>=(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator >= does not exist for this type");
|
throw TypeError("Operator >= does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator&&(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator&&(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator && does not exist for this type");
|
throw TypeError("Operator && does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator||(const MacroValue &mv) const throw (TypeError)
|
MacroValue::operator||(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator || does not exist for this type");
|
throw TypeError("Operator || does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator!() const throw (TypeError)
|
MacroValue::operator!() const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator ! does not exist for this type");
|
throw TypeError("Operator ! does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
MacroValue::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
||||||
{
|
{
|
||||||
throw TypeError("Operator [] does not exist for this type");
|
throw TypeError("Operator [] does not exist for this type");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::append(const MacroValue &mv) const throw (TypeError)
|
MacroValue::append(const MacroValue *mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
|
throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::new_base_value(int i)
|
MacroValue::new_base_value(MacroDriver &driver, int i)
|
||||||
{
|
{
|
||||||
return new IntMV(i);
|
return new IntMV(driver, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
MacroValue::new_base_value(const string &s)
|
MacroValue::new_base_value(MacroDriver &driver, const string &s)
|
||||||
{
|
{
|
||||||
return new StringMV(s);
|
return new StringMV(driver, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntMV::IntMV(int value_arg) : value(value_arg)
|
IntMV::IntMV(MacroDriver &driver, int value_arg) : MacroValue(driver), value(value_arg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,132 +132,132 @@ IntMV::~IntMV()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator+(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator+(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of + operator");
|
throw TypeError("Type mismatch for operands of + operator");
|
||||||
return new IntMV(value + mv2->value);
|
return new IntMV(driver, value + mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator+() const throw (TypeError)
|
IntMV::operator+() const throw (TypeError)
|
||||||
{
|
{
|
||||||
return clone();
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator-(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator-(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of - operator");
|
throw TypeError("Type mismatch for operands of - operator");
|
||||||
return new IntMV(value - mv2->value);
|
return new IntMV(driver, value - mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator-() const throw (TypeError)
|
IntMV::operator-() const throw (TypeError)
|
||||||
{
|
{
|
||||||
return new IntMV(-value);
|
return new IntMV(driver, -value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator*(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator*(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of * operator");
|
throw TypeError("Type mismatch for operands of * operator");
|
||||||
return new IntMV(value * mv2->value);
|
return new IntMV(driver, value * mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator/(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator/(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of / operator");
|
throw TypeError("Type mismatch for operands of / operator");
|
||||||
return new IntMV(value / mv2->value);
|
return new IntMV(driver, value / mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator<(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator<(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of < operator");
|
throw TypeError("Type mismatch for operands of < operator");
|
||||||
return new IntMV(value < mv2->value);
|
return new IntMV(driver, value < mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator>(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator>(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of > operator");
|
throw TypeError("Type mismatch for operands of > operator");
|
||||||
return new IntMV(value > mv2->value);
|
return new IntMV(driver, value > mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator<=(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator<=(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of <= operator");
|
throw TypeError("Type mismatch for operands of <= operator");
|
||||||
return new IntMV(value <= mv2->value);
|
return new IntMV(driver, value <= mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator>=(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator>=(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of >= operator");
|
throw TypeError("Type mismatch for operands of >= operator");
|
||||||
return new IntMV(value >= mv2->value);
|
return new IntMV(driver, value >= mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator==(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator==(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
return new IntMV(0);
|
return new IntMV(driver, 0);
|
||||||
else
|
else
|
||||||
return new IntMV(value == mv2->value);
|
return new IntMV(driver, value == mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator!=(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator!=(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
return new IntMV(1);
|
return new IntMV(driver, 1);
|
||||||
else
|
else
|
||||||
return new IntMV(value != mv2->value);
|
return new IntMV(driver, value != mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator&&(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator&&(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of && operator");
|
throw TypeError("Type mismatch for operands of && operator");
|
||||||
return new IntMV(value && mv2->value);
|
return new IntMV(driver, value && mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator||(const MacroValue &mv) const throw (TypeError)
|
IntMV::operator||(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of || operator");
|
throw TypeError("Type mismatch for operands of || operator");
|
||||||
return new IntMV(value || mv2->value);
|
return new IntMV(driver, value || mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::operator!() const throw (TypeError)
|
IntMV::operator!() const throw (TypeError)
|
||||||
{
|
{
|
||||||
return new IntMV(!value);
|
return new IntMV(driver, !value);
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
|
@ -263,37 +268,31 @@ IntMV::toString() const
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::clone() const
|
|
||||||
{
|
|
||||||
return new IntMV(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
MacroValue *
|
|
||||||
IntMV::toArray() const
|
IntMV::toArray() const
|
||||||
{
|
{
|
||||||
vector<int> v;
|
vector<int> v;
|
||||||
v.push_back(value);
|
v.push_back(value);
|
||||||
return new ArrayMV<int>(v);
|
return new ArrayMV<int>(driver, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::append(const MacroValue &array) const throw (TypeError)
|
IntMV::append(const MacroValue *array) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(&array);
|
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(array);
|
||||||
if (array2 == NULL)
|
if (array2 == NULL)
|
||||||
throw TypeError("Type mismatch for append operation");
|
throw TypeError("Type mismatch for append operation");
|
||||||
|
|
||||||
vector<int> v(array2->values);
|
vector<int> v(array2->values);
|
||||||
v.push_back(value);
|
v.push_back(value);
|
||||||
return new ArrayMV<int>(v);
|
return new ArrayMV<int>(driver, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
IntMV::new_range(const MacroValue &mv1, const MacroValue &mv2) throw (TypeError)
|
IntMV::new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError)
|
||||||
{
|
{
|
||||||
const IntMV *mv1i = dynamic_cast<const IntMV *>(&mv1);
|
const IntMV *mv1i = dynamic_cast<const IntMV *>(mv1);
|
||||||
const IntMV *mv2i = dynamic_cast<const IntMV *>(&mv2);
|
const IntMV *mv2i = dynamic_cast<const IntMV *>(mv2);
|
||||||
if (mv1i == NULL || mv2i == NULL)
|
if (mv1i == NULL || mv2i == NULL)
|
||||||
throw TypeError("Arguments of range operator (:) must be integers");
|
throw TypeError("Arguments of range operator (:) must be integers");
|
||||||
|
|
||||||
|
@ -309,10 +308,11 @@ IntMV::new_range(const MacroValue &mv1, const MacroValue &mv2) throw (TypeError)
|
||||||
}
|
}
|
||||||
for(; v1 <= v2; v1++)
|
for(; v1 <= v2; v1++)
|
||||||
result.push_back(v1);
|
result.push_back(v1);
|
||||||
return new ArrayMV<int>(result);
|
return new ArrayMV<int>(driver, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringMV::StringMV(const string &value_arg) : value(value_arg)
|
StringMV::StringMV(MacroDriver &driver, const string &value_arg)
|
||||||
|
: MacroValue(driver), value(value_arg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,36 +320,36 @@ StringMV::~StringMV()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
StringMV::operator+(const MacroValue &mv) const throw (TypeError)
|
StringMV::operator+(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
throw TypeError("Type mismatch for operands of + operator");
|
throw TypeError("Type mismatch for operands of + operator");
|
||||||
return new StringMV(value + mv2->value);
|
return new StringMV(driver, value + mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
StringMV::operator==(const MacroValue &mv) const throw (TypeError)
|
StringMV::operator==(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
return new IntMV(0);
|
return new IntMV(driver, 0);
|
||||||
else
|
else
|
||||||
return new IntMV(value == mv2->value);
|
return new IntMV(driver, value == mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
StringMV::operator!=(const MacroValue &mv) const throw (TypeError)
|
StringMV::operator!=(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
return new IntMV(1);
|
return new IntMV(driver, 1);
|
||||||
else
|
else
|
||||||
return new IntMV(value != mv2->value);
|
return new IntMV(driver, value != mv2->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
StringMV::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
StringMV::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
||||||
{
|
{
|
||||||
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
|
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
|
||||||
|
@ -364,7 +364,7 @@ StringMV::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsEr
|
||||||
char c = value.at(*it - 1);
|
char c = value.at(*it - 1);
|
||||||
result.append(&c);
|
result.append(&c);
|
||||||
}
|
}
|
||||||
return new StringMV(result);
|
return new StringMV(driver, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
|
@ -373,28 +373,22 @@ StringMV::toString() const
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
StringMV::clone() const
|
|
||||||
{
|
|
||||||
return new StringMV(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
MacroValue *
|
|
||||||
StringMV::toArray() const
|
StringMV::toArray() const
|
||||||
{
|
{
|
||||||
vector<string> v;
|
vector<string> v;
|
||||||
v.push_back(value);
|
v.push_back(value);
|
||||||
return new ArrayMV<string>(v);
|
return new ArrayMV<string>(driver, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
StringMV::append(const MacroValue &array) const throw (TypeError)
|
StringMV::append(const MacroValue *array) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(&array);
|
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(array);
|
||||||
if (array2 == NULL)
|
if (array2 == NULL)
|
||||||
throw TypeError("Type mismatch for append operation");
|
throw TypeError("Type mismatch for append operation");
|
||||||
|
|
||||||
vector<string> v(array2->values);
|
vector<string> v(array2->values);
|
||||||
v.push_back(value);
|
v.push_back(value);
|
||||||
return new ArrayMV<string>(v);
|
return new ArrayMV<string>(driver, v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,14 @@ using namespace std;
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
class MacroDriver;
|
||||||
|
|
||||||
//! Base class for representing values in macro language
|
//! Base class for representing values in macro language
|
||||||
class MacroValue
|
class MacroValue
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
//! Reference to enclosing MacroDriver
|
||||||
|
MacroDriver &driver;
|
||||||
public:
|
public:
|
||||||
//! Exception thrown when type error occurs in macro language
|
//! Exception thrown when type error occurs in macro language
|
||||||
class TypeError
|
class TypeError
|
||||||
|
@ -41,72 +46,59 @@ public:
|
||||||
class OutOfBoundsError
|
class OutOfBoundsError
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
MacroValue(MacroDriver &driver_arg);
|
||||||
virtual ~MacroValue();
|
virtual ~MacroValue();
|
||||||
//! Applies + operator
|
//! Applies + operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0;
|
||||||
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0;
|
|
||||||
//! Applies unary + operator
|
//! Applies unary + operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator+() const throw (TypeError);
|
||||||
virtual MacroValue *operator+() const throw (TypeError);
|
|
||||||
//! Applies - operator
|
//! Applies - operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Applies unary - operator
|
//! Applies unary - operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator-() const throw (TypeError);
|
||||||
virtual MacroValue *operator-() const throw (TypeError);
|
|
||||||
//! Applies * operator
|
//! Applies * operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Applies / operator
|
//! Applies / operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Less comparison
|
//! Less comparison
|
||||||
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
|
/*! Returns an IntMV, equal to 0 or 1 */
|
||||||
virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
|
||||||
//! Greater comparision
|
//! Greater comparision
|
||||||
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
|
/*! Returns an IntMV, equal to 0 or 1 */
|
||||||
virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
|
||||||
//! Less or equal comparison
|
//! Less or equal comparison
|
||||||
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
|
/*! Returns an IntMV, equal to 0 or 1 */
|
||||||
virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
|
||||||
//! Greater or equal comparison
|
//! Greater or equal comparison
|
||||||
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
|
/*! Returns an IntMV, equal to 0 or 1 */
|
||||||
virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
|
||||||
//! Equal comparison
|
//! Equal comparison
|
||||||
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
|
/*! Returns an IntMV, equal to 0 or 1 */
|
||||||
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0;
|
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0;
|
||||||
//! Not equal comparison
|
//! Not equal comparison
|
||||||
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
|
/*! Returns an IntMV, equal to 0 or 1 */
|
||||||
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0;
|
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0;
|
||||||
//! Applies && operator
|
//! Applies && operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Applies || operator
|
//! Applies || operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Applies unary ! operator
|
//! Applies unary ! operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator!() const throw (TypeError);
|
||||||
virtual MacroValue *operator!() const throw (TypeError);
|
|
||||||
//! Applies [] operator
|
//! Applies [] operator
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
||||||
virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
|
||||||
//! Converts value to string
|
//! Converts value to string
|
||||||
virtual string toString() const = 0;
|
virtual string toString() const = 0;
|
||||||
//! Clones value
|
|
||||||
/*! Returns a newly allocated value */
|
|
||||||
virtual MacroValue *clone() const = 0;
|
|
||||||
//! Converts value to array form
|
//! Converts value to array form
|
||||||
/*! Returns a newly allocated array value */
|
virtual const MacroValue *toArray() const = 0;
|
||||||
virtual MacroValue *toArray() const = 0;
|
|
||||||
//! Appends value at the end of an array
|
//! Appends value at the end of an array
|
||||||
/*! The first argument must be an array. Returns a newly allocated array. */
|
/*! The first argument must be an array. */
|
||||||
virtual MacroValue *append(const MacroValue &array) const throw (TypeError);
|
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
|
||||||
//! Returns a new IntMV
|
//! Returns a new IntMV
|
||||||
/*! Necessary for ArrayMV::operator[] (template issue) */
|
/*! Necessary for ArrayMV::operator[] (template issue) */
|
||||||
static MacroValue *new_base_value(int i);
|
static const MacroValue *new_base_value(MacroDriver &driver, int i);
|
||||||
//! Returns a new StringMV
|
//! Returns a new StringMV
|
||||||
/*! Necessary for ArrayMV::operator[] (template issue) */
|
/*! Necessary for ArrayMV::operator[] (template issue) */
|
||||||
static MacroValue *new_base_value(const string &s);
|
static const MacroValue *new_base_value(MacroDriver &driver, const string &s);
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Represents an integer value in macro language
|
//! Represents an integer value in macro language
|
||||||
|
@ -115,57 +107,48 @@ class IntMV : public MacroValue
|
||||||
friend class StringMV;
|
friend class StringMV;
|
||||||
private:
|
private:
|
||||||
//! Underlying integer value
|
//! Underlying integer value
|
||||||
int value;
|
const int value;
|
||||||
public:
|
public:
|
||||||
IntMV(int value_arg);
|
IntMV(MacroDriver &driver, int value_arg);
|
||||||
virtual ~IntMV();
|
virtual ~IntMV();
|
||||||
//! Computes arithmetic addition
|
//! Computes arithmetic addition
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Unary plus
|
//! Unary plus
|
||||||
/*! Returns a clone of itself */
|
/*! Returns itself */
|
||||||
virtual MacroValue *operator+() const throw (TypeError);
|
virtual const MacroValue *operator+() const throw (TypeError);
|
||||||
//! Computes arithmetic substraction
|
//! Computes arithmetic substraction
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Computes opposite
|
//! Computes opposite
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator-() const throw (TypeError);
|
||||||
virtual MacroValue *operator-() const throw (TypeError);
|
|
||||||
//! Computes arithmetic multiplication
|
//! Computes arithmetic multiplication
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Computes arithmetic division
|
//! Computes arithmetic division
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Computes logical and
|
//! Computes logical and
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Computes logical or
|
//! Computes logical or
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Computes logical negation
|
//! Computes logical negation
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator!() const throw (TypeError);
|
||||||
virtual MacroValue *operator!() const throw (TypeError);
|
|
||||||
virtual string toString() const;
|
virtual string toString() const;
|
||||||
virtual MacroValue *clone() const;
|
|
||||||
//! Converts value to array form
|
//! Converts value to array form
|
||||||
/*! Returns a newly allocated integer array containing a single value */
|
/*! Returns an integer array containing a single value */
|
||||||
virtual MacroValue *toArray() const;
|
virtual const MacroValue *toArray() const;
|
||||||
//! Appends value at the end of an array
|
//! Appends value at the end of an array
|
||||||
/*! The first argument must be an integer array. Returns a newly allocated integer array. */
|
/*! The first argument must be an integer array. */
|
||||||
virtual MacroValue *append(const MacroValue &array) const throw (TypeError);
|
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
|
||||||
//! Creates a integer range
|
//! Creates a integer range
|
||||||
/*! Arguments must be of type IntMV.
|
/*! Arguments must be of type IntMV.
|
||||||
Returns a newly allocated integer array containing all integers between mv1 and mv2.
|
Returns an integer array containing all integers between mv1 and mv2.
|
||||||
If mv2 < mv1, constructs the range in decreasing order.
|
If mv2 < mv1, constructs the range in decreasing order.
|
||||||
*/
|
*/
|
||||||
static MacroValue *new_range(const MacroValue &mv1, const MacroValue &mv2) throw (TypeError);
|
static const MacroValue *new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError);
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Represents a string value in macro language
|
//! Represents a string value in macro language
|
||||||
|
@ -173,28 +156,25 @@ class StringMV : public MacroValue
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
//! Underlying string value
|
//! Underlying string value
|
||||||
string value;
|
const string value;
|
||||||
public:
|
public:
|
||||||
StringMV(const string &value_arg);
|
StringMV(MacroDriver &driver, const string &value_arg);
|
||||||
virtual ~StringMV();
|
virtual ~StringMV();
|
||||||
//! Computes string concatenation
|
//! Computes string concatenation
|
||||||
/*! Returns a newly allocated value */
|
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Subscripting operator
|
//! Subscripting operator
|
||||||
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
|
/*! Argument must be an ArrayMV<int>. Indexes begin at 1. Returns a StringMV. */
|
||||||
Returns a newly allocated string. */
|
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
||||||
virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
|
||||||
//! Returns underlying string value
|
//! Returns underlying string value
|
||||||
virtual string toString() const;
|
virtual string toString() const;
|
||||||
virtual MacroValue *clone() const;
|
|
||||||
//! Converts value to array form
|
//! Converts value to array form
|
||||||
/*! Returns a newly allocated string array containing a single value */
|
/*! Returns a string array containing a single value */
|
||||||
virtual MacroValue *toArray() const;
|
virtual const MacroValue *toArray() const;
|
||||||
//! Appends value at the end of an array
|
//! Appends value at the end of an array
|
||||||
/*! The first argument must be a string array. Returns a newly allocated string array. */
|
/*! The first argument must be a string array. Returns a string array. */
|
||||||
virtual MacroValue *append(const MacroValue &array) const throw (TypeError);
|
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Represents an array in macro language
|
//! Represents an array in macro language
|
||||||
|
@ -205,32 +185,31 @@ class ArrayMV : public MacroValue
|
||||||
friend class IntMV;
|
friend class IntMV;
|
||||||
friend class StringMV;
|
friend class StringMV;
|
||||||
friend class ArrayMV<string>; // Necessary for operator[] to access values of integer array when subscripting a string array
|
friend class ArrayMV<string>; // Necessary for operator[] to access values of integer array when subscripting a string array
|
||||||
|
friend class MacroDriver;
|
||||||
private:
|
private:
|
||||||
//! Underlying vector
|
//! Underlying vector
|
||||||
vector<T> values;
|
const vector<T> values;
|
||||||
public:
|
public:
|
||||||
ArrayMV(const vector<T> &values_arg);
|
ArrayMV(MacroDriver &driver, const vector<T> &values_arg);
|
||||||
virtual ~ArrayMV();
|
virtual ~ArrayMV();
|
||||||
//! Computes array concatenation
|
//! Computes array concatenation
|
||||||
/*! Both array must be of same type
|
/*! Both array must be of same type */
|
||||||
Returns a newly allocated array */
|
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
|
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
||||||
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
|
|
||||||
//! Subscripting operator
|
//! Subscripting operator
|
||||||
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
|
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
|
||||||
If argument is a one-element array, returns a newly-allocated IntMV or String.
|
If argument is a one-element array, returns an IntMV or StringMV.
|
||||||
Otherwise returns a newly allocated array. */
|
Otherwise returns an array. */
|
||||||
virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
|
||||||
//! Returns a string containing the concatenation of string representations of elements
|
//! Returns a string containing the concatenation of string representations of elements
|
||||||
virtual string toString() const;
|
virtual string toString() const;
|
||||||
virtual MacroValue *clone() const;
|
//! Returns itself
|
||||||
//! Returns a clone of itself
|
virtual const MacroValue *toArray() const;
|
||||||
virtual MacroValue *toArray() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ArrayMV<T>::ArrayMV(const vector<T> &values_arg) : values(values_arg)
|
ArrayMV<T>::ArrayMV(MacroDriver &driver, const vector<T> &values_arg) : MacroValue(driver), values(values_arg)
|
||||||
{
|
{
|
||||||
if (values.size() == 0)
|
if (values.size() == 0)
|
||||||
throw "Empty arrays forbidden";
|
throw "Empty arrays forbidden";
|
||||||
|
@ -242,7 +221,7 @@ ArrayMV<T>::~ArrayMV()
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
ArrayMV<T>::operator+(const MacroValue &mv) const throw (TypeError)
|
ArrayMV<T>::operator+(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
||||||
|
@ -251,33 +230,33 @@ ArrayMV<T>::operator+(const MacroValue &mv) const throw (TypeError)
|
||||||
|
|
||||||
vector<T> values_copy(values);
|
vector<T> values_copy(values);
|
||||||
values_copy.insert(values_copy.end(), mv2->values.begin(), mv2->values.end());
|
values_copy.insert(values_copy.end(), mv2->values.begin(), mv2->values.end());
|
||||||
return new ArrayMV<T>(values_copy);
|
return new ArrayMV<T>(driver, values_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
ArrayMV<T>::operator==(const MacroValue &mv) const throw (TypeError)
|
ArrayMV<T>::operator==(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
return new IntMV(0);
|
return new IntMV(driver, 0);
|
||||||
else
|
else
|
||||||
return new IntMV(values == mv2->values);
|
return new IntMV(driver, values == mv2->values);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
ArrayMV<T>::operator!=(const MacroValue &mv) const throw (TypeError)
|
ArrayMV<T>::operator!=(const MacroValue &mv) const throw (TypeError)
|
||||||
{
|
{
|
||||||
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
|
||||||
if (mv2 == NULL)
|
if (mv2 == NULL)
|
||||||
return new IntMV(1);
|
return new IntMV(driver, 1);
|
||||||
else
|
else
|
||||||
return new IntMV(values != mv2->values);
|
return new IntMV(driver, values != mv2->values);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
|
||||||
{
|
{
|
||||||
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
|
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
|
||||||
|
@ -293,9 +272,9 @@ ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError, OutOfBounds
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.size() > 1)
|
if (result.size() > 1)
|
||||||
return new ArrayMV<T>(result);
|
return new ArrayMV<T>(driver, result);
|
||||||
else
|
else
|
||||||
return MacroValue::new_base_value(result[0]);
|
return MacroValue::new_base_value(driver, result[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -310,17 +289,10 @@ ArrayMV<T>::toString() const
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MacroValue *
|
const MacroValue *
|
||||||
ArrayMV<T>::clone() const
|
|
||||||
{
|
|
||||||
return new ArrayMV<T>(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MacroValue *
|
|
||||||
ArrayMV<T>::toArray() const
|
ArrayMV<T>::toArray() const
|
||||||
{
|
{
|
||||||
return clone();
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue