#include #include #include #include #include #include class Expression; void pretty_print(std::ostream& os, Expression* expression); class Expression { public: virtual ~Expression() = default; virtual bool evaluate() const = 0; virtual void print(std::ostream& os) const = 0; }; class Literal : public Expression { public: Literal(bool value) : value { value } { } bool evaluate() const override { return value; } void print(std::ostream& os) const override { os << std::boolalpha << value; } private: bool value; }; class Compound : public Expression { public: Compound(std::initializer_list const& expressions) : expressions { expressions.begin(), expressions.end() } { } ~Compound() { for (Expression* expression : expressions) { delete expression; } } virtual std::string glyph() const = 0; void print(std::ostream& os) const override { if (expressions.empty()) return; pretty_print(os, expressions.front()); for (Expression* expression : expressions | std::views::drop(1)) { os << " " << glyph() << " "; pretty_print(os, expression); } } protected: std::vector expressions; }; class And : public Compound { public: using Compound::Compound; bool evaluate() const override { for (Expression* expression : expressions) { if (!expression->evaluate()) return false; } return true; } std::string glyph() const override { return "&&"; } }; class Or : public Compound { public: using Compound::Compound; bool evaluate() const override { for (Expression* expression : expressions) { if (expression->evaluate()) return true; } return false; } std::string glyph() const override { return "||"; } }; class Negation : public Expression { public: Negation(Expression* expression) : expression { expression } { } ~Negation() { delete expression; } bool evaluate() const override { return !expression->evaluate(); } void print(std::ostream& os) const override { os << '!'; pretty_print(os, expression); } private: Expression* expression; }; void pretty_print(std::ostream& os, Expression* expression) { bool const parenthesis { dynamic_cast(expression) != nullptr }; if (parenthesis) os << '('; expression->print(os); if (parenthesis) os << ')'; } /* Expected output: !true = false !(true && false) = true (true || false) && false && (false || !false) = false */ int main() { Expression* expr1 { new Negation { new Literal { true } } }; expr1->print(std::cout); std::cout << " = " << expr1->evaluate() << std::endl; Expression* expr2 { new Negation { new And { new Literal { true }, new Literal { false } } } }; expr2->print(std::cout); std::cout << " = " << expr2->evaluate() << std::endl; Expression* expr3 { new And { new Or { new Literal { true }, new Literal { false } }, new Literal { false }, new Or { new Literal { false }, new Negation { new Literal{false} } } } }; expr3->print(std::cout); std::cout << " = " << expr3->evaluate() << std::endl; }