设计模式(十五)解释器

这篇具有很好参考价值的文章主要介绍了设计模式(十五)解释器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、定义

定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种行为型模式。

二、描述

解释器模式是一种使用频率相对较低但学习难度较大的设计模式,它主要用于描述如何使用面向对象语言构成一个简单的语言解释器,包含以下四个角色:
设计模式(十五)解释器1、AbstractExpression(抽象表达式)在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结表达式的公共父类。
2、TerminalExpression(终结符表达式):TerminalExpression(终结符表达式):终结符表达式是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例。通常,在一个解释器模式中只有少数几个终结符表达式类,它们的实例可以通过非终结符表达式组成较为复杂的句子。
3、NonterminalExpression(非终结符表达式):非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归的方式来完成。
4、Context(环境类):环境类又称为上下文类,它用于存储解释器之外的一些全局信息,通常临时存储了需要解释的语句。

三、例子

X公司开发了一套简单的基于字符界面的格式化指令,可以根据输入的指令在字符界面输出一些格式化内容,例如输入“LOOP 2 PRINT 杨过 SPACE SPACE PRINT 小龙女 BREAK END PRINT 郭靖 SPACE SPACE PRINT 黄蓉”,将输出以下结果:设计模式(十五)解释器其中,关键词LOOP表示循环,后面的数字表示循环次数;PRINT表示打印,后面的字符串表示打印的内容;SPACE表示空格;BREAK表示换行;END表示循环结束。每一个关键词对应一条指令,计算机程序将根据关键词执行相应的处理操作。设计模式(十五)解释器
Context:环境类

/// <summary>
/// 环境类:用于存储和操作需要解释的语句,
/// 在本实例中每一个需要解释的单词都可以称为一个动作标记(ActionToker)或命令
/// </summary>
public class Context
{
    private int index = -1;
    private string[] tokens;
    private string currentToken;

    public Context(string text)
    {
        text = text.Replace("  ", " ");
        tokens = text.Split(' ');
        NextToken();
    }

    // 获取下一个标记
    public string NextToken()
    {
        if (index < tokens.Length - 1)
        {
            currentToken = tokens[++index];
        }
        else
        {
            currentToken = null;
        }

        return currentToken;
    }

    // 返回当前的标记
    public string GetCurrentToken()
    {
        return currentToken;
    }

    // 跳过一个标记
    public void SkipToken(string token)
    {
        if (!token.Equals(currentToken, StringComparison.OrdinalIgnoreCase))
        {
            Console.WriteLine("错误提示:{0} 解释错误!", currentToken);
        }

        NextToken();
    }

    // 如果当前的标记是一个数字,则返回对应的数值
    public int GetCurrentNumber()
    {
        int number = 0;
        try
        {
            // 将字符串转换为整数
            number = Convert.ToInt32(currentToken);
        }
        catch (Exception ex)
        {
            Console.WriteLine("错误提示:{0}", ex.Message);
        }

        return number;
    }
}

Node:抽象节点类,充当抽象表达式

public abstract class Node
{
    // 声明一个方法用于解释语句
    public abstract void Interpret(Context context);
    // 声明一个方法用于执行标记对应的命令
    public abstract void Execute();
}

ExpressionNode、CommandNode、LoopCommandNode:表达式节点类、语句命令节点类、循环命令类,充当非终结符表达式

public class ExpressionNode : Node
{
    // 用于存储多条命令的集合
    private IList<Node> nodeList = new List<Node>();

    public override void Interpret(Context context)
    {
        // 循环处理Context中的标记
        while (true)
        {
            // 如果已经没有任何标记,则退出解释
            if (context.GetCurrentToken() == null)
            {
                break;
            }
            // 如果标记为END,则不解释END并结束本次解释过程,可以继续之后的解释
            else if (context.GetCurrentToken().Equals("END", StringComparison.OrdinalIgnoreCase))
            {
                context.SkipToken("END");
                break;
            }
            // 如果为其它标记,则解释标记并加入命令集合
            else
            {
                Node node = new CommandNode();
                node.Interpret(context);
                nodeList.Add(node);
            }
        }
    }

    // 循环执行命令集合中的每一条指令
    public override void Execute()
    {
        foreach (var node in nodeList)
        {
            node.Execute();
        }
    }
}

public class CommandNode : Node
{
    private Node node;

    public override void Interpret(Context context)
    {
        // 处理LOOP指令
        if (context.GetCurrentToken().Equals("LOOP", StringComparison.OrdinalIgnoreCase))
        {
            node = new LoopCommand();
            node.Interpret(context);
        }
        // 处理其他指令
        else
        {
            node = new PrimitiveCommand();
            node.Interpret(context);
        }
    }

    public override void Execute()
    {
        node.Execute();
    }
}

public class LoopCommand : Node
{
    // 循环次数
    private int number;
    // 循环语句中的表达式
    private Node commandNode;

    public override void Interpret(Context context)
    {
        context.SkipToken("LOOP");
        number = context.GetCurrentNumber();
        context.NextToken();
        // 循环语句中的表达式
        commandNode = new ExpressionNode();
        commandNode.Interpret(context);
    }

    public override void Execute()
    {
        for (int i = 0; i < number; i++)
        {
            commandNode.Execute();
        }
    }
}

PrimitiveCommandNode:基本命令类,充当终结符表达式

public class PrimitiveCommand : Node
{
    private string name;
    private string text;

