解释器模式——自定义语言的实现

news2024/11/19 3:48:59

1、简介

1.1、文法规则和抽象语法树

解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。在正式分析解释器模式结构之前,先来学习如何表示一个语言的文法规则以及如何构造一棵抽象语法树。

加法/减法解释器中,每个输入表达式,例如“1+2+3-4+1”,都包含了3个语言单位,可以使用如下文法规则来定义:

exression::=value|opoeration
opoeration::=opoeration'+'opoeration|opoeration'-'opoeration
value::=an integer // 一个整数值

该文法规则包含3条语句。第一条表示表达式的组成方式,其中value和operation是后面两个语言单位的定义。每一条语句所定义的字符串如operation和value称为语言构造成分或语言单位。符号“∷=”表示“定义为”的意思,其左边的语言单位通过右边来进行说明和定义,语言单位对应终结符表达式和非终结符表达式。例如,本规则中的operation是非终结符表达式,它的组成元素仍然可以是表达式,可以进一步分解;而value是终结符表达式,它的组成元素是最基本的语言单位,不能再进行分解。

在文法规则定义中可以使用一些符号来表示不同的含义,例如使用“|”表示或,使用“{”和“}”表示组合,使用“∗”表示出现0次或多次等。其中,使用频率最高的符号是表示或关系的“|”,例如,文法规则“boolValue∷=0|1”表示终结符表达式boolValue的取值可以为0或者1。

除了使用文法规则来定义一个语言外,还可以通过一种被称为抽象语法树(Abstract Syntax Tree,AST)的图形方式来直观地表示语言的构成。每一棵抽象语法树对应一个语言实例,例如加法/减法表达式语言中的语句“1+2+3-4+1”,可以通过如下图所示抽象语法树来表示。
在这里插入图片描述
在该抽象语法树中,可以通过终结符表达式value和非终结符表达式operation组成复杂的语句。每个文法规则的语言实例都可以表示为一个抽象语法树,即每一条具体的语句都可以用类似图18-2所示的抽象语法树来表示。在图中终结符表达式类的实例作为树的叶子节点,而非终结符表达式类的实例作为非叶子节点,它们可以将终结符表达式类的实例以及包含终结符和非终结符实例的子表达式作为其子节点。抽象语法树描述了如何构成一个复杂的句子。通过对抽象语法树的分析,可以识别出语言中的终结符类和非终结符类。

1.2、概述

像C++、Java和C#等语言无法直接解释类似“1+2+3-4+1”这样的字符串(如果直接作为数值表达式时可以解释),用户必须自己定义一套文法规则来实现对这些语句的解释,即设计一个自定义语言。在实际开发中,这些简单的自定义语言可以基于现有的编程语言来设计。如果所基于的编程语言是面向对象语言,此时可以使用解释器模式来实现自定义语言。

解释器模式是一种使用频率相对较低但学习难度较大的设计模式,它用于描述如何使用面向对象语言构成一个简单的语言解释器。在某些情况下,为了更好地描述某些特定类型的问题,可以创建一种新的语言。这种语言拥有自己的表达式和结构,即文法规则,这些问题的实例将对应为该语言中的句子。此时,可以使用解释器模式来设计这种新的语言。对解释器模式的学习能够加深对面向对象思想的理解,并且掌握编程语言中文法规则的解释过程。

1.3、定义

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

2、解析

2.1、UML类图

由于表达式可分为终结符表达式和非终结符表达式,因此解释器模式的结构与组合模式的结构有些类似,但在解释器模式中包含更多的组成元素,其结构如下图所示。
在这里插入图片描述
可以看出,在解释器模式结构图中包含以下4个角色:

  1. AbstractExpression(抽象表达式):在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类。
  2. TerminalExpression(终结符表达式):是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例。通常,在一个解释器模式中只有少数几个终结符表达式类,它们的实例可以通过非终结符表达式组成较为复杂的句子。
  3. NonterminalExpression(非终结符表达式):也是抽象表达式的子类,它实现了文法中非终结符的解释操作。由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归的方式来完成。
  4. Context(环境类):环境类又称为上下文类,它用于存储解释器之外的一些全局信息,通常它临时存储了需要解释的语句。

2.2、代码示例

在解释器模式中,每一种终结符和非终结符都有一个具体类与之对应。正因为使用类来表示每一条文法规则,所以系统将具有较好的灵活性和可扩展性。对于所有的终结符和非终结符,首先需要抽象出一个公共父类,即抽象表达式类,其典型代码如下:

/**
 * @Description: 抽象表达式类
 * @Author: yangyongbing
 * @CreateTime: 2023/08/02  12:51
 * @Version: 1.0
 */
abstract class AbstractExpression {
    public abstract void interpret(Context context);

}

