java开发简单解释器,实现一个简单的解释器(5)

article/2025/7/1 11:32:04

你如何处理和了解像创建解释器或编译器这样复杂的事情?在开始时,一切看上去都像是一团乱七八糟的纱线,你需要解开缠结才能得到完美的球。

到达那里的方法是将它解开一个线,一次解开一个结。不过有时候,你可能会觉得自己听不懂某些内容,但必须继续前进,我向你保证,如果你足够坚持,它最终将“咔嗒”一声被解开。

在理解如何创建解释器和编译器的过程中,最好的建议之一是阅读文章中的解释,阅读代码,然后自己编写代码,甚至在一段时间里编写相同的代码,使你能完全了解材料和代码,然后继续学习新主题。不要着急,只要放慢脚步,花点时间深刻理解基本概念,这种方法虽然看似很慢,但会在未来获得回报。相信我。

最后,最终将获得完美的毛线球,即使不是那么完美,它也比什么也不做或者快速浏览后的几天内忘掉好多了。

请记住:一步步理解这些知识点,并通过编写代码练习所学的知识:

98c4bceab897535c1ac3b7a6ddd3fc44.png

今天,你将使用前几篇文章中获得的知识,学习如何解析和解释具有任意数量的加,减,乘和除运算的算术表达式,你将编写一个解释器,该解释器将能够对"14 + 2 * 3 - 6 / 2"之类的表达式求值。

在深入学习并编写一些代码之前,我们先讨论一下运算符的结合性(associativity)和优先级(associativity)。

按照惯例7 + 3 + 1与(7 + 3)+ 1相同,而7 - 3 - 1相当于(7 - 3)- 1。 我们都了解这些。如果我们将7 - 3 - 1视为7 -(3 - 1),则结果将会意外的变成5,而不是我们预期的3。

在普通算术和大多数编程语言中,加,减,乘和除是左结合(left-associative)的:

7 + 3 + 1 is equivalent to (7 + 3) + 1

- 3 - 1 is equivalent to (7 - 3) - 1

* 4 * 2 is equivalent to (8 * 4) * 2

/ 4 / 2 is equivalent to (8 / 4) / 2

什么是运算符号的左结合性呢?

当表达式7 + 3 + 1中的3之类的操作数在两侧都带有加号时,我们需要约定来确定哪个运算符适用于3,是左边的加号还是右边的加号?我们说运算符加号左结合,是因为在存在两侧都带有加号的操作数时,此时左边的加号适用于此操作数,因此我们说运算符加号是左结合的(The operator + associates to the left because an operand that has plus signs on both sides belongs to the operator to its left and so we say that the operator + is left-associative.),所以按照结合性惯例,7 + 3 + 1等于(7 + 3)+ 1。

我们再来看7 + 5 * 2这个表达式,在操作数5的两边都有不同类型的运算符,该表达式等于7 +(5 * 2)还是(7 + 5)* 2呢?我们如何解决这种歧义?

在这种情况下,结合性约定对我们没有帮助,因为它仅适用于加减法(+,-)或乘除法(*,/)这种同一类型的运算符。当我们在同一表达式中具有不同种类的运算符时,我们需要另一种约定来解决歧义。我们需要一个定义运算符相对优先级的约定。

我们说如果运算符乘号在加号之前执行其操作数,则乘号具有更高的优先级(higher precedence)。在我们所使用的运算中,乘法和除法的优先级高于加法和减法,所以表达式7 + 5 * 2等效于7 +(5 * 2),表达式7 - 8 / 4等效于7-(8 / 4)。

在含有优先级相同的运算符的表达式中,我们仅使用结合性约定并从左到右执行运算符:

7 + 3 - 1 is equivalent to (7 + 3) - 1

/ 4 * 2 is equivalent to (8 / 4) * 2

希望你不要因为这些运算符的结合性和优先级而感到无聊,我们可以利用这些约定来构造算术表达式的语法,以显示算术运算符的结合性和优先级,然后,我们可以按照我在第4部分中概述的准则将语法转换为代码,我们的解释器将能够处理运算符的优先级和结合性约定。

这是我们的优先级表(precedence table):

ab86e23d1893591761fae0a655348f65.png

从表中可以看出,运算符加号和减号具有相同的优先级,并且它们都是左结合的,还可以看到,运算符乘号和除号也是左结合的,它们之间也具有相同的优先级,但是比加减运算符具有更高的优先级。

