#ifndef EXPRESSION_HPP_ #define EXPRESSION_HPP_ #include #include // TODO: you may add more classes, functions, etc. however you want (even restructure the code if needed) class Value { public: using pointer = std::unique_ptr; Value() = default; virtual ~Value() noexcept = default; Value(const Value&) = delete; Value& operator=(const Value&) = delete; Value& operator=(Value&&) noexcept; Value(Value&&) noexcept; // adding behavior to `Value + Value` (look up double dispatch pattern for useful hints) friend pointer operator+(const Value& lhs, const Value& rhs) { return lhs.add(rhs); } // adding behavior to `Value * Value` friend pointer operator*(const Value& lhs, const Value& rhs) { return lhs.mul(rhs); } // adding a behavior to `ostream << Value` friend std::ostream& operator<<(std::ostream& os, const Value& v) { v.print(os); return os; } protected: virtual pointer add(const Value& rhs) const = 0; virtual pointer mul(const Value& rhs) const = 0; virtual void print(std::ostream& os) const = 0; }; class Expression { public: using pointer = std::unique_ptr; Expression() = default; virtual ~Expression() noexcept = default; Expression(const Expression&) = delete; Expression& operator=(const Expression&) = delete; Expression& operator=(Expression&&) noexcept; Expression(Expression&&) noexcept; virtual Value::pointer evaluate() const = 0; // adding a behavior to `ostream << Expression` friend std::ostream& operator<<(std::ostream& os, const Expression& e) { // TODO: print the expression in prefix notation (so we do not need to care about parentheses) // and return the stream return os; } protected: virtual void print(std::ostream& os) const = 0; }; class ValueExpression : public Expression { public: // TODO: Implement ValueExpression; you can change it to a template class if you want // represents a value (literal) in an expression }; class AddExpression : public Expression { public: // TODO: Implement AddExpression // represents an addition operation in an expression }; // etc. // dummy functions that you want to replace with your own implementation: inline Expression::pointer make_value(int) { return nullptr; } inline Expression::pointer make_value(double) { return nullptr; } inline Expression::pointer make_addition(Expression::pointer, Expression::pointer) { return nullptr; } inline Expression::pointer make_multiplication(Expression::pointer, Expression::pointer) { return nullptr; } #endif // EXPRESSION_HPP_