v4 preprocessor/macro:

* added integer ranges
* added Doxygen documents for MacroValue and its subclass
* fixed string delimiter in macro language (it's double quote and not single)
* fixed problem with line count in presence of macro directives


git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@1714 ac1d8469-bf42-47a9-8791-bf33cf982152
issue#70
sebastien 2008-02-20 09:56:47 +00:00
parent e495078e8d
commit e56af01f04
4 changed files with 158 additions and 73 deletions

View File

@ -65,8 +65,8 @@ class MacroDriver;
#define yylex driver.lexer->lex
%}
%token DEFINE
%token LPAREN RPAREN LBRACKET RBRACKET COLON EQUAL EOL
%token DEFINE LINE
%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL
%token <int_val> INTEGER
%token <string_val> NAME STRING
@ -80,6 +80,8 @@ class MacroDriver;
%left UMINUS UPLUS EXCLAMATION
%left LBRACKET
%nonassoc COLON
%type <mv> expr array_expr
%%
@ -95,6 +97,8 @@ statement : expr
{ *driver.out_stream << $1->toString(); delete $1; }
| DEFINE NAME EQUAL expr
{ driver.env[*$2] = $4; delete $2; }
| LINE STRING INTEGER
/* Ignore @line declarations */
expr : INTEGER
{ $$ = new IntMV($1); }
@ -138,6 +142,8 @@ expr : INTEGER
{ $$ = (*$1)[*$3]; delete $1; delete $3; }
| LBRACKET array_expr RBRACKET
{ $$ = $2; }
| expr COLON expr
{ $$ = IntMV::new_range(*$1, *$3); delete $1; delete $3; }
;
array_expr : expr

View File

@ -62,9 +62,6 @@ typedef Macro::parser::token token;
yylloc->step();
%}
/* Ignore @line declarations, replace them by a blank line */
<INITIAL>^@line[^\r\n]*(\r)?\n { yylloc->lines(1); yylloc->step(); *yyout << endl; }
<INITIAL>^@include[ \t]+\" BEGIN(INCLUDE);
<INCLUDE>[^\"\r\n]* {
@ -102,7 +99,7 @@ typedef Macro::parser::token token;
<MACRO>[ \t\r\f]+ { yylloc->step(); }
<MACRO>@ { BEGIN(INITIAL); return token::EOL; }
<MACRO>\n { BEGIN(INITIAL); return token::EOL; }
<MACRO>\n { BEGIN(INITIAL); yylloc->lines(1); yylloc->step(); *yyout << endl; return token::EOL; }
<MACRO>[0-9]+ {
yylval->int_val = atoi(yytext);
@ -129,12 +126,13 @@ typedef Macro::parser::token token;
<MACRO>[*] { return token::TIMES; }
<MACRO>[/] { return token::DIVIDE; }
<MACRO>\'[^\']*\' {
<MACRO>\"[^\"]*\" {
yylval->string_val = new string(yytext + 1);
yylval->string_val->resize(yylval->string_val->length() - 1);
return token::STRING;
}
<MACRO>line { return token::LINE; }
<MACRO>define { return token::DEFINE; }
<MACRO>[A-Za-z_][A-Za-z0-9_]* {

View File

@ -95,6 +95,12 @@ MacroValue::operator[](const MacroValue &mv) const throw (TypeError)
throw TypeError("Operator [] does not exist for this type");
}
MacroValue *
MacroValue::append(const MacroValue &mv) const
{
throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
}
IntMV::IntMV(int value_arg) : value(value_arg)
{
}
@ -109,8 +115,7 @@ IntMV::operator+(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of + operator");
else
return new IntMV(value + mv2->value);
return new IntMV(value + mv2->value);
}
MacroValue *
@ -119,8 +124,7 @@ IntMV::operator-(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of - operator");
else
return new IntMV(value - mv2->value);
return new IntMV(value - mv2->value);
}
MacroValue *
@ -135,8 +139,7 @@ IntMV::operator*(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of * operator");
else
return new IntMV(value * mv2->value);
return new IntMV(value * mv2->value);
}
MacroValue *
@ -145,8 +148,7 @@ IntMV::operator/(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of / operator");
else
return new IntMV(value / mv2->value);
return new IntMV(value / mv2->value);
}
MacroValue *
@ -155,8 +157,7 @@ IntMV::operator<(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of < operator");
else
return new IntMV(value < mv2->value);
return new IntMV(value < mv2->value);
}
MacroValue *
@ -165,8 +166,7 @@ IntMV::operator>(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of > operator");
else
return new IntMV(value > mv2->value);
return new IntMV(value > mv2->value);
}
MacroValue *
@ -175,8 +175,7 @@ IntMV::operator<=(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of <= operator");
else
return new IntMV(value <= mv2->value);
return new IntMV(value <= mv2->value);
}
MacroValue *
@ -185,8 +184,7 @@ IntMV::operator>=(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of >= operator");
else
return new IntMV(value >= mv2->value);
return new IntMV(value >= mv2->value);
}
MacroValue *
@ -194,7 +192,7 @@ IntMV::operator==(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw new IntMV(0);
return new IntMV(0);
else
return new IntMV(value == mv2->value);
}
@ -204,7 +202,7 @@ IntMV::operator!=(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw new IntMV(1);
return new IntMV(1);
else
return new IntMV(value != mv2->value);
}
@ -215,8 +213,7 @@ IntMV::operator&&(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of && operator");
else
return new IntMV(value && mv2->value);
return new IntMV(value && mv2->value);
}
MacroValue *
@ -225,8 +222,7 @@ IntMV::operator||(const MacroValue &mv) const throw (TypeError)
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of || operator");
else
return new IntMV(value || mv2->value);
return new IntMV(value || mv2->value);
}
MacroValue *
@ -263,12 +259,33 @@ IntMV::append(const MacroValue &array) const
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(&array);
if (array2 == NULL)
throw TypeError("Type mismatch for append operation");
else
vector<int> v(array2->values);
v.push_back(value);
return new ArrayMV<int>(v);
}
MacroValue *
IntMV::new_range(const MacroValue &mv1, const MacroValue &mv2) throw (TypeError)
{
const IntMV *mv1i = dynamic_cast<const IntMV *>(&mv1);
const IntMV *mv2i = dynamic_cast<const IntMV *>(&mv2);
if (mv1i == NULL || mv2i == NULL)
throw TypeError("Arguments of range operator (:) must be integers");
int v1 = mv1i->value;
int v2 = mv2i->value;
vector<int> result;
if (v2 < v1)
{
vector<int> v(array2->values);
v.push_back(value);
return new ArrayMV<int>(v);
int x = v2;
v2 = v1;
v1 = x;
}
for(; v1 <= v2; v1++)
result.push_back(v1);
return new ArrayMV<int>(result);
}
StringMV::StringMV(const string &value_arg) : value(value_arg)
@ -285,8 +302,7 @@ StringMV::operator+(const MacroValue &mv) const throw (TypeError)
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of + operator");
else
return new StringMV(value + mv2->value);
return new StringMV(value + mv2->value);
}
MacroValue *
@ -294,7 +310,7 @@ StringMV::operator==(const MacroValue &mv) const throw (TypeError)
{
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
if (mv2 == NULL)
throw new IntMV(0);
return new IntMV(0);
else
return new IntMV(value == mv2->value);
}
@ -304,7 +320,7 @@ StringMV::operator!=(const MacroValue &mv) const throw (TypeError)
{
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
if (mv2 == NULL)
throw new IntMV(1);
return new IntMV(1);
else
return new IntMV(value != mv2->value);
}
@ -351,10 +367,8 @@ StringMV::append(const MacroValue &array) const
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(&array);
if (array2 == NULL)
throw TypeError("Type mismatch for append operation");
else
{
vector<string> v(array2->values);
v.push_back(value);
return new ArrayMV<string>(v);
}
vector<string> v(array2->values);
v.push_back(value);
return new ArrayMV<string>(v);
}

