解释器模式.cpp
#include <iostream>
#include <map>
#include <stack>
#include <vector>
#include <cstring>
#include <memory>
#include <set>
#include <sstream>
using namespace std;
namespace ns1
{class Expression {public: int m_dbg_num; char m_dbg_sign; public:Expression(int num, char sign) : m_dbg_num(num), m_dbg_sign(sign) {}virtual ~Expression() {}public: virtual int interpret(const map<char, int> &var) const = 0; };class VarExpression : public Expression {char m_key; public:VarExpression(const char &key, int num, char sign) : Expression(num, sign), m_key(key) {}int interpret(const map<char, int> &var) const override { return var.at(m_key); } };class SymbolExpression : public Expression {protected: shared_ptr<Expression> m_left;shared_ptr<Expression> m_right;public:SymbolExpression(const shared_ptr<Expression> &left, const shared_ptr<Expression> &right, int num, char sign) : m_left(left), m_right(right), Expression(num, sign) {}shared_ptr<Expression> getLeft() const { return m_left; }shared_ptr<Expression> getRight() const { return m_right; }};class AddExpression : public SymbolExpression {public:AddExpression(const shared_ptr<Expression> &left, const shared_ptr<Expression> &right, int num, char sign) : SymbolExpression(left, right, num, sign) {} int interpret(const map<char, int> &var) const override{int value1 = m_left->interpret(var); int value2 = m_right->interpret(var); int result = value1 + value2;return result; }};class SubExpression : public SymbolExpression {public:SubExpression(const shared_ptr<Expression> &left, const shared_ptr<Expression> &right, int num, char sign) : SymbolExpression(left, right, num, sign) {} int interpret(const map<char, int> &var) const override{int value1 = m_left->interpret(var);int value2 = m_right->interpret(var);int result = value1 - value2;return result; }};shared_ptr<Expression> analyse(const string &strExp) {stack<shared_ptr<Expression>> expStack; shared_ptr<Expression> left;shared_ptr<Expression> right;int icount = 1;for (size_t i = 0; i < strExp.size(); ++i) {switch (strExp[i]){case '+': left = expStack.top(); right.reset(new VarExpression(strExp[++i], icount++, 'v')); expStack.push(make_shared<AddExpression>(left, right, icount++, '+')); break;case '-': left = expStack.top(); right.reset(new VarExpression(strExp[++i], icount++, 'v'));expStack.push(make_shared<SubExpression>(left, right, icount++, '-')); break;default: expStack.push(make_shared<VarExpression>(strExp[i], icount++, 'v'));break;}}shared_ptr<Expression> expression = expStack.top(); return expression;}
}namespace ns2
{class Expression {public:virtual ~Expression() {}public: virtual string interpret() const = 0;};class DirectionExpression : public Expression {string m_direction; public:DirectionExpression(const string &direction) : m_direction(direction) {}string interpret() const override{static set<string> directionSet = {"up", "down", "left", "right"};if (directionSet.find(m_direction) != directionSet.end())return m_direction;elsereturn "direction error";}};class ActionExpression : public Expression {string m_action; public:ActionExpression(const string &action) : m_action(action) {}string interpret() const override{static set<string> actionSet = {"walk", "run"};if (actionSet.find(m_action) != actionSet.end())return m_action;elsereturn "action error";}};class DistanceExpression : public Expression {string m_distance; public:DistanceExpression(const string &distance) : m_distance(distance) {}string interpret() const override{return m_distance + "m";}};class SentenceExpression : public Expression {shared_ptr<Expression> m_direction; shared_ptr<Expression> m_action; shared_ptr<Expression> m_distance; public:SentenceExpression(const shared_ptr<Expression> &direction, const shared_ptr<Expression> &action, const shared_ptr<Expression> &distance): m_direction(direction), m_action(action), m_distance(distance) {}shared_ptr<Expression> getDirection() const { return m_direction; }shared_ptr<Expression> getAction() const { return m_action; }shared_ptr<Expression> getDistance() const { return m_distance; }string interpret() const override{return m_direction->interpret() + " " + m_action->interpret() + " " + m_distance->interpret();}};class AndExpression : public Expression {shared_ptr<Expression> m_left;shared_ptr<Expression> m_right;public:AndExpression(const shared_ptr<Expression> &left, const shared_ptr<Expression> &right) : m_left(left), m_right(right) {}shared_ptr<Expression> getLeft() const { return m_left; }shared_ptr<Expression> getRight() const { return m_right; }string interpret() const override{return m_left->interpret() + " and " + m_right->interpret();}};shared_ptr<Expression> analyse(const string &strExp) {stack<shared_ptr<Expression>> expStack;shared_ptr<Expression> direction;shared_ptr<Expression> action;shared_ptr<Expression> distance;shared_ptr<Expression> left;shared_ptr<Expression> right;vector<string> resultVec;stringstream iss(strExp); string token; while (getline(iss, token, ' ')) resultVec.push_back(token);for (auto iter = resultVec.begin(); iter != resultVec.end(); ++iter){if ((*iter) == "and") {left = expStack.top(); ++iter;direction.reset(new DirectionExpression(*iter)); ++iter;action.reset(new ActionExpression(*iter)); ++iter;distance.reset(new DistanceExpression(*iter)); right.reset(new SentenceExpression(direction, action, distance));expStack.push(make_shared<AndExpression>(left, right));}else{direction.reset(new DirectionExpression(*iter)); ++iter;action.reset(new ActionExpression(*iter)); ++iter;distance.reset(new DistanceExpression(*iter)); expStack.push(make_shared<SentenceExpression>(direction, action, distance));}}shared_ptr<Expression> expression = expStack.top(); return expression;}
}int main()
{
#if 0using namespace ns1;map<char, int> varmap;varmap.insert(make_pair('a', 7)); varmap.insert(make_pair('b', 9)); varmap.insert(make_pair('c', 3)); varmap.insert(make_pair('d', 2)); string strExp = "a-b+c+d"; shared_ptr<Expression> expression = analyse(strExp); int result = expression->interpret(varmap); cout << strExp << " = " << result << endl;
#endif#if 1using namespace ns2;string strExp = "left walk 15 and down run 20";shared_ptr<Expression> expression = analyse(strExp); cout << expression->interpret() << endl;
#endifcout << "Over!\n";return 0;
}