终结符表达式和非终结符表达式类都是抽象表达式类的子类。对于终结符表达式,其代码很简单,主要是对终结符元素的处理,其典型代码如下:

/**
 * @Description: 终结符表达式
 * @Author: yangyongbing
 * @CreateTime: 2023/08/02  12:56
 * @Version: 1.0
 */
public class TerminalExpression extends AbstractExpression{
    @Override
    public void interpret(Context context) {

    }
}

对于非终结符表达式,其代码相对比较复杂,因为可以通过非终结符将表达式组合成更加复杂的结构。对于包含两个操作元素的非终结符表达式类,其典型代码如下:

/**
 * @Description: 非终结符表达式类
 * @Author: yangyongbing
 * @CreateTime: 2023/08/02  12:58
 * @Version: 1.0
 */
public class NonterminalExpression extends AbstractExpression {

    private AbstractExpression left;
    private AbstractExpression right;

    public NonterminalExpression(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public void interpret(Context context) {
        // 递归调用每一个组成部分的interpret()方法
        // 在递归调用时指定组成部分的连接方式,即非终结符的功能
    }
}

除了上述用于表示表达式的类以外,通常在解释器模式中还提供了一个环境类Context,用于存储一些全局信息。在Context中可以包含一个HashMap或ArrayList等类型的集合对象(也可以直接由HashMap等集合类充当环境类)来存储一系列公共信息,例如变量名与值的映射关系(key/value)等,用于在进行具体的解释操作时从中获取相关信息。其典型代码片段如下:

import java.util.HashMap;

/**
 * @Description: 环境类
 * @Author: yangyongbing
 * @CreateTime: 2023/08/02  12:53
 * @Version: 1.0
 */
public class Context {
    private HashMap map = new HashMap();

    public void assign(String key, String value) {
        // 往环境类中设值
    }

