Commit 045e20e2 authored by sebastien's avatar sebastien
Browse files

trunk preprocessor/macro: added new 'in' operator for testing membership of an array

git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@2300 ac1d8469-bf42-47a9-8791-bf33cf982152
parent 6a80037d
...@@ -85,6 +85,7 @@ class MacroDriver; ...@@ -85,6 +85,7 @@ class MacroDriver;
%left LOGICAL_OR %left LOGICAL_OR
%left LOGICAL_AND %left LOGICAL_AND
%left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL %left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL
%nonassoc IN
%nonassoc COLON %nonassoc COLON
%left PLUS MINUS %left PLUS MINUS
%left TIMES DIVIDE %left TIMES DIVIDE
...@@ -180,6 +181,8 @@ expr : INTEGER ...@@ -180,6 +181,8 @@ expr : INTEGER
{ $$ = $2; } { $$ = $2; }
| expr COLON expr | expr COLON expr
{ TYPERR_CATCH($$ = IntMV::new_range(driver, $1, $3), @$); } { TYPERR_CATCH($$ = IntMV::new_range(driver, $1, $3), @$); }
| expr IN expr
{ TYPERR_CATCH($$ = $1->in($3), @$); }
; ;
array_expr : expr array_expr : expr
......
...@@ -144,6 +144,7 @@ CONT \\\\ ...@@ -144,6 +144,7 @@ CONT \\\\
<STMT,EXPR>[-] { return token::MINUS; } <STMT,EXPR>[-] { return token::MINUS; }
<STMT,EXPR>[*] { return token::TIMES; } <STMT,EXPR>[*] { return token::TIMES; }
<STMT,EXPR>[/] { return token::DIVIDE; } <STMT,EXPR>[/] { return token::DIVIDE; }
<STMT,EXPR>in { return token::IN; }
<STMT,EXPR>\"[^\"]*\" { <STMT,EXPR>\"[^\"]*\" {
yylval->string_val = new string(yytext + 1); yylval->string_val = new string(yytext + 1);
...@@ -155,7 +156,6 @@ CONT \\\\ ...@@ -155,7 +156,6 @@ CONT \\\\
<STMT>define { return token::DEFINE; } <STMT>define { return token::DEFINE; }
<STMT>for { reading_for_statement = true; return token::FOR; } <STMT>for { reading_for_statement = true; return token::FOR; }
<STMT>in { return token::IN; }
<STMT>endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); } <STMT>endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); }
<STMT>if { reading_if_statement = true; return token::IF; } <STMT>if { reading_if_statement = true; return token::IF; }
......
...@@ -112,6 +112,12 @@ MacroValue::append(const MacroValue *mv) const throw (TypeError) ...@@ -112,6 +112,12 @@ 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.");
} }
const MacroValue *
MacroValue::in(const MacroValue *array) const throw (TypeError)
{
throw TypeError("First argument of 'in' operator cannot be an array");
}
const MacroValue * const MacroValue *
MacroValue::new_base_value(MacroDriver &driver, int i) MacroValue::new_base_value(MacroDriver &driver, int i)
{ {
...@@ -288,6 +294,25 @@ IntMV::append(const MacroValue *array) const throw (TypeError) ...@@ -288,6 +294,25 @@ IntMV::append(const MacroValue *array) const throw (TypeError)
return new ArrayMV<int>(driver, v); return new ArrayMV<int>(driver, v);
} }
const MacroValue *
IntMV::in(const MacroValue *array) const throw (TypeError)
{
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(array);
if (array2 == NULL)
throw TypeError("Type mismatch for 'in' operator");
int result = 0;
for(vector<int>::const_iterator it = array2->values.begin();
it != array2->values.end(); it++)
if (*it == value)
{
result = 1;
break;
}
return new IntMV(driver, result);
}
const MacroValue * const MacroValue *
IntMV::new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError) IntMV::new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError)
{ {
...@@ -392,3 +417,22 @@ StringMV::append(const MacroValue *array) const throw (TypeError) ...@@ -392,3 +417,22 @@ StringMV::append(const MacroValue *array) const throw (TypeError)
v.push_back(value); v.push_back(value);
return new ArrayMV<string>(driver, v); return new ArrayMV<string>(driver, v);
} }
const MacroValue *
StringMV::in(const MacroValue *array) const throw (TypeError)
{
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(array);
if (array2 == NULL)
throw TypeError("Type mismatch for 'in' operator");
int result = 0;
for(vector<string>::const_iterator it = array2->values.begin();
it != array2->values.end(); it++)
if (*it == value)
{
result = 1;
break;
}
return new IntMV(driver, result);
}
...@@ -91,8 +91,11 @@ public: ...@@ -91,8 +91,11 @@ public:
//! Converts value to array form //! Converts value to array form
virtual const MacroValue *toArray() const = 0; virtual const 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. */ /*! The argument must be an array. */
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError); virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
//! Applies "in" operator
/*! The argument must be an array. Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *in(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 const MacroValue *new_base_value(MacroDriver &driver, int i); static const MacroValue *new_base_value(MacroDriver &driver, int i);
...@@ -144,6 +147,7 @@ public: ...@@ -144,6 +147,7 @@ public:
//! Appends value at the end of an array //! Appends value at the end of an array
/*! The first argument must be an integer array. */ /*! The first argument must be an integer array. */
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError); virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
virtual const MacroValue *in(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 an integer array containing all integers between mv1 and mv2. Returns an integer array containing all integers between mv1 and mv2.
...@@ -177,6 +181,7 @@ public: ...@@ -177,6 +181,7 @@ public:
//! 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 string array. */ /*! The first argument must be a string array. Returns a string array. */
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError); virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
}; };
//! Represents an array in macro language //! Represents an array in macro language
......
Supports Markdown
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