解释器模式.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;
else
return "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;
else
return "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 0
using 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 1
using namespace ns2;
string strExp = "left walk 15 and down run 20";
shared_ptr<Expression> expression = analyse(strExp);
cout << expression->interpret() << endl;
#endif
cout << "Over!\n";
return 0;
}