/// // Interpreter pattern // - Given a language, define a represention for its grammar along with an interpreter // that uses the representation to interpret sentences in the language. /// #include #include using namespace std; // forward declaraction class VariableExp; // Context // - contains information that's global to the interpreter class Context { public: bool Lookup(char *name) const; void Assign(VariableExp *exp, bool b); private: map _mapping; }; // AbstractExpression // - declares an abstract Interpret operation that is common to all nodes in the // abstract syntax tree. class BooleanExp { public: virtual ~BooleanExp() { } virtual bool Evaluate(Context &c) = 0; }; // TerminalExpression // - implements an Interpret operation associated with terminal symbols in the // grammar. // - an instance is required for every terminal symbol in a sentence. class VariableExp : public BooleanExp { public: VariableExp(char *name) : _name(name) { } virtual bool Evaluate(Context &aContext) { return aContext.Lookup(_name); } const char *GetName() { return _name; } private: char *_name; }; bool Context::Lookup(char *name) const { for (map ::const_iterator map_it = _mapping.begin(); map_it != _mapping.end(); ++map_it) { if (strcmp(map_it->first->GetName(), name) == 0) { return map_it->second; } } } void Context::Assign(VariableExp *exp, bool b) { _mapping.insert(std::pair (exp, b)); } // NonterminalExpression // - one such class is required for every rule R::=R1R2...Rn in the grammar. // - maintains instance variables of type AbstractExpression for each of the // symbols R1 through Rn. // - implements an Interpret operation for nonterminal symbols in the grammer. // Interpret typically calls itself recursively on the variables representing // R1 through Rn. class AndExp : public BooleanExp { public: AndExp(BooleanExp *op1, BooleanExp *op2) : _operand1(op1), _operand2(op2) { } virtual bool Evaluate(Context &aContext) { return _operand1->Evaluate(aContext) && _operand2->Evaluate(aContext); } private: BooleanExp *_operand1; BooleanExp *_operand2; }; class OrExp : public BooleanExp { public: OrExp(BooleanExp *op1, BooleanExp *op2) : _operand1(op1), _operand2(op2) { } virtual bool Evaluate(Context &aContext) { return _operand1->Evaluate(aContext) || _operand2->Evaluate(aContext); } private: BooleanExp *_operand1; BooleanExp *_operand2; }; class NotExp : public BooleanExp { public: NotExp(BooleanExp *op) : _operand(op) { } virtual bool Evaluate(Context &aContext) { return ~_operand->Evaluate(aContext); } private: BooleanExp *_operand; }; // Client // - builds(or is given) an abstract syntax tree representing a particular // sentence in the language that the grammar defines. The abstract syntax // tree is assembled from instance fo the NonterminalExpression and // TerminalExpression classes. // - invokes the Interpret operation. int main() { // VariableExp represents a named variable. VariableExp *x = new VariableExp("X"); VariableExp *y = new VariableExp("Y"); // boolean expression (x and y) or (x and (not y)) BooleanExp *expression = new OrExp( new AndExp(x, y), new AndExp(x, new NotExp(y)) ); Context context; context.Assign(x, true); context.Assign(y, false); bool result = expression->Evaluate(context); return 0; }