    public override void Interpret(Context context)
    {
        name = context.GetCurrentToken();
        context.SkipToken(name);

        if (!name.Equals("PRINT", StringComparison.OrdinalIgnoreCase) 
            && !name.Equals("BREAK", StringComparison.OrdinalIgnoreCase)
            && !name.Equals("SPACE", StringComparison.OrdinalIgnoreCase))
        {
            Console.WriteLine("非法命令!");
        }

        if (name.Equals("PRINT", StringComparison.OrdinalIgnoreCase))
        {
            text = context.GetCurrentToken();
            context.NextToken();
        }
    }

    public override void Execute()
    {
        if (name.Equals("PRINT", StringComparison.OrdinalIgnoreCase))
        {
            Console.Write(text);
        }
        else if (name.Equals("SPACE", StringComparison.OrdinalIgnoreCase))
        {
            Console.Write(" ");
        }
        else if (name.Equals("BREAK", StringComparison.OrdinalIgnoreCase))
        {
            Console.Write("\r\n");
        }
    }
}

Program:客户端测试类

string instruction = "LOOP 2 PRINT 杨过 SPACE SPACE PRINT 小龙女 BREAK END PRINT 郭靖 SPACE SPACE PRINT 黄蓉";
Context context = new Context(instruction);

Node node = new ExpressionNode();
node.Interpret(context);

Console.WriteLine("源指令 : {0}", instruction);
Console.WriteLine("解释后 : ");

node.Execute();
Console.ReadLine();

设计模式(十五)解释器

四、总结

1、优点

(1)解释器模式易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
(2)在解释器模式中,每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
(3)实现文法较为容易。在抽象语法树中每一个表达式结点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成结点类代码。
(4)增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合开闭原则。

2、缺点

(1)解释器模式对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义-个类,因此如果一个语言包含太多的文法规则,类的个数将会急剧增加,从而导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
(2)其执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。文章来源地址https://www.toymoban.com/news/detail-747345.html

到了这里,关于设计模式(十五)解释器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式详解-解释器模式

    类型:行为型模式 实现原理:实现了一个表达式接口,该接口使用标识来解释语言中的句子 作用:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器来解释。 主要解决:一些重复的固定文法分别创建解释器会很麻烦 何时使用:某一种特定类型的问题发生的

    2024年02月12日
    浏览(38)
  • 解释器设计模式

    解释器设计模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法,并建立一个解释器来解释该语言中的句子。这种模式通常用于需要解释或执行一种特定类型的语言的场景,例如编程语言的编译器或解释器、规则引擎系统等。 关键组成部分 抽象表达式(

    2024年02月21日
    浏览(38)
  • 设计模式(行为型模式)解释器模式

       解释器模式(Interpreter Pattern) 是一种行为设计模式,用于解释特定语言或处理特定问题领域的语法或表达式。它定义了一种语言的语法表示,并使用该表示来解释语言中的句子。通常用于构建解析器、编译器和规则评估引擎等场景。 在解释器模式中,有以下关键角色:

    2024年02月20日
    浏览(33)
  • js设计模式:解释器模式

    对文本进行解释和编译的时候,就会用到解释器模式 比如你写了一段js代码,js引擎就会去解释并执行这段代码 webpack中的各种loader就是用来解释各种文件类型的,并将其解释为js可识别的代码

    2024年02月22日
    浏览(31)
  • 设计模式之解释器模式(下)

    3)Context的作用 1.概述 在解释器模式中,环境类Context用于存储解释器之外的一些全局信息,它通常作为参数被传递到所有表达式的解释方法interpret()中,可以在Context对象中存储和访问表达式解释器的状态,向表达式解释器提供一些全局的、公共的数据,此外还可以在Context中

    2024年04月12日
    浏览(30)
  • 设计模式之解释器模式笔记

    记录下学习设计模式-解释器模式的写法。JDK使用版本为1.8版本。 意图 :定义一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 结构 : 其中: AbstractExpression 声明一个程序的解释操作,这个接口为抽象语法树中所有的结点所

    2024年02月11日
    浏览(34)
  • Java设计模式-解释器模式

    一、概述 如上图,设计一个软件用来进行加减计算。我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。 上面的形式比较单一、有限,如果形式变化非常多,这就不符合要求,因为加法和减法运算,两个运算符与数值可以有无限种组合方式。比如 1+2+3+4+5、

    2024年01月17日
    浏览(28)
  • 解锁Spring Boot中的设计模式—02.解释器模式:探索【解释器模式】的奥秘与应用实践!

    解释器模式(Interpreter Pattern)是一种行为设计模式,它用于定义语言的文法,并且解释语言中的表达式。在Java中,解释器模式可以用于构建解释器以解析特定的语言或表达式,如数学表达式、查询语言等。 优点: 灵活性: 解释器模式可以 灵活地添加新的表达式和规则 ,因

    2024年02月19日
    浏览(39)
  • Unity实现设计模式——解释器模式

    解释器模式(Interpreter Pattern)是一种按照规定语法进行解析的模式,现实项目中用得较少。 给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。 下面用一个例子演示:将罗马文字转换为十进制的格式 解释器基类 千位数

    2024年02月07日
    浏览(29)
  • java设计模式之解释器模式

    1.基本介绍 在编译原理中,一个算术表达式通过词法分析器形成词法单远,而这些词法单远再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树,(词法分析器和语法分析器都可以看做是解释器) 解释器模式是指给定一个语言(表达式),定义它的文法的一种

    2024年02月19日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包