    public String lookup(String key) {
        // 获取存储在环境类中的值
    }
}

当系统无须提供全局公共信息时可以省略环境类,也可根据实际情况决定是否需要环境类。

3、解释器模式总结

解释器模式为自定义语言的设计和实现提供了一种解决方案,它用于定义一组文法规则并通过这组文法规则来解释语言中的句子。虽然解释器模式的使用频率不是特别高,但是它在正则表达式、XML文档解释等领域还是得到了广泛使用。与解释器模式类似,目前还诞生了很多基于抽象语法树的源代码处理工具。例如Eclipse中的Eclipse AST,它可以用于表示Java语言的语法结构,用户可以通过扩展其功能,创建自己的文法规则。

3.1、主要优点

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

3.2、主要缺点

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

3.3、适用场景

(1)可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
(2)一些重复出现的问题可以用一种简单的语言来进行表达。
(3)一个语言的文法较为简单。
(4)执行效率不是关键问题。
:高效的解释器通常不是通过直接解释抽象语法树来实现的,而是需要将它们转换成其他形式,使用解释器模式的执行效率并不高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/826335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows 同时安装 Mysql 5.7 和8.0

下载链接 https://dev.mysql.com/downloads/mysql/ 推荐下载 MSI,可以通过图像化界面配置 8.1 版本 安装5.7 系统安装两个MySQL 怎么访问 都是mysql,所以环境变量 配置,只能一个生效,生效就是谁靠前谁生效 cmd 录入 services.m…

【LeetCode】647. 回文子串

题目链接 文章目录 1. 思路讲解1.1 方法选择1.2 dp表的创建1.3 状态转移方程1.4 填表顺序 2. 代码实现 1. 思路讲解 1.1 方法选择 这道题我们采用动态规划的解法,倒不是动态规划的解法对于这道题有多好,它并不是最优解。但是,这道题的动态…

给你一个小技巧,解放办公室管理!

电力的稳定供应对于现代社会中的办公室和企业来说至关重要。为了应对这些潜在的问题,许多办公室和企业都采用了不间断电源(UPS)系统来提供电力备份。UPS可以保持关键设备的运行,确保生产和业务不受干扰。 然而,仅仅安装…

【读书笔记】CHAPTER 1: SCALE FROM ZERO TO MILLIONS OF USERS

如果你有一定工作经验,或者开发项目基础,就看这个图就可以。 一个“从零扩展到数百万用户”系统,基本由上述部分组成: web、app:触达用户的设备(页面) DNS:用户看到的都是域名(ww…

2023年还能选择前端吗?

前言 在Github2022的 Octoverse年度报告上,稳居最多使用榜首的语言可以看到是JavaScript,作为前端中最为关键的一部分,这说明即使现在,前端这一块仍然是大量的人涌进来,依然是火热,但是,一门语…

【Vue3项目实战】vue3项目配置页面切换过渡动画

文章目录 一、先看效果二、全量代码三、注意事项虽然Vue3支持 template 下存在多个根节点,但是 transition 过渡动画并不支持,要实现过渡动画的页面,都需要有一个根标签包裹页面内容,否则就会报如下警告: 四、相关文章友链本专栏记…

《吐血整理》高级系列教程-吃透Fiddler抓包教程(22)-如何使用Fiddler生成Jmeter脚本-下篇

1.简介 今天这篇文章其实和上一篇差不多也是利用一个fiddler的插件进行Jmeter脚本的导出,开始宏哥想要合在一起写一篇文章,可是结果实践的时候,两个插件还是有区别的,因此为了不绕晕小伙伴或者童鞋们,决定分为两篇进行…

结构思考力-有效提升你的工作效率20倍以上

结构思考力是一种帮助人们察觉并改善自身思考结构的思考艺术,它将人们的思维表达以一种逻辑结构的形式来表示,从而简化人与人之间的沟通成本,提高工作效率。每个人思考问题的方式不同,不同的思考结构使人们的注意力的方向也不同&a…

Linux运维面试题(三)之数据库管理

Linux运维面试题(三)之数据库管理 1. SQL语句2.集群主从服务器原理主从故障切换单台Mysql达到性能瓶颈时,如何处理 3.索引(软优化)什么是索引索引的分类劣势(优点:效率和减少数据表内排序和随机…

VMWare虚拟系统上网设置及VMWare虚拟机三种工作模式详解

很多网友安装了VMWare虚拟机,但是在虚拟机上网问题上却卡住了。要想虚拟机上网,首先让我们了解一下VMWare虚拟机三种工作模式。现在,让我们一起走近VMWare的三种工作模式。 理解三种工作模式 …

商海风云起 张俪高瀚宇上演巅峰对决《越过山丘》登陆湖北卫视

彩虹与风雨共生,机遇与挑战并存。由沈煜杰执导,张俪、高瀚宇、蒋冰、周奇奇、柳小海、陈牧扬、张杨智子领衔主演的都市励志情感剧《越过山丘》,将于今晚(8月2日)19:30起,登陆湖北卫视长江剧场。 电视剧《越…

Python系统学习1-2

目录 一、硬件 二、软件:程序文档 三、基础知识 四、python执行过程 五、Pycharm使用技巧 一、硬件 计算机五大部件:运算器,存储器,控制器、输入设备,输出设备。 运算器和控制器 集成在CPU中。 存储&#xff1a…

省份数量(力扣)深度优先 JAVA

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市c 间接相连。 省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。 给你一个 …

python项目开发案例集锦,python项目案例代码

这篇文章主要介绍了python项目开发案例集锦(全彩版),具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获,下面让小编带着大家一起了解一下。 前言 22个通过Python构建的项目,以此来学习Python编程。 ① 骰…

2023年华数杯建模思路 - 案例:随机森林

## 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林? 随机森林属于 集成学习 中的 Bagging(Bootstrap AGgregation 的简称) 方法。如果用图来表示他们之…

vue 3.0 + element-ui MessageBox弹出框的 让文本框显示文字 placeholder

inputPlaceholder:请填写理由, 方法实现如下: this.$prompt(, 是否确认?, { confirmButtonText: 确定, cancelButtonText: 取消, inputPlaceholder:请填写理由, }).then(({ value }) > { if(value null || value ""){ Message({message: 请填…

贝塞尔曲线

贝塞尔曲线于 1962 年,由法国工程师皮埃尔贝济埃(Pierre Bzier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计,贝塞尔曲线最初由保尔德卡斯特里奥于1959年运用德卡斯特里奥算法开发,以稳定数值的方法求出贝塞尔曲…

Centos7 安装yum

1、检查主机名和网络并且配置/etc/hosts文件 查看主机名:hostname 查看ip :ifconfig vi /etc/hosts//添加把主机名和IP配置进去hosts文件192.18.56.111 orcale12c2、关闭防火墙 systemctl status firewalld.service//检查防火墙状态 暂时关闭防火墙,下…

零售行业提高效率的有效技巧!赶紧get

在当今快节奏和数字化的时代,零售业正经历着深刻的变革和创新。新零售模式的兴起正以前所未有的速度改变着传统零售的面貌。其中,自动售货机作为新零售模式的重要代表之一,正以其便捷、高效、数字化的特点,成为越来越多消费者喜爱…

怎么查看企业的征信报告

一、企业征信报告是什么? 企业征信报告是对企业信用状况、财务状况和经营状况等信息进行综合评估的重要工具,为合作伙伴、供应商、投资者等提供了重要的参考并做出明智的决策。企业信用报告记录了企业的信用记录、债务情况以及过往的经营表现等&#xf…