diff --git a/macro/MacroBison.yy b/macro/MacroBison.yy index 0addc52cb48781dfa0e0a9addb9261a62fb91cd6..64848d141fbf3d36feea76f031b5c2fbfcdf2d7f 100644 --- a/macro/MacroBison.yy +++ b/macro/MacroBison.yy @@ -55,7 +55,7 @@ class MacroDriver; }; %{ -#include <stdlib.h> // Pour atoi() +#include <cstdlib> // 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 <int_val> INTEGER %token <string_val> 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 <mv> expr +%type <mv> 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/macro/MacroFlex.ll b/macro/MacroFlex.ll index 8bdc68ccb24c4f984f08a8f5ac8d7378c4314d03..a1ba2ca97ae0204d01d1109cdb3e4e540ec2ca82 100644 --- a/macro/MacroFlex.ll +++ b/macro/MacroFlex.ll @@ -113,6 +113,7 @@ typedef Macro::parser::token token; <MACRO>\[ { return token::LBRACKET; } <MACRO>\] { return token::RBRACKET; } <MACRO>: { return token::COLON; } +<MACRO>, { return token::COMMA; } <MACRO>= { return token::EQUAL; } <MACRO>[!] { return token::EXCLAMATION; } <MACRO>"||" { 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 */ +<INITIAL>[\r]+ { yylloc->step(); } + /* Copy everything else to output */ <INITIAL>[\n]+ { yylloc->lines(yyleng); yylloc->step(); ECHO; } <INITIAL>. { yylloc->step(); ECHO; } diff --git a/macro/MacroValue.cc b/macro/MacroValue.cc index aa137dfab50bcb72c4f4f00eb6deb60354c32bd4..b8e0d0753270974362a4daf0c7e4e35404792ab3 100644 --- a/macro/MacroValue.cc +++ b/macro/MacroValue.cc @@ -17,10 +17,12 @@ * along with Dynare. If not, see <http://www.gnu.org/licenses/>. */ -#include <sstream> - #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<int> v; + v.push_back(value); + return new ArrayMV<int>(v); +} + +MacroValue * +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); + } +} + 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<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv); + if (mv2 == NULL) + throw TypeError("Expression inside [] must be an integer array"); + string result; + for(vector<int>::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<string> v; + v.push_back(value); + return new ArrayMV<string>(v); +} + +MacroValue * +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); + } +} diff --git a/macro/MacroValue.hh b/macro/MacroValue.hh index 31e7687c49b8466bcadd42ac991f4bebb358698b..cdac2db5e0991b9350897f1bad8965d4b4602897 100644 --- a/macro/MacroValue.hh +++ b/macro/MacroValue.hh @@ -24,6 +24,7 @@ using namespace std; #include <string> #include <vector> +#include <sstream> 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); + //! Subscripting operator + /*! + Argument must be an ArrayMV<int>. 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 IntArrayMV : public MacroValue +template<typename T> +class ArrayMV : public MacroValue { + friend class IntMV; + friend class StringMV; + friend class ArrayMV<string>; // Necessary for operator[] to access values of integer array when subscripting a string array private: - vector<int> values; + vector<T> values; public: - IntArrayMV(const vector<int> &values_arg); + ArrayMV(const vector<T> &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<int>. 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<typename T> +ArrayMV<T>::ArrayMV(const vector<T> &values_arg) : values(values_arg) { -private: - vector<string> values; -public: - StringArrayMV(const vector<string> &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); - virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); - virtual string toString() const; - virtual MacroValue *clone() const; -}; -*/ +} + +template<typename T> +ArrayMV<T>::~ArrayMV() +{ +} + +template<typename T> +MacroValue * +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); + } +} + +template<typename T> +MacroValue * +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); + else + return new IntMV(values == mv2->values); +} + +template<typename T> +MacroValue * +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); + else + return new IntMV(values != mv2->values); +} + +template<typename T> +MacroValue * +ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError) +{ + const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv); + if (mv2 == NULL) + throw TypeError("Expression inside [] must be an integer array"); + vector<T> result; + for(vector<int>::const_iterator it = mv2->values.begin(); + it != mv2->values.end(); it++) + result.push_back(values[*it - 1]); + return new ArrayMV<T>(result); +} + +template<typename T> +string +ArrayMV<T>::toString() const +{ + ostringstream ss; + for(typename vector<T>::const_iterator it = values.begin(); + it != values.end(); it++) + ss << *it; + return ss.str(); +} + +template<typename T> +MacroValue * +ArrayMV<T>::clone() const +{ + return new ArrayMV<T>(values); +} + +template<typename T> +MacroValue * +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