解释器模式一般用于语义解释问题。我们把问题抽象一下,这里定义一种简单的语法。这套语法规定,符号和结尾符构成表达式,只支持单个语句构成的表达式,不支持多表达式语句。那么我们可以实现一个比较简单的命令解释器,其结构如是非结尾符号+若干空格+结尾符
。这里定义非结尾符号仅有2种,分别是symbolA
和symbolB
,结尾符是;
。
解释器模式要求对每个语义成分实现一个表达式子类,并实现解释方法。
以下代码定义了非结尾符号类型。
#include <iostream>
using namespace std;
enum NonTerminalSymbolType
{
None,
TypeA,
TypeB,
};
以下代码定义了抽象表达式类型,子类必须实现解释方法。
class AbstractExpression
{
public:
virtual void Interpret() = 0;
};
以下代码定义了结尾符类,解释器的工作就是分辨当前符号是否为结尾符。
class TerminalExpression:public AbstractExpression
{
private:
string m_symbol;
bool bValid;
public:
static const string symbolTerminal;
TerminalExpression(string &symbol):m_symbol(symbol),bValid(false){}
void Interpret()
{
bValid = (symbolTerminal == m_symbol);
}
bool IsValid()
{
return bValid;
}
};
const string TerminalExpression::symbolTerminal = string(";");
以下代码定义了非结尾符号类,解释器的工作就是分辨当前符号是哪一种符号。
class NonTerminalExpression:public AbstractExpression
{
private:
string m_symbol;
NonTerminalSymbolType m_type;
public:
static const string symbolsNonTerminal[2];
NonTerminalExpression(string &symbol):m_symbol(symbol),m_type(None){}
void Interpret()
{
if (m_symbol == symbolsNonTerminal[0])
{
m_type = TypeA;
}
else if (m_symbol == symbolsNonTerminal[1])
{
m_type = TypeB;
}
else
{
m_type = None;
}
}
NonTerminalSymbolType GetResult()
{
return m_type;
}
};
const string NonTerminalExpression::symbolsNonTerminal[] = {string("symbolA"), string("symbolB")};
以下代码实现了一个解释器类。它的功能是拆分语句为符号,并根据语义使用对应的解释类去解释符号,最后根据解释的结果执行不同的动作。
class Interpretor
{
private:
string command;
void AAction()
{
cout<<__FUNCTION__<<endl;
}
void BAction()
{
cout<<__FUNCTION__<<endl;
}
public:
Interpretor(string &cmd):command(cmd){}
static string RemoveSpace(const string &str)
{
for (int i = 0; i < str.length(); ++i)
{
if (str[i] != L' ')
{
if (i > 0)
{
return str.substr(i, str.length()-i);
}
break;
}
}
return str;
}
void Execute()
{
string cmd(RemoveSpace(command));
string symbolNonTerminal;
string symbolTerminal;
for (int i = 0; i < cmd.length(); ++i)
{
if (cmd[i] == L' ')
{
symbolNonTerminal = cmd;
symbolNonTerminal.resize(i);
cmd = RemoveSpace(cmd.substr(i, cmd.length()-i));
break;
}
}
if (cmd.length() > 0)
{
symbolTerminal = cmd.substr(0, 1);
}
if (symbolNonTerminal.length() > 0 && symbolTerminal.length() > 0)
{
TerminalExpression TE(symbolTerminal);
TE.Interpret();
if (TE.IsValid())
{
NonTerminalExpression NTE(symbolNonTerminal);
NTE.Interpret();
NonTerminalSymbolType type = NTE.GetResult();
switch (type)
{
case TypeA:
AAction();
break;
case TypeB:
BAction();
break;
case None:
break;
default:
break;
}
}
}
}
};
以下代码测试了两个符号的命令。
int main(void)
{
string cmdA("symbolA ;");
Interpretor interpretA(cmdA);
interpretA.Execute();
string cmdB("symbolB ;");
Interpretor interpretB(cmdB);
interpretB.Execute();
return 0;
}
输出
AAction
BAction