十五、Interpreter(解释器)
情景举例:
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
代码示例:
/* 该例子以布尔表达式的文法为例,文法如下:
BooleanExp = VariableExp|Constant|OrExp|AndExp|NotExp|’(BooleanExp)’
AndExp = BooleanExp ‘and’ BooleanExp
OrExp = BooleanExp ‘or’ BooleanExp
NotExp = ‘not’ BooleanExp
Constant = true|false
VariableExp = A|B|C|……|X|Y|Z
*/
/* 所有布尔运算的公共父类
*/
class BooleanExp {
public:
BooleanExp();
virtual ~BooleanExp();
/*
*/
virtual bool Evaluate(Context&) = 0;
virtual BooleanExp* Replace(const char*, BooleanExp&) = 0;
virtual BooleanExp* Copy() const = 0;
};
/* 这个类保存了VariableExp到布尔值的映射(与整体结构无关,仅为实现方便)
*/
class Context {
public:
bool Lookup(const char*) const;
void Assign(VariableExp*, bool);
};
/* VariableExp的类声明
*/
class VariableExp : public BooleanExp {
public:
VariableExp(const char*);
virtual ~VariableExp();
/*
*/
virtual bool Evaluate(Context&);
virtual BooleanExp* Replace(const char*, BooleanExp&);
virtual BooleanExp* Copy() const;
private:
char* _name;
};
/* VariableExp由一个名字(从A到Z)作为构造函数参数,并在计算结果时直
* 接根据名字从上下文Lookup出一个布尔值
*/
VariableExp::VariableExp (const char* name) {
_name = strdup(name);
}
/*
*/
bool VariableExp::Evaluate (Context& aContext) {
return aContext.Lookup(_name);
}
/*
*/
BooleanExp* VariableExp::Copy () const {
return new VariableExp(_name);
}
/* Replace的时候当发现待替换变量名就是本对象名时才执行替换,否则直接
* 返回本对象
*/
BooleanExp* VariableExp::Replace (
const char* name, BooleanExp& exp
) {
if (strcmp(name, _name) == 0) {
return exp.Copy();
} else {
return new VariableExp(_name);
}
}
/* “与”操作,其实现基本上递归调用左右2个操作数
*/
class AndExp : public BooleanExp {
public:
AndExp(BooleanExp*, BooleanExp*);
virtual ~ AndExp();
/*
*/
virtual bool Evaluate(Context&);
virtual BooleanExp* Replace(const char*, BooleanExp&);
virtual BooleanExp* Copy() const;
private:
BooleanExp* _operand1;
BooleanExp* _operand2;
};
/*
*/
AndExp::AndExp (BooleanExp* op1, BooleanExp* op2) {
_operand1 = op1;
_operand2 = op2;
}
/*
*/
bool AndExp::Evaluate (Context& aContext) {
return
_operand1->Evaluate(aContext) &&
_operand2->Evaluate(aContext);
}
/*
*/
BooleanExp* AndExp::Copy () const {
return
new AndExp(_operand1->Copy(), _operand2->Copy());
}
/*
*/
BooleanExp* AndExp::Replace (const char* name, BooleanExp& exp) {
return
new AndExp(
_operand1->Replace(name, exp),
_operand2->Replace(name, exp)
);
}
/* 下面是常数、或操作、否操作的接口,其实现略
*/
class Constant : public BooleanExp {
public:
Constant(int v) { _value = v; };
virtual bool Evaluate(Context&);
virtual BooleanExp* Replace(const char*, BooleanExp&);
virtual BooleanExp* Copy() const;
private:
int _value;
};
class OrExp : public BooleanExp {
public:
OrExp(BooleanExp*, BooleanExp*);
virtual ~ OrExp();
virtual bool Evaluate(Context&);
virtual BooleanExp* Replace(const char*, BooleanExp&);
virtual BooleanExp* Copy() const;
private:
BooleanExp* _operand1;
BooleanExp* _operand2;
};
class NotExp : public BooleanExp {
public:
NotExp(BooleanExp*);
virtual ~ NotExp();
virtual bool Evaluate(Context&);
virtual BooleanExp* Replace(const char*, BooleanExp&);
virtual BooleanExp* Copy() const;
private:
BooleanExp* _operand;
};
main () {
/* 主程序中定义表达式:(true and x) or (y and (not x))
*/
BooleanExp* expression;
Context context;
VariableExp* x = new VariableExp("X");
VariableExp* y = new VariableExp("Y");
expression = new OrExp(
new AndExp(new Constant(true), x),
new AndExp(y, new NotExp(x))
);
/* 对x,y赋值然后计算结果
*/
context.Assign(x, false);
context.Assign(y, true);
bool result = expression->Evaluate(context);
/* 用not z代替原先的y然后重新计算
*/
BooleanExp* replacement;
VariableExp* z = new VariableExp("Z");
replacement = new NotExp(z);
expression->Replace("Y", *replacement);
context.Assign(z, true);
result = expression ->Evaluate(context);
/*
*/
}
个人理解:
解释器模式中,非终结符与终结符都继承自公共的抽象父类。非终结符的操作部分递归调用直至终结符完成整个操作。而另外一个比较难懂晦涩的地方就是Context类,该类映射了具体语法在上下文中的具体取值,可以看到在模式结构中,各解释器类都以该类作参数。