以下是有关如何根据优先级表构造语法的规则:

1、为每一类优先级定义一个非终结符。非终极符的产生式主体应包含该类优先级的算术运算符和下一类更高优先级的非终结符。( The body of a production for the non-terminal should contain arithmetic operators from that level and non-terminals for the next higher level of precedence.)

2、为基本的表达单位(在本文下为整数)创建一个附加的非终结符factor。一般规则是,如果具有N类优先级,则总共将需要N + 1个非终结符:每类级别一个非终结符(N个)再加上一个运算基本单位的非终结符factor(1个)。(Create an additional non-terminal factor for basic units of expression, in our case, integers. The general rule is that if you have N levels of precedence, you will need N + 1 non-terminals in total: one non-terminal for each level plus one non-terminal for basic units of expression.)

继续!

让我们遵循规则并构建语法。

根据规则1,我们将定义两个非终结符:一个用于级别2的称为expr的非终结符和一个用于级别1的称为term的非终结符,通过规则2,我们将为算术的基本单位定义一个非终结符factor来表达整数。

新语法的起始符号将为expr,expr的产生式将包含一个表示使用级别2的运算符主体,在本例中为加号和减号,并将包含更高级别优先级的非终结符term。

级别2:

1bd3c1e1b717bad36a7caf2e1b8a9558.png

term产生式将包含一个使用级别1运算符的主题,即运算符乘号和除号,并且它也包含基本表达式单位(整数)的非终结符factor:

8fd93808799a49c285a0152cf9c3249a.png

非终结符factor的产生式为:

8f1d49013c0818e11a0eb26a8e20ed7d.png

你已经在之前的文章看见过以上产生式的语法和语法图,在这里,考虑到结合性和优先级,我们将它们组合成一个语法:

ee83fb63e69ac237c63ae4fe96d122ff.png

这是与上面的语法相对应的语法图:

bc1ffad020c1f0efe65a2028db2d0115.png

图中的每个矩形框都是对另一个图的“函数调用(method call)”。 如果你采用表达式7 + 5 * 2并从顶部expr开始,然后一直走到最底部的factor,那么应该能够看到较高优先级的运算符乘号和除号在较低的图中,运算符加号和减号在较

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[实现一个简单的解释器(5)]http://www.zyiz.net/tech/detail-113299.html


http://chatgpt.dhexx.cn/article/23iblVII.shtml

相关文章

【“笨办法”学Python】43.基本的面向对象分析和设计——自顶向下、自底向上

43.基本的面向对象分析和设计 文章目录 前言一、解决问题的方法——流程1、自顶向下(top down)2、自底向上 二、代码示例三、运行Python程序总结 前言 使用Python,尤其是通过面向对象编程(OOP)方式构建一些东西的流程。 一、解决问题的方法——流程 所谓按照流程就是…

5大代码规则,守护程序猿世界的爱与和平!

全文共2878字,预计学习时长9分钟 图源:Unsplash 编码规则是程序编码所要遵循的规则,要注意代码的正确性、稳定性、可读性。 而对于这些条条框框,一些不拘小节的程序猿们往往并不在意,这导致常常会发生一些意想不到的问题和状况,让大家苦恼不已。 现在,小芯整理了一份…

【AI产品】认猫、认花、认车、认吃,请认准识别全能王

欢迎来到《AI产品》专栏,本专栏面向所有热爱人工智能技术的朋友、同学。在本专栏中,会多多分享给大家不同种类的且新奇有趣的AI产品,对产品中的核心技术进行深度剖析。文章底部会推荐相关核心技术学习资料,全部原创! 请…

【杂谈】什么文章可以给有三AI投稿?你能得到什么

我们公众号的风格是做系统性的原创,除了一些资源类的东西,大多数是专栏,大部分是有三本人在写,还有一些是其他的专栏作者,那么现在有哪些专栏可以自由投稿,新手也可以来练练手呢,今天就来汇总一…

听声音做钥匙?!慢放开锁音轨,黑客就能破解常用门锁

作者|牛婉杨 出品|大数据文摘 你熟悉的黑客是不是这样的?比如上个月,黑客造成推特史上最严重的安全事故,马斯克奥巴马等多位大V账号被黑;或者像8月初英特尔的那起数据泄露事故,足足20GB数据被黑…

