From 666f93aa7770a5e840e2d1c803a5e33850060a64 Mon Sep 17 00:00:00 2001 From: sebastien Date: Tue, 19 Feb 2008 14:24:40 +0000 Subject: [PATCH] v4 preprocessor/macro: added handling of arrays git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@1711 ac1d8469-bf42-47a9-8791-bf33cf982152 --- preprocessor/macro/MacroBison.yy | 15 +++- preprocessor/macro/MacroFlex.ll | 4 + preprocessor/macro/MacroValue.cc | 74 +++++++++++++++- preprocessor/macro/MacroValue.hh | 147 ++++++++++++++++++++++++++----- 4 files changed, 215 insertions(+), 25 deletions(-) diff --git a/preprocessor/macro/MacroBison.yy b/preprocessor/macro/MacroBison.yy index 0addc52cb..64848d141 100644 --- a/preprocessor/macro/MacroBison.yy +++ b/preprocessor/macro/MacroBison.yy @@ -55,7 +55,7 @@ class MacroDriver; }; %{ -#include // Pour atoi() +#include // Pour atoi() #include "MacroDriver.hh" /* this "connects" the bison parser in the driver to the flex scanner class @@ -71,6 +71,7 @@ class MacroDriver; %token INTEGER %token NAME STRING +%left COMMA %left LOGICAL_OR %left LOGICAL_AND %left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL @@ -79,7 +80,7 @@ class MacroDriver; %left UMINUS UPLUS EXCLAMATION %left LBRACKET -%type expr +%type expr array_expr %% %start statement_list_or_nothing; @@ -133,10 +134,18 @@ expr : INTEGER { $$ = $2; } | EXCLAMATION expr { $$ = !*$2; delete $2; } - | expr LBRACKET expr RBRACKET + | expr LBRACKET array_expr RBRACKET { $$ = (*$1)[*$3]; delete $1; delete $3; } + | LBRACKET array_expr RBRACKET + { $$ = $2; } ; +array_expr : expr + { $$ = $1->toArray(); delete $1; } + | array_expr COMMA expr + { $$ = $3->append(*$1); delete $1; delete $3; } + ; + %% void diff --git a/preprocessor/macro/MacroFlex.ll b/preprocessor/macro/MacroFlex.ll index 8bdc68ccb..a1ba2ca97 100644 --- a/preprocessor/macro/MacroFlex.ll +++ b/preprocessor/macro/MacroFlex.ll @@ -113,6 +113,7 @@ typedef Macro::parser::token token; \[ { return token::LBRACKET; } \] { return token::RBRACKET; } : { return token::COLON; } +, { return token::COMMA; } = { return token::EQUAL; } [!] { return token::EXCLAMATION; } "||" { return token::LOGICAL_OR; } @@ -162,6 +163,9 @@ typedef Macro::parser::token token; BEGIN(END_INCLUDE); } + /* Ignore \r, because under Cygwin, outputting \n automatically adds another \r */ +[\r]+ { yylloc->step(); } + /* Copy everything else to output */ [\n]+ { yylloc->lines(yyleng); yylloc->step(); ECHO; } . { yylloc->step(); ECHO; } diff --git a/preprocessor/macro/MacroValue.cc b/preprocessor/macro/MacroValue.cc index aa137dfab..b8e0d0753 100644 --- a/preprocessor/macro/MacroValue.cc +++ b/preprocessor/macro/MacroValue.cc @@ -17,10 +17,12 @@ * along with Dynare. If not, see . */ -#include - #include "MacroValue.hh" +MacroValue::~MacroValue() +{ +} + MacroValue * MacroValue::operator-(const MacroValue &mv) const throw (TypeError) { @@ -97,6 +99,10 @@ IntMV::IntMV(int value_arg) : value(value_arg) { } +IntMV::~IntMV() +{ +} + MacroValue * IntMV::operator+(const MacroValue &mv) const throw (TypeError) { @@ -243,10 +249,36 @@ IntMV::clone() const return new IntMV(value); } +MacroValue * +IntMV::toArray() const +{ + vector v; + v.push_back(value); + return new ArrayMV(v); +} + +MacroValue * +IntMV::append(const MacroValue &array) const +{ + const ArrayMV *array2 = dynamic_cast *>(&array); + if (array2 == NULL) + throw TypeError("Type mismatch for append operation"); + else + { + vector v(array2->values); + v.push_back(value); + return new ArrayMV(v); + } +} + StringMV::StringMV(const string &value_arg) : value(value_arg) { } +StringMV::~StringMV() +{ +} + MacroValue * StringMV::operator+(const MacroValue &mv) const throw (TypeError) { @@ -277,6 +309,22 @@ StringMV::operator!=(const MacroValue &mv) const throw (TypeError) return new IntMV(value != mv2->value); } +MacroValue * +StringMV::operator[](const MacroValue &mv) const throw (TypeError) +{ + const ArrayMV *mv2 = dynamic_cast *>(&mv); + if (mv2 == NULL) + throw TypeError("Expression inside [] must be an integer array"); + string result; + for(vector::const_iterator it = mv2->values.begin(); + it != mv2->values.end(); it++) + { + char c = value.at(*it - 1); + result.append(&c); + } + return new StringMV(result); +} + string StringMV::toString() const { @@ -288,3 +336,25 @@ StringMV::clone() const { return new StringMV(value); } + +MacroValue * +StringMV::toArray() const +{ + vector v; + v.push_back(value); + return new ArrayMV(v); +} + +MacroValue * +StringMV::append(const MacroValue &array) const +{ + const ArrayMV *array2 = dynamic_cast *>(&array); + if (array2 == NULL) + throw TypeError("Type mismatch for append operation"); + else + { + vector v(array2->values); + v.push_back(value); + return new ArrayMV(v); + } +} diff --git a/preprocessor/macro/MacroValue.hh b/preprocessor/macro/MacroValue.hh index 31e7687c4..cdac2db5e 100644 --- a/preprocessor/macro/MacroValue.hh +++ b/preprocessor/macro/MacroValue.hh @@ -24,6 +24,7 @@ using namespace std; #include #include +#include class MacroValue { @@ -34,6 +35,7 @@ public: const string message; TypeError(const string &message_arg) : message(message_arg) {}; }; + virtual ~MacroValue(); virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0; virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError); virtual MacroValue *operator-() const throw (TypeError); @@ -51,14 +53,18 @@ public: virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); virtual string toString() const = 0; virtual MacroValue *clone() const = 0; + virtual MacroValue *toArray() const = 0; + virtual MacroValue *append(const MacroValue &array) const = 0; }; class IntMV : public MacroValue { + friend class StringMV; private: int value; public: IntMV(int value_arg); + virtual ~IntMV(); virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError); virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError); virtual MacroValue *operator-() const throw (TypeError); @@ -75,6 +81,8 @@ public: virtual MacroValue *operator!() const throw (TypeError); virtual string toString() const; virtual MacroValue *clone() const; + virtual MacroValue *toArray() const; + virtual MacroValue *append(const MacroValue &array) const; }; class StringMV : public MacroValue @@ -83,6 +91,7 @@ private: string value; public: StringMV(const string &value_arg); + virtual ~StringMV(); 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); @@ -90,39 +99,137 @@ 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); -// virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); - virtual string toString() const; - virtual MacroValue *clone() const; -}; - -/* -class IntArrayMV : public MacroValue -{ -private: - vector values; -public: - IntArrayMV(const vector &values_arg); - 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. Indexes begin at 1. + \todo Add bound error checking + */ virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); virtual string toString() const; virtual MacroValue *clone() const; + virtual MacroValue *toArray() const; + virtual MacroValue *append(const MacroValue &array) const; }; -class StringArrayMV : public MacroValue +template +class ArrayMV : public MacroValue { + friend class IntMV; + friend class StringMV; + friend class ArrayMV; // Necessary for operator[] to access values of integer array when subscripting a string array private: - vector values; + vector values; public: - StringArrayMV(const vector &values_arg); + ArrayMV(const vector &values_arg); + virtual ~ArrayMV(); 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. Indexes begin at 1. + \todo Add bound error checking + */ virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); virtual string toString() const; virtual MacroValue *clone() const; + virtual MacroValue *toArray() const; + virtual MacroValue *append(const MacroValue &array) const; }; -*/ + +template +ArrayMV::ArrayMV(const vector &values_arg) : values(values_arg) +{ +} + +template +ArrayMV::~ArrayMV() +{ +} + +template +MacroValue * +ArrayMV::operator+(const MacroValue &mv) const throw (TypeError) +{ + const ArrayMV *mv2 = dynamic_cast *>(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of + operator"); + else + { + vector values_copy(values); + values_copy.insert(values_copy.end(), + mv2->values.begin(), + mv2->values.end()); + return new ArrayMV(values_copy); + } +} + +template +MacroValue * +ArrayMV::operator==(const MacroValue &mv) const throw (TypeError) +{ + const ArrayMV *mv2 = dynamic_cast *>(&mv); + if (mv2 == NULL) + throw new IntMV(0); + else + return new IntMV(values == mv2->values); +} + +template +MacroValue * +ArrayMV::operator!=(const MacroValue &mv) const throw (TypeError) +{ + const ArrayMV *mv2 = dynamic_cast *>(&mv); + if (mv2 == NULL) + throw new IntMV(1); + else + return new IntMV(values != mv2->values); +} + +template +MacroValue * +ArrayMV::operator[](const MacroValue &mv) const throw (TypeError) +{ + const ArrayMV *mv2 = dynamic_cast *>(&mv); + if (mv2 == NULL) + throw TypeError("Expression inside [] must be an integer array"); + vector result; + for(vector::const_iterator it = mv2->values.begin(); + it != mv2->values.end(); it++) + result.push_back(values[*it - 1]); + return new ArrayMV(result); +} + +template +string +ArrayMV::toString() const +{ + ostringstream ss; + for(typename vector::const_iterator it = values.begin(); + it != values.end(); it++) + ss << *it; + return ss.str(); +} + +template +MacroValue * +ArrayMV::clone() const +{ + return new ArrayMV(values); +} + +template +MacroValue * +ArrayMV::toArray() const +{ + return clone(); +} + +template +MacroValue * +ArrayMV::append(const MacroValue &mv) const +{ + throw TypeError("Cannot append an array at the end of another one. Should use concatenation."); +} #endif