// FILE: EXPRESSION.H // CLASS DEFINITIONS OF EXPRESSIONS // MODEL SOLUTION #if !defined(_EXPRESSION_H_) #define _EXPRESSION_H_ #if defined(__GNUG__) #if (__GNUC_MINOR__ == 7) // gcc 2.7.x #include #endif #endif #include #include "list.h" /* EXPRESSION CLASS * * ABSTRACT, SUBCLASSES MUST IMPLEMENT * - EVALUATE * - PRINT * - CLONE */ class expression { protected: // THE COPY CONSTRUCTOR IS NOT PUBLIC!!! // EXPRESSIONS CAN BE POTENTIALLY LARGE // AND RECURSIVE IN STRUCTURE, HENCE THEY // SHOULD NOT BE PASSED OR RETURNED BY VALUE // // MAKING THE COPY CONSTRUCTOR PROTECTED // AUTOMATICALLY ACHIEVES THAT expression(const expression&); // NO ASSIGNMENT EITHER expression& operator=(const expression&); public: // DEFAULT CONSTRUCTOR expression(); // IF YOU DO NEED A COPY, USE THE CLONE // METHOD, WHICH CREATES A CARBON COPY // DYNAMICALLY AND RETURNS ITS ADDRESS virtual expression* clone() const = 0; // EVALUATE RETURNS THE VALUE OF THE EXPRESSION // IT MUST BE VIRTUAL, BECUASE SUBCLASSES // OVERLOAD IT // // THE ARGUMENT IS A LIST OF CURRENT BINDINGS // FOR VARIABLES virtual double evaluate(double*) const = 0; // DESTRUCTOR virtual ~expression(); // TEXTUAL FORM virtual void print(ostream&) const = 0; // CAN THIS EXPRESSION BE REPLACED BY A CONSTANT // IE, CAN IT BE "COMPILE TIME" EVALUATED // THEY ARE ALL SIMPLE UNLESS CONTAIN A // VARIABLE virtual bool simple() const; // SIMPLIFY EXPRESSION // AND RETURN A NEW ONE // IT RETURNS A NEW SIMPLIFIED EXPRESSION // EXAMPLES // EXPR SIMPL EXPRESSION // 3+4 7 // (x*7)/3 (x*7)/3 // (7+9)*x 16*x virtual expression* simplify() const = 0; }; // OVERLOADED OUTPUT OPERATOR, SO INSTANCES // OF EXPRESSIONS CAN BE PRINTED AS IF THEY // WERE PRIMITIVE OF TYPE ostream& operator<<(ostream&, const expression&); /* CONSTANT EXPRESSION * * THEY EVALUATE TO THEMSELVES, AND * REPRESENT LITERAL FLOATING POINT * VALUES */ class constant: public expression { private: double value; // INTERNAL REP // COPY CONSTRUCTOR, NOT PUBLIC!! constant(const constant&); public: // CONSTRUCTOR, NO DEFAULT constant(double); // EVALUATES TO ITSELF, IE VALUE double evaluate(double*) const; // CREATE A NEW INSTANCE, COPY expression* clone() const; // TEXTUAL FORM void print(ostream&) const; // ALWAYS SIMPLE bool simple() const; // RETURN A CLONE expression* simplify() const; }; /* VARIABLE EXPRESSION * * THEY EVALUATE TO THE INDEXTH * ELEMENT IN THE LIST OF BINDINGS */ class variable: public expression { private: int index; // INDEX IN BINDING LIST // COPY CONSTRUCTOR, NOT PUBLIC!! variable(const variable&); public: // CONSTRUCTOR, NO DEFAULT variable(int); // EVALUATES TO THE INDEXTH ELEMENT IN THE LIST double evaluate(double*) const; // CREATE A NEW INSTANCE, COPY expression* clone() const; // TEXTUAL FORM void print(ostream&) const; // RETURNS FALSE bool simple() const; // RETURNS A CLONE OF ITSELF expression* simplify() const; }; /* PARANTHESIZED EXPRESSIONS * * * */ class sub_expression: public expression { private: // EXPRESSION IN THE PARANTHESIS expression* expr; // COPY CONSTRUCTOR, PRIVATE sub_expression(const sub_expression&); public: // CONSTRUCTOR, NO DEFAULT sub_expression(expression*); ~sub_expression(); // RETURNS THE VALUE OF THE EXPRESSION // IN PARANTHESIS double evaluate(double*) const; // RETURNS A CLONE OF ITSELF expression* clone() const; void print(ostream&) const; // IF expr IS SIMPLE bool simple() const; // RETURNS A CONSTANT // A SIMPLIFIED SUB EXPRESSION // OR ITSELF expression* simplify() const; }; /* A BINARY OPERATOR EXPRESSION HAS * A LEFT AND RIGHT HAND SIDES * */ class binary_operator_expression: public expression { protected: expression* lhs; // LEFT HAND SIDE expression* rhs; // RIGHT HAND SIDE int precedence; // PRECEDENCE, THE HIGHER // THE LOWER IT SHOULD BE ON THE TREE // COPY CONSTRUCTOR, NOT PUBLIC binary_operator_expression(const binary_operator_expression&); public: // DEFAULT CONSTRUCTOR, PRECEDENCE IS 0 BY DEFAULT binary_operator_expression(expression*,expression*, int = 0); // DESSTRUCTOR virtual ~binary_operator_expression(); int get_precedence() const; // IF lhs AND rhs ARE SIMPLE bool simple() const; friend class binary_operator_adaptor; }; /* THIS CLASS HOLDS A BINARY OPERATOR EXPRESSION * * ITS ONLY PURPOSE IS TO FIX PRECEDENCE * * IF EITHER LHS OR RHS IS ITSELF A BINARY EXPRESSION * AND HAS LOWER PRECEDENCE THAN 'binary_expression' * THEN EXCHANGE THE ORDER OF EVALUATION, AND DO IT * RECURSIVELLY * */ class binary_operator_adaptor: public expression { protected: // THE BINARY EXPRESSION IT WRAPS binary_operator_expression* binary_expression; void fix_right(); // FIX RIGHT SUBTREE void fix_left(); // FIX LEFT SUBTREE // COPY CONSTRUCTOR binary_operator_adaptor(const binary_operator_adaptor&); public: // CONSTRUCTOR binary_operator_adaptor(binary_operator_expression*); ~binary_operator_adaptor(); double evaluate(double*) const; expression* clone() const; void print(ostream&) const; // SIMPLE IF binary_expression IS SIMPLE bool simple() const; // RETRUNS A BINARY EXPRESSION OR // A SIMPLIFIED BUNARY EXPRESSION expression* simplify() const; }; /* UNARY OPERATOR EXPRESSIONS HAVE AN OPERAND * */ class unary_operator_expression: public expression { protected: expression* operand; unary_operator_expression(const unary_operator_expression&); public: unary_operator_expression(expression*); virtual ~unary_operator_expression(); // IF expr IS SIMPLE virtual bool simple() const; }; /* FUNCTION CALLS HAVE A LIST OF ARGUMENTS * EACH AN EXPRESSION ITSELF */ class function_call: public expression { protected: expression** argv; // ARGUMENTS int argc; // NUMBER OF ARGUMENTS // BOTH COPY AND DEFALUT CONSTRUCTORS ARE PROTECTED function_call(const function_call&); function_call(); public: virtual ~function_call(); // IF ALL ARGUMENTS IN argv ARE SIMPLE virtual bool simple() const; }; #endif