#ifndef EXPRESSION_HPP_ #define EXPRESSION_HPP_ #include #include #include #include #include // TODO: you may add more classes, functions, etc. however you want 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; friend pointer operator+(const Value& lhs, const Value& rhs) { return lhs.add(rhs); } friend pointer operator*(const Value& lhs, const Value& rhs) { return lhs.mul(rhs); } 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; friend std::ostream& operator<<(std::ostream& os, const Expression& e) { auto value = e.evaluate(); return os << *value; } }; class IntValue : public Value { public: pointer add(const Value& rhs) const override { if (auto intValue = dynamic_cast(&rhs)) { return std::make_unique(value_ + intValue->value_); } // TODO: rhs je DoubleValue throw std::runtime_error("weird type"); } private: int value_; } 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 }; inline Expression::pointer parse_add_expression(std::istream &in) { auto lhs = parse_mul_expression(in); while (in >> std::ws && (in.peek() == '+' || in.peek() == '-')) { char op = (char)in.get(); auto rhs = parse_mul_expression(in); if (op == '+') { lhs = make_add_expression(std::move(lhs), std::move(rhs)); } else { lhs = make_sub_expression(std::move(lhs), std::move(rhs)); } } return lhs; } inline bool is_numeric_char(char c) { return std::isdigit(static_cast(c)) || c == '.'; } inline std::string parse_numeric(std::istream& in) { char c; std::string numeric; in >> std::ws; while (in.get(c)) { if (is_numeric_char(c)) numeric.push_back(c); else in.unget(); // rollback the character } if (numeric.empty()) throw std::runtime_error("expected a number"); return numeric; } // dummy functions that you want to replace with your own implementation: inline Expression::pointer make_value(int) { return } inline Expression::pointer make_value(double) { return nullptr; } inline Expression::pointer parse_value_expression(std::istream& in) { char c; in >> std::ws; if (in.get(c)) { if (c == '(') { auto expr = parse_add_expression(in); if (!in.get(c) || c != ')') { throw std::runtime_error("expected ), got something else"); } return expr; } auto numeric = parse_numeric(in); if (std::any_of(numeric.begin(), numeric.end(), [](char c) { return c == '.'})) { return make_value(std::stod(numeric)); } else { return make_value(std::stoi(numeric)); } } } 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_