Interpreter

Structural example

#include <iostream>
#include <vector>
using namespace std;
 
// The 'Context' class
class Context {
};
 
// The 'AbstractExpression' abstract class
class AbstractExpression {
public:
	virtual void Interpret(Context *context) = 0;
};
 
// The 'TerminalExpression' class
class TerminalExpression : public AbstractExpression {
public:
	virtual void Interpret(Context *context) {
		cout << "Called Terminal.Interpret()" << endl;
	}
};
 
// The 'NonterminalExpression' class
class NonterminalExpression : public AbstractExpression {
public:
	virtual void Interpret(Context *context) {
		cout << "Called Nonterminal.Interpret()" << endl;
	}
};
 
// Entry point into console application.
int main() {
	Context *context = new Context;
 
	// Usually a tree
	vector<AbstractExpression*> list;
 
	// Populate 'abstract syntax tree'
	list.push_back(new TerminalExpression);
	list.push_back(new NonterminalExpression);
	list.push_back(new TerminalExpression);
	list.push_back(new TerminalExpression);
 
	vector<AbstractExpression*>::iterator it;
 
	// Interpret
	it = list.begin();
	while (it != list.end()) {
		(*it)->Interpret(context);
		++it;
	}
 
	// end
	it = list.begin();
	while (it != list.end()) {
		delete *it;
		++it;
	}
	return 0;
}
 


Real World example

#include <iostream>
#include <string>
#include <list>
using namespace std;
 
// The 'Context' class
class Context {
private:
	string _input;
	int _output;
public:
	// Constructor
	Context(const string &input) {
		_input = input;
		_output = 0;
	}
	// Gets or sets input
	string getInput() {
		return _input;
	}
	void setInput(const string &value) {
		_input = value;
	}
	// Gets or sets output
	int getOutput() {
		return _output;
	}
	void setOutput(int value) {
		_output = value;
	}
};
 
// The 'AbstractExpression' class
class Expression {
public:
	void Interpret(Context *context) {
		if (context->getInput().length() == 0) {
			return;
		}
		if (context->getInput().compare(0, Nine().length(), Nine()) == 0) {
			context->setOutput(context->getOutput() + (9 * Multiplier()));
			context->setInput(context->getInput().substr(2));
		}
		else if (context->getInput().compare(0, Four().length(), Four()) == 0) {
			context->setOutput(context->getOutput() + (4 * Multiplier()));
			context->setInput(context->getInput().substr(2));
		}
		else if (context->getInput().compare(0, Five().length(), Five()) == 0) {
			context->setOutput(context->getOutput() + (5 * Multiplier()));
			context->setInput(context->getInput().substr(1));
		}
		while (context->getInput().compare(0, One().length(), One()) == 0) {
			context->setOutput(context->getOutput() + (1 * Multiplier()));
			context->setInput(context->getInput().substr(1));
		}
	}
	virtual string One() = 0;
	virtual string Four() = 0;
	virtual string Five() = 0;
	virtual string Nine() = 0;
	virtual int Multiplier() = 0;	// multiplier: 掛ける、増える
};
 
// A 'TerminalExpression' class
// Thousand checks for the Roman Numeral M
class ThousandExpression : public Expression {
public:
	virtual string One() { return "M"; }
	virtual string Four() { return " "; }
	virtual string Five() { return " "; }
	virtual string Nine() { return " "; }
	virtual int Multiplier() { return 1000; }
};
 
// A 'TerminalExpression' class
// Hundred checks C, CD, D or CM
class HundredExpression : public Expression {
public:
	virtual string One() { return "C"; }
	virtual string Four() { return "CD"; }
	virtual string Five() { return "D"; }
	virtual string Nine() { return "CM"; }
	virtual int Multiplier() { return 100; }
};
 
// A 'TerminalExpression' class
// Ten checks for X, XL, L and XC
class TenExpression : public Expression {
public:
	virtual string One() { return "X"; }
	virtual string Four() { return "XL"; }
	virtual string Five() { return "L"; }
	virtual string Nine() { return "XC"; }
	virtual int Multiplier() { return 10; }
};
 
// A 'TerminalExpression' class
// One checks for I, II, III, IV, V, VI,VII, VIII, IX
class OneExpression : public Expression {
public:
	virtual string One() { return "I"; }
	virtual string Four() { return "IV"; }
	virtual string Five() { return "V"; }
	virtual string Nine() { return "IX"; }
	virtual int Multiplier() { return 1; }
};
 
// Entry point into console application.
int main() {
	string roman = "MCMXXVIII";
	Context *context = new Context(roman);
 
	// Build the 'parse tree'
	list<Expression*> tree;
	tree.push_back(new ThousandExpression);
	tree.push_back(new HundredExpression);
	tree.push_back(new TenExpression);
	tree.push_back(new OneExpression);
 
	list<Expression*>::iterator it;
 
	// Interpret
	it = tree.begin();
	while (it != tree.end()) {
		(*it)->Interpret(context);
		++it;
	}
 
	cout << roman << " = " << context->getOutput() << endl;
 
	// end
	it = tree.begin();
	while (it != tree.end()) {
		delete *it;
		++it;
	}
	return 0;
}
 


参考サイト

デザインパターンを“喩え話”で分かり易く理解する
http://www.netlaputa.ne.jp/~hijk/study/oo/designpattern.html



デザインパターンの骸骨たち
http://www002.upp.so-net.ne.jp/ys_oota/mdp/

デザインパターンの使い方: Interpreter
http://japan.internet.com/developer/20081205/26.html
最終更新:2011年12月31日 23:25