/* * Copyright (C) 2008 Dynare Team * * This file is part of Dynare. * * Dynare is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dynare is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Dynare. If not, see . */ #ifndef _MACRO_VALUE_HH #define _MACRO_VALUE_HH using namespace std; #include #include #include class MacroDriver; //! Base class for representing values in macro language class MacroValue { protected: //! Reference to enclosing MacroDriver MacroDriver &driver; public: //! Exception thrown when type error occurs in macro language class TypeError { public: const string message; TypeError(const string &message_arg) : message(message_arg) {}; }; //! Exception thrown when doing an out-of-bounds access through [] operator class OutOfBoundsError { }; MacroValue(MacroDriver &driver_arg); virtual ~MacroValue(); //! Applies + operator virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0; //! Applies unary + operator virtual const MacroValue *operator+() const throw (TypeError); //! Applies - operator virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError); //! Applies unary - operator virtual const MacroValue *operator-() const throw (TypeError); //! Applies * operator virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError); //! Applies / operator virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError); //! Less comparison /*! Returns an IntMV, equal to 0 or 1 */ virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError); //! Greater comparision /*! Returns an IntMV, equal to 0 or 1 */ virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError); //! Less or equal comparison /*! Returns an IntMV, equal to 0 or 1 */ virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError); //! Greater or equal comparison /*! Returns an IntMV, equal to 0 or 1 */ virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError); //! Equal comparison /*! Returns an IntMV, equal to 0 or 1 */ virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0; //! Not equal comparison /*! Returns an IntMV, equal to 0 or 1 */ virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0; //! Applies && operator virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError); //! Applies || operator virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError); //! Applies unary ! operator virtual const MacroValue *operator!() const throw (TypeError); //! Applies [] operator virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError); //! Converts value to string virtual string toString() const = 0; //! Converts value to array form virtual const MacroValue *toArray() const = 0; //! Appends value at the end of an array /*! The first argument must be an array. */ virtual const MacroValue *append(const MacroValue *array) const throw (TypeError); //! Returns a new IntMV /*! Necessary for ArrayMV::operator[] (template issue) */ static const MacroValue *new_base_value(MacroDriver &driver, int i); //! Returns a new StringMV /*! Necessary for ArrayMV::operator[] (template issue) */ static const MacroValue *new_base_value(MacroDriver &driver, const string &s); }; //! Represents an integer value in macro language class IntMV : public MacroValue { friend class StringMV; friend class MacroDriver; private: //! Underlying integer value const int value; public: IntMV(MacroDriver &driver, int value_arg); virtual ~IntMV(); //! Computes arithmetic addition virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError); //! Unary plus /*! Returns itself */ virtual const MacroValue *operator+() const throw (TypeError); //! Computes arithmetic substraction virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError); //! Computes opposite virtual const MacroValue *operator-() const throw (TypeError); //! Computes arithmetic multiplication virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError); //! Computes arithmetic division virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError); //! Computes logical and virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError); //! Computes logical or virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError); //! Computes logical negation virtual const MacroValue *operator!() const throw (TypeError); virtual string toString() const; //! Converts value to array form /*! Returns an integer array containing a single value */ virtual const MacroValue *toArray() const; //! Appends value at the end of an array /*! The first argument must be an integer array. */ virtual const MacroValue *append(const MacroValue *array) const throw (TypeError); //! Creates a integer range /*! Arguments must be of type IntMV. Returns an integer array containing all integers between mv1 and mv2. If mv2 < mv1, constructs the range in decreasing order. */ static const MacroValue *new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError); }; //! Represents a string value in macro language class StringMV : public MacroValue { friend class MacroDriver; private: //! Underlying string value const string value; public: StringMV(MacroDriver &driver, const string &value_arg); virtual ~StringMV(); //! Computes string concatenation virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError); //! Subscripting operator /*! Argument must be an ArrayMV. Indexes begin at 1. Returns a StringMV. */ virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError); //! Returns underlying string value virtual string toString() const; //! Converts value to array form /*! Returns a string array containing a single value */ virtual const MacroValue *toArray() const; //! Appends value at the end of an array /*! The first argument must be a string array. Returns a string array. */ virtual const MacroValue *append(const MacroValue *array) const throw (TypeError); }; //! Represents an array in macro language /*! Empty arrays are forbidden */ 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 friend class MacroDriver; private: //! Underlying vector const vector values; public: ArrayMV(MacroDriver &driver, const vector &values_arg); virtual ~ArrayMV(); //! Computes array concatenation /*! Both array must be of same type */ virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError); virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError); //! Subscripting operator /*! Argument must be an ArrayMV. Indexes begin at 1. If argument is a one-element array, returns an IntMV or StringMV. Otherwise returns an array. */ virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError); //! Returns a string containing the concatenation of string representations of elements virtual string toString() const; //! Returns itself virtual const MacroValue *toArray() const; }; template ArrayMV::ArrayMV(MacroDriver &driver, const vector &values_arg) : MacroValue(driver), values(values_arg) { if (values.size() == 0) throw "Empty arrays forbidden"; } template ArrayMV::~ArrayMV() { } template const 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"); vector values_copy(values); values_copy.insert(values_copy.end(), mv2->values.begin(), mv2->values.end()); return new ArrayMV(driver, values_copy); } template const MacroValue * ArrayMV::operator==(const MacroValue &mv) const throw (TypeError) { const ArrayMV *mv2 = dynamic_cast *>(&mv); if (mv2 == NULL) return new IntMV(driver, 0); else return new IntMV(driver, values == mv2->values); } template const MacroValue * ArrayMV::operator!=(const MacroValue &mv) const throw (TypeError) { const ArrayMV *mv2 = dynamic_cast *>(&mv); if (mv2 == NULL) return new IntMV(driver, 1); else return new IntMV(driver, values != mv2->values); } template const MacroValue * ArrayMV::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError) { 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++) { if (*it < 1 || *it > (int) values.size()) throw OutOfBoundsError(); result.push_back(values[*it - 1]); } if (result.size() > 1) return new ArrayMV(driver, result); else return MacroValue::new_base_value(driver, result[0]); } 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 const MacroValue * ArrayMV::toArray() const { return this; } #endif