View File

@ -26,9 +26,11 @@ using namespace std;
#include <vector>
#include <sstream>
//! Base class for representing values in macro language
class MacroValue
{
public:
//! Exception thrown when type error occurs in macro language
class TypeError
{
public:
@ -36,39 +38,88 @@ public:
TypeError(const string &message_arg) : message(message_arg) {};
};
virtual ~MacroValue();
//! Applies + operator
/*! Returns a newly allocated value */
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0;
//! Applies - operator
/*! Returns a newly allocated value */
virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
//! Applies unary - operator
/*! Returns a newly allocated value */
virtual MacroValue *operator-() const throw (TypeError);
//! Applies * operator
/*! Returns a newly allocated value */
virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
//! Applies / operator
/*! Returns a newly allocated value */
virtual MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
//! Less comparison
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
//! Greater comparision
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
//! Less or equal comparison
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
//! Greater or equal comparison
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
//! Equal comparison
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0;
//! Not equal comparison
/*! Returns a newly allocated IntMV, equal to 0 or 1 */
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0;
//! Applies && operator
/*! Returns a newly allocated value */
virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
//! Applies || operator
/*! Returns a newly allocated value */
virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
//! Applies unary ! operator
/*! Returns a newly allocated value */
virtual MacroValue *operator!() const throw (TypeError);
//! Applies [] operator
/*! Returns a newly allocated value */
virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError);
//! Converts value to string
virtual string toString() const = 0;
//! Clones value
/*! Returns a newly allocated value */
virtual MacroValue *clone() const = 0;
//! Converts value to array form
/*! Returns a newly allocated array value */
virtual MacroValue *toArray() const = 0;
virtual MacroValue *append(const MacroValue &array) const = 0;
//! Appends value at the end of an array
/*! The first argument must be an array. Returns a newly allocated array. */
virtual MacroValue *append(const MacroValue &array) const;
};
//! Represents an integer value in macro language
class IntMV : public MacroValue
{
friend class StringMV;
private:
//! Underlying integer value
int value;
public:
IntMV(int value_arg);
virtual ~IntMV();
//! Computes arithmetic addition
/*! Returns a newly allocated value */
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
//! Computes arithmetic substraction
/*! Returns a newly allocated value */
virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
//! Computes opposite
/*! Returns a newly allocated value */
virtual MacroValue *operator-() const throw (TypeError);
//! Computes arithmetic multiplication
/*! Returns a newly allocated value */
virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
//! Computes arithmetic division
/*! Returns a newly allocated value */
virtual MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
@ -76,41 +127,63 @@ public:
virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
//! Computes logical and
/*! Returns a newly allocated value */
virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
//! Computes logical or
/*! Returns a newly allocated value */
virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
//! Computes logical negation
/*! Returns a newly allocated value */
virtual MacroValue *operator!() const throw (TypeError);
virtual string toString() const;
virtual MacroValue *clone() const;
//! Converts value to array form
/*! Returns a newly allocated integer array containing a single value */
virtual MacroValue *toArray() const;
//! Appends value at the end of an array
/*! The first argument must be an integer array. Returns a newly allocated integer array. */
virtual MacroValue *append(const MacroValue &array) const;
//! Creates a integer range
/*! Arguments must be of type IntMV.
Returns a newly allocated integer array containing all integers between mv1 and mv2.
If mv2 < mv1, constructs the range in decreasing order.
*/
static MacroValue *new_range(const MacroValue &mv1, const MacroValue &mv2) throw (TypeError);
};
//! Represents a string value in macro language
class StringMV : public MacroValue
{
private:
//! Underlying string value
string value;
public:
StringMV(const string &value_arg);
virtual ~StringMV();
//! Computes string concatenation
/*! Returns a newly allocated value */
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
// virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
// virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
// virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
// virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
//! Subscripting operator
/*!
Argument must be an ArrayMV<int>. Indexes begin at 1.
\todo Add bound error checking
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
Returns a newly allocated string.
\todo Add bound error checking
*/
virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError);
//! Returns underlying string value
virtual string toString() const;
virtual MacroValue *clone() const;
//! Converts value to array form
/*! Returns a newly allocated string array containing a single value */
virtual MacroValue *toArray() const;
//! Appends value at the end of an array
/*! The first argument must be a string array. Returns a newly allocated string array. */
virtual MacroValue *append(const MacroValue &array) const;
};
//! Represents an array in macro language
template<typename T>
class ArrayMV : public MacroValue
{
@ -118,23 +191,28 @@ class ArrayMV : public MacroValue
friend class StringMV;
friend class ArrayMV<string>; // Necessary for operator[] to access values of integer array when subscripting a string array
private:
//! Underlying vector
vector<T> values;
public:
ArrayMV(const vector<T> &values_arg);
virtual ~ArrayMV();
//! Computes array concatenation
/*! Both array must be of same type
Returns a newly allocated array */
virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
//! Subscripting operator
/*!
Argument must be an ArrayMV<int>. Indexes begin at 1.
\todo Add bound error checking
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
Returns a newly allocated array.
\todo Add bound error checking
*/
virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError);
//! Returns a string containing the concatenation of string representations of elements
virtual string toString() const;
virtual MacroValue *clone() const;
//! Returns itself
virtual MacroValue *toArray() const;
virtual MacroValue *append(const MacroValue &array) const;
};
template<typename T>
@ -154,14 +232,10 @@ ArrayMV<T>::operator+(const MacroValue &mv) const throw (TypeError)
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of + operator");
else
{
vector<T> values_copy(values);
values_copy.insert(values_copy.end(),
mv2->values.begin(),
mv2->values.end());
return new ArrayMV<T>(values_copy);
}
vector<T> values_copy(values);
values_copy.insert(values_copy.end(), mv2->values.begin(), mv2->values.end());
return new ArrayMV<T>(values_copy);
}
template<typename T>
@ -170,7 +244,7 @@ ArrayMV<T>::operator==(const MacroValue &mv) const throw (TypeError)
{
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
if (mv2 == NULL)
throw new IntMV(0);
return new IntMV(0);
else
return new IntMV(values == mv2->values);
}
@ -181,7 +255,7 @@ ArrayMV<T>::operator!=(const MacroValue &mv) const throw (TypeError)
{
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
if (mv2 == NULL)
throw new IntMV(1);
return new IntMV(1);
else
return new IntMV(values != mv2->values);
}
@ -225,11 +299,4 @@ ArrayMV<T>::toArray() const
return clone();
}
template<typename T>
MacroValue *
ArrayMV<T>::append(const MacroValue &mv) const
{
throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
}
#endif