【AI产品】爱做短视频的你,真的很需要一款配音软件

欢迎来到《AI产品》专栏,本专栏面向所有热爱人工智能技术的朋友、同学。在本专栏中,会多多分享给大家不同种类的且新奇有趣的AI产品,对产品中的核心技术进行深度剖析。文章底部会推荐相关核心技术学习资料,全部原创! 请…

怎样设计宝藏游戏_宝藏! 免费的移动设计资源

怎样设计宝藏游戏 Being a designer usually requires staying in the know of resources that you could use to get better at your craft as well as resources you could use in your work. 成为设计师通常需要了解可以用来提高自己的Craft.io水平的资源以及可以在工作中使…

webaudio_WebAudio Deep Note,第5部分:增益节点

webaudio Previously on "Deep Note via WebAudio": 以前在“通过WebAudio进行深度注释”中: intro 介绍play a sound 播放声音 2.1. boots and cats2.1。 靴子和猫play a sound 播放声音 loop and change pitch循环并改变音高multiple sounds多种声音no…

web audio api_带有Web Audio API的动态声音

web audio api This article is part of a web dev series from Microsoft. Thank you for supporting the partners who make SitePoint possible. 本文是Microsoft的Web开发系列的一部分。 感谢您支持使SitePoint成为可能的合作伙伴。 Before the Web Audio API, HTML5 gave…

Apache Spark【从无到有从有到无】【编程指南】【AS5】结构化流编程指南

目录 1.概观 2.快速示例 3.编程模型 3.1.基本概念 3.2.处理事件时间和延迟数据 3.3.容错语义 4.使用数据集和数据框架的API 4.1.创建streaming DataFrames 和 streaming Datasets 4.1.1.输入源(Input Sources) 4.1.2.流式数据帧/数据集&#x…

王者荣耀scratch版

现在,防沉迷使我每周都玩不了王者了,不对,不是周5,6,7,八点到九点能玩吗,偶不,那时候我正在上课。。。。。。 现在我,正式想你介绍“Scrach版王者荣耀”!&…

编程斐波那契数列_通过斐波那契序列记忆和制表法进行动态编程的简介

编程斐波那契数列 Lately I have been studying algorithms and data structures while trying to prepare for technical interviews. Some of it comes easier than the rest, but I always enjoy a good challenge. I love the whiteboard problems that feel like a puzzle…

javascript编程题_JavaScript中的鼠标滚轮编程

javascript编程题 In this article Ill describe cross-browser techniques for using the mouse wheel (or "scroll wheel") in your JavaScript programming for HTML pages. Ill show example Javascript for option selection and image zooming. 在本文中&…

【AI产品】智能修图时代已来临?「咔嗒」一下,轻松后期

欢迎来到《AI产品》专栏,本专栏面向所有热爱人工智能技术的朋友、同学。在本专栏中,会多多分享给大家不同种类的且新奇有趣的AI产品,对产品中的核心技术进行深度剖析。文章底部会推荐相关核心技术学习资料,全部原创! 请…

在网易咔哒上面制作SCRATCH小程序

小朋友在网易咔嗒上面创作作品。

什么是命令行参数

命令行参数:在启动这个程序的时候可以给这个程序从命令行中传递一些参数 这个- l就叫做命令行参数 int main(int argc ,char* argv[],char* env[])argc :命令行参数的个数 argv :命令行参数的内容 env:环境变量

Python教程:命令行参数处理

sys模块 sys模块代表了Python解释器,主要用于获取和Python解释器相关的信息,其中 sys.argv 可以获取命令行参数 在Python交互式解释器中可以先导入sys模块 import sys,再输入 dir(sys) 查看sys模块所包含的全部程序单元(包括变量…

java命令行参数详解

java 命令参数详解_赶路人儿的博客-CSDN博客_java命令行参数java命令用于启动 java 应用:它首先会启动 java 运行时环境(JRE),然后加载指定的类,调用类的main()方法。main()方法必须定义为public和static的&#xff0c…

浏览器命令行参数

浏览器命令行参数 一、Google浏览器 1.命令行参数 --google-url ”" 地址栏打开网址(官方并无此命令) --app”" 无地址栏打开网址 --allow-running-insecure-content Https协议页面允许请求http资源加载 --disable-web-security 禁用同源安…