第27章:解释器模式
解释器模式
解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
AbstractExpression
(抽象表达式):声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
TerminalExpression
(终结符表达式):实现与文法中的终结符相关联的解释操作。实现抽象表达式中所要求的接口,主要是一个interpret()
方法。文法中每一个终结符都有一个具体终结表达式与之相对应。
NonterminalExpression
(非终结符表达式):为文法中的非终结符实现解释操作。对文法中每一条规则R1、R2……Rn
都需要一个具体的非终结符表达式类。通过实现抽象表达式的interpret()
方法实现解释操作。解释操作以递归方式调用上面所提到的代表R1、R2……Rn
中各个符号的实例变量。
Context
:包含解释器之外的一些全局信息。
客户端代码,构建表示该文法定义的语言中一个特定的句子的抽象语法树。调用解释操作。
结果显示
解释器模式好处
当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
解释器模式的优点:使用解释器模式意味着可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。
只要是可以用语言来描述的,都可以解释器模式,例正则表达式、浏览器等应用。
解释器模式就是将一句话,转变成实际的命令程序执行。不用解释器模式本来也可以分析,但通过继承抽象表达式的方式,由于依赖倒转原则,使得对文法的扩展和维护都带来了方便。
解释器模式的不足:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。
解释器模式示例
任务:乐谱解释器
规则:
-
O
表示音阶:O 1
表示低音阶,O 2
表示中音阶,O 3
表示高音阶; -
P
表示休止符; -
C D E F G A B
表示Do-Re-Mi-Fa-So-La-Ti
; -
音符长度1表示一拍,2表示二拍,0.5表示半拍,0.25 表示四分之一拍,以此类推
所有的字母和数字都要用半角空格分开。例如上海滩的歌曲第一句,‘浪奔’,可以写成O 2 E 0.5 G 0.5 A 3
表示中音开始,演奏的是mi so la
。
from abc import ABCMeta, abstractmethod
from typing import Text
# import pdb
class PlayContext(object):
"""
演奏内容(Context)类
"""
def __init__(self) -> None:
self.__text = None
@property
def play_text(self) -> Text:
return self.__text
@play_text.setter
def play_text(self, value: Text) -> None:
self.__text = value
class Expression(metaclass=ABCMeta):
"""
表达式(AbstractExpression)类
"""
def interpret(self, context: PlayContext) -> None:
"""
解析演奏文本第一条命令,获得命令字母及其参数值。
例:“O 3 E 0.5 G 0.5 A 3”,则playKey为O、playValue为3
"""
if len(context.play_text) == 0:
return
else:
play_key = context.play_text[0]
context.play_text = context.play_text[2 :]
play_value = context.play_text[0 : context.play_text.find(" ")]
play_value = float(play_value)
context.play_text = context.play_text[context.play_text.find(" ") + 1 : ]
self.execute(play_key, play_value)
@abstractmethod
def execute(self, key: Text, value: float) -> None:
pass
class Note(Expression):
"""
音符(TerminalExpression)类
"""
_note_map = {
"C": "do", "D": "re", "E": "mi", "F": "fa",
"G": "so", "A": "la", "B": "ti"
}
def execute(self, key: Text, value: float) -> None:
note = self._note_map.get(key)
print(note, value)
class Scale(Expression):
"""
音阶(TerminalExpression)类
"""
_scale_map = {
1: "低音", 2: "中音", 3: "高音"
}
def execute(self, key: Text, value: float) -> None:
scale = self._scale_map.get(value)
print(scale)
class ExpressionFactory(object):
"""
表达示工厂类
"""
_switch = {
"CDEFGAB": Note(),
"O": Scale(),
}
def create_interpreter(self, value: Text) -> Expression:
for key, inpt in self._switch.items():
if value in key:
return inpt
# 客户端代码
if __name__ == "__main__":
context = PlayContext()
# 音乐 - 上海滩
print("上海滩:")
context.play_text = "O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 "
expression = None
factory = ExpressionFactory()
try:
while len(context.play_text) > 0:
char = context.play_text[0]
# print(char)
# pdb.set_trace()
expression = factory.create_interpreter(char)
expression.interpret(context)
except Exception as e:
raise e
上海滩:
中音
mi 0.5
so 0.5
la 3.0
mi 0.5
so 0.5
re 3.0
mi 0.5
so 0.5
la 0.5
高音
do 1.0
中音
la 0.5
so 1.0
do 0.5
mi 0.5
re 3.0
增加一个文法
- 演奏速度,
T
代表速度,以亳秒为单位,T 1000
表示每节拍一秒、T 500
表示每节拍半秒。
class Speed(Expression):
"""
音速(TerminalExpression)类
"""
def execute(self, key: Text, value: float) -> None:
speed = None
if value < 500:
speed = "快速"
elif value >= 1000:
speed = "慢速"
else:
speed = "中速"
print(speed)
class ExpressionFactory(object):
"""
表达示工厂类
"""
_switch = {
"CDEFGAB": Note(),
"O": Scale(),
"T": Speed()
}
def create_interpreter(self, value: Text) -> Expression:
for key, inpt in self._switch.items():
if value in key:
return inpt
# 客户端代码
if __name__ == "__main__":
context = PlayContext()
# 音乐 - 上海滩
print("上海滩:")
context.play_text = "T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 "
expression = None
factory = ExpressionFactory()
try:
while len(context.play_text) > 0:
char = context.play_text[0]
# print(char)
# pdb.set_trace()
expression = factory.create_interpreter(char)
expression.interpret(context)
except Exception as e:
raise e
上海滩:
中速
中音
mi 0.5
so 0.5
la 3.0
mi 0.5
so 0.5
re 3.0
mi 0.5
so 0.5
la 0.5
高音
do 1.0
中音
la 0.5
so 1.0
do 0.5
mi 0.5
re 3.0