/* * C++ Design Patterns: Interpreter * Author: Jakub Vojvoda [github.com/JakubVojvoda] * 2016 * * Source code is licensed under MIT License * (for more details see LICENSE) * */ #include #include /* * Context * contains information that's global to the interpreter */ class Context { public: void set(std::string var, bool value) { vars.insert(std::pair(var, value)); } bool get(std::string exp) { return vars[exp]; } // ... private: std::map vars; // ... }; /* * Abstract Expression * declares an abstract Interpret operation that is common to all nodes * in the abstract syntax tree */ class AbstractExpression { public: virtual ~AbstractExpression() {} virtual bool interpret(Context *) { return false; } // ... }; /* * Terminal Expression * implements an Interpret operation associated with terminal symbols * in the grammar (an instance is required for every terminal symbol * in a sentence) */ class TerminalExpression : public AbstractExpression { public: TerminalExpression(std::string val) : value(val) {} ~TerminalExpression() {} bool interpret(Context *context) { return context->get(value); } // ... private: std::string value; // ... }; /* * Nonterminal Expression * implements an Interpret operation for nonterminal symbols * in the grammar (one such class is required for every rule in the grammar) */ class NonterminalExpression : public AbstractExpression { public: NonterminalExpression(AbstractExpression *left, AbstractExpression *right) : lop(left), rop(right) {} ~NonterminalExpression() { delete lop; delete rop; } bool interpret(Context *context) { return lop->interpret(context) && rop->interpret(context); } // ... private: AbstractExpression *lop; AbstractExpression *rop; // ... }; int main() { // An example of very simple expression tree // that corresponds to expression (A AND B) AbstractExpression *A = new TerminalExpression("A"); AbstractExpression *B = new TerminalExpression("B"); AbstractExpression *exp = new NonterminalExpression(A, B); Context context; context.set("A", true); context.set("B", false); std::cout << context.get("A") << " AND " << context.get("B"); std::cout << " = " << exp->interpret(&context) << std::endl; delete exp; return 0; }