类图]]
在计算机编程中,解释器模式(),是一种设计模式,它规定了如何求值一个语言中的句子。基本想法是使专门计算机语言的每个符号(终结符与非终结符)都有一个类。这个语言中句子的语法树是合成模式的一个实例,它被用来为客户求值(解释)这个句子。
结构
在上面的UML类图中:
*客户Client类提及公共的AbstractExpression接口来解释一个表达式interpret(context)。
*终结表达式TerminalExpression类没有子表达式并且直接解释一个表达式。
*非终结表达式NonTerminalExpression类维护一个子表达式的容器(expressions)并且将解释请求转发给这些expressions。
对象图展示了运行时交互:
*客户Client对象发送解释请求到抽象语法树。这个请求被沿着树结构转发到(办理于)所有对象。
*非终结表达式NonTerminalExpression对象(ntExpr1,ntExpr2)将请求转发到它们的子表达式。
*终结表达式TerminalExpression对象(tExpr1,tExpr2,…)直接的进行解释。
示例
C++
下面的例子是基于《设计模式》书中先于C++98的样例代码的C++23实现:
import std;
using String = std::string;
template
using TreeMap = std::map;
template
using UniquePtr = std::unique_ptr;
class BooleanExpression {
public:
BooleanExpression() = default;
virtual ~BooleanExpression() = default;
virtual bool evaluate(Context&) = 0;
virtual UniquePtr replace(String&, BooleanExpression&) = 0;
virtual UniquePtr copy() const = 0;
};
class VariableExpression;
class Context {
private:
TreeMap m;
public:
Context() = default;
nodiscard
bool lookup(const VariableExpression* key) const {
return m.at(key);
}
void assign(VariableExpression* key, bool value) {
m[key] = value;
}
};
class VariableExpression : public BooleanExpression {
private:
String name;
public:
VariableExpression(const String& name):
name{name} {}
virtual ~VariableExpression() = default;
nodiscard
virtual bool evaluate(Context& context) const {
return context.lookup(this);
}
nodiscard
virtual UniquePtr replace(const String& name, BooleanExpression& exp) {
if (this->name == name) {
return std::make_unique(exp.copy());
} else {
return std::make_unique(name);
}
}
nodiscard
virtual UniquePtr copy() const {
return std::make_unique(name);
}
VariableExpression(const VariableExpression&) = delete;
VariableExpression& operator=(const VariableExpression&) = delete;
};
class AndExpression : public BooleanExpression {
private:
UniquePtr operand1;
UniquePtr operand2;
public:
AndExpression(UniquePtr op1, UniquePtr op2):
operand1{std::move(op1)}, operand{std::move(op2)} {}
virtual ~AndExpression() = default;
nodiscard
virtual bool evaluate(Context& context) const {
return operand1->evaluate(context) && operand2->evaluate(context);
}
nodiscard
virtual UniquePtr replace(const String& name, BooleanExpression& exp) const {
return std::make_unique(
operand1->replace(name, exp),
operand2->replace(name, exp)
);
}
nodiscard
virtual UniquePtr copy() const {
return std::make_unique(operand1->copy(), operand2->copy());
}
AndExpression(const AndExpression&) = delete;
AndExpression& operator=(const AndExpression&) = delete;
};
int main(int argc, char* argv[]) {
UniquePtr expression;
Context context;
UniquePtr x = std::make_unique("X");
UniquePtr y = std::make_unique("Y");
UniquePtr expression; = std::make_unique(x, y);
context.assign(x.get(), false);
context.assign(y.get(), true);
bool result = expression->evaluate(context);
std::println("{}", result);
context.assign(x.get(), true);
context.assign(y.get(), true);
result = expression->evaluate(context);
std::println("{}", result);
return 0;
}
程序输出为:
0
1
Python
下面是Python的例子:
from abc import ABC, abstractmethod
class Context():
def __init__(self):
self.var_dict = {}
def lookup(self, var):
return (self.var_dict[var.name]
if var.name in self.var_dict else None)
def assign(self, var, value):
self.var_dict[var.name] = value
class BooleanExp(ABC):
@abstractmethod
def evaluate(self): pass
@abstractmethod
def replace(self): pass
@abstractmethod
def copy(self): pass
class VariableExp(BooleanExp):
def __init__(self, context, name, value=None):
self.context = context
self.name = name
if value is not None:
self.context.assign(self, value)
def __str__(self):
return f"({self.name})"
def evaluate(self):
return self.context.lookup(self)
def replace(self, var, exp):
return (exp.copy() if self.name == var.name
else self.copy())
def copy(self):
return type(self)(self.context, self.name)
class AndExp(BooleanExp):
def __init__(self, opd1, opd2):
self.opd1 = opd1
self.opd2 = opd2
def __str__(self):
return f"({self.opd1} and {self.opd2})"
def evaluate(self):
opd1 = self.opd1.evaluate()
opd2 = self.opd2.evaluate()
return opd1 and opd2
def replace(self, var, exp):
opd1 = self.opd1.replace(var, exp)
opd2 = self.opd2.replace(var, exp)
return type(self)(opd1, opd2)
def copy(self):
opd1 = self.opd1.copy()
opd2 = self.opd2.copy()
return type(self)(opd1, opd2)
def demo():
context = Context()
x = VariableExp(context, "X", False)
y = VariableExp(context, "Y", True)
exp = AndExp(x, y)
print(exp)
print(exp.evaluate())
context.assign(x, True)
z = VariableExp(context, "Z")
context.assign(z, exp.evaluate())
print(context.lookup(z))
exp1 = exp.replace(x, z)
print(exp1)
print(exp1.evaluate())
context.assign(z, False)
print(exp1.evaluate())
其输出:
>> demo()
((X) and (Y))
False
True
((Z) and (Y))
True
False
参见
- 巴科斯-诺尔范式
- 组合子逻辑
- 解释器
引用
外部链接
- [http://lukaszwrobel.pl/blog/interpreter-design-pattern Interpreter implementation] in Ruby
- [https://github.com/jamesdhutton/Interpreter Interpreter implementation] in C++
- [http://sourcemaking.com/design_patterns/interpreter SourceMaking tutorial]
- [http://c2.com/cgi/wiki?InterpreterPattern Interpreter pattern description from the Portland Pattern Repository]
评论 (0)