大话设计模式:第27章 解释器模式

第27章:解释器模式

解释器模式

解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

在这里插入图片描述

AbstractExpression(抽象表达式):声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。

在这里插入图片描述

TerminalExpression(终结符表达式):实现与文法中的终结符相关联的解释操作。实现抽象表达式中所要求的接口,主要是一个interpret()方法。文法中每一个终结符都有一个具体终结表达式与之相对应。

在这里插入图片描述

NonterminalExpression(非终结符表达式):为文法中的非终结符实现解释操作。对文法中每一条规则R1、R2……Rn都需要一个具体的非终结符表达式类。通过实现抽象表达式的interpret()方法实现解释操作。解释操作以递归方式调用上面所提到的代表R1、R2……Rn中各个符号的实例变量。

在这里插入图片描述

Context:包含解释器之外的一些全局信息。

在这里插入图片描述

客户端代码,构建表示该文法定义的语言中一个特定的句子的抽象语法树。调用解释操作。

在这里插入图片描述

结果显示

在这里插入图片描述

解释器模式好处

当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。

解释器模式的优点:使用解释器模式意味着可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。

只要是可以用语言来描述的,都可以解释器模式,例正则表达式、浏览器等应用。

解释器模式就是将一句话,转变成实际的命令程序执行。不用解释器模式本来也可以分析,但通过继承抽象表达式的方式,由于依赖倒转原则,使得对文法的扩展和维护都带来了方便。

解释器模式的不足:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。

解释器模式示例

任务:乐谱解释器

规则:

  1. O表示音阶:O 1表示低音阶,O 2表示中音阶,O 3表示高音阶;

  2. P表示休止符;

  3. C D E F G A B表示Do-Re-Mi-Fa-So-La-Ti

  4. 音符长度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

增加一个文法

  1. 演奏速度,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

猜你喜欢

转载自blog.csdn.net/zhaoyin214/article/details/106055790