自己动手写编译器:语法解析的基本原理
在前面系列章节中我们完成了词法解析。词法解析的基本任务就是判断给定字符串是否符合特定规则,如果符合那么就给这个字符串分配一个标签(token)。词法解析完成后接下来的工作就要分配给语法解析,后者的任务就是判断一系列标签的组合是否符合特定规范。
语法解析遵守的规则叫巴克斯-诺尔范式,它由三部分组成,最左边的部分叫非终结符,然后跟着一个箭头,箭头右边是一系列终结符或者非终结符。它的意思是左边的概念可以分解成右边一系列概念的组合,举个具体例子:
人 -> 头 上半身 下半身
头 -> 头发 眼睛 耳朵 鼻子 嘴巴
上半身 -> 双手 胸部 肚子
下半身 -> 屁股 双腿
我们看上面的例子,在第一个表达式中左边是一个抽象概念“人”,箭头右边是人的组成部分或者说“人”可以分解成三个相对更具体一些的概念,也就是头,上半身,下半身。然后概念“头”又可以进一步分解成其他概念的组合,例如头发,眼睛等。这里需要注意的是,所有出现在箭头左边的概念都叫“非终结符”,所有只在箭头右边出现而且从来没有在箭头左边出现的概念叫“终结符”。非终结符可以进行分解,而终结符不能再继续往下分解。由上面一系列表达式形成的集合就叫”语法“,在语法解析中特别强调“上下文无关语法”,这个概念的意思是,语法规则只规定词法解析只分析标签的组合规律,至于这些标签的组合到底表达什么含义它不管。
例如 :
句子 -> 主语 谓语 宾语
上面的语法描述的是,一个中文句子可以分成三部分分别是主语,谓语和宾语,但上面的分解并不能告诉我们一个具体句子的内容是什么,也就是语法只关心句子的逻辑构造而不关心句子要传递的意义。这里还需要注意的是,箭头右边一系列概念的顺序很重要,顺序是语法规则的组成部分,例如合乎逻辑的“人头”必须满足鼻子在眼睛后面,如果这个顺序颠倒了,那么这个“头”就不是人头,而是异形的头。
语法解析的基本过程就是给定一个字符串,先对其进行词法解析得到一系列标签组合,然后根据给定语法表达式看看这些标签组合能否顺利分解,我们看一个具体例子,下面是针对数字和加号进行组合的加法算算数表达式语法:
STMT -> EXPR SEMI
EXPR -> FACTOR PLUS EXPR | FACTOR
FACTOR -> NUMBER
现在我们有一个字符串:“1+2;", 首先对这个字符串做词法解析得到 NUMBER PLUS NUMBER SEMI,现在我们需要判断它是否遵守上面语法,首先从第一个表达式开始,由于最后一个标签是 SEMI,因此它满足第一个表达式右边的 SEMI,现在需要判断 NUMBER PLUS NUMBER 是否能满足 EXPR 的规则。
我们看 EXPR 的右边分解。首先 FACTOR PLUS EXPR 跟 NUMBER PLUS NUMBER 中的 PLUS 匹配,于是接下来需要判断第一个 NUMBER 是否能满足 FACTOR 的规定,同时判断第二个 NUMBER 是否满足 EXPR 规定。
我们看 FACTOR 的分解,它可以直接分解成 NUMBER,所以第一个 NUMBER 满足 FACTOR 的规定,此时再看第二个 NUMBER,由于 EXPR 可以之间分解成 FACTOR,然后 FACTOR 又可以之间分解成 NUMBER,由此第二个 NUMBER 满足 EXPR 规定,至此 NUMBER PLUS NUMBER 能被上面语法解析,因此它包含的标签组合满足给定的语法规则。
上面的推导方法也叫最左推导,因为我们总是先拿到表达式右边,然后从最左往右,依次取出非终结符,先看给定的标签是否满足规范。同时还需要注意的是我们从最顶部的规则开始推导,依次从上往下分解,这种方式也叫自顶向下的推导。后面我们会看到第一种语法解析方式,它的特点是先获得一串标签集合,然后从最左边的标签开始逐个解析,然后采用上面描述的最左推导法,于是这样的语法解析叫 LL语法解析算法,两个 L 都对应英语里的 left,也就是左边的意思。其中LL(1)表示解析时会预先多查看 1 个标签,LL(k)表示预先多查看 k 个标签。之所以预先多查看标签主语是因为一个非终结符可能有多个表达式,例如
EXPR -> FACTOR PLUS EXPR | FACTOR
它其实对应两个表达式,一个是EXPR -> FACTOR PLUS EXPR,另一个是 EXPR->FACTOR,在解析时应该选取哪一个呢,此时就可以通过预先查看 一个或多个标签来决定。后面我们还会研究 LR 解析算法,第一个 L 表示从标签串的最左边开始进行解析,R 表示在解析时采用最右方式,也就是跟我们前面说的最左方式正好相反。
还有一点需要注意的是,在前面给出的语法表达式中,左边的符号都可以解析成右边 1 个或多个符号,事实上还存在一种可能是右边可以解析成 0 个符号,还记得前面将词法解析时的 epsilon 转换吧,它表示当前状态下不需要输入任何符号就能跳转到下一个状态,同样我们允许如下语法表达式
此时它表示可以通过什么都不做来完成解析,不难理解c 语言编译器可以编译解析一个内容为空的.c 源文件。
本节描述的东西比较抽象,它很可能给你带来更多的是困惑,好在在最开始和前面做词法解析时,我们都接触过语法解析,所以前面的练习应该会有助于我们对这些理论的理解,在后面章节中,我们会拿几个较为简单的语法解析做练手,通过实践才能更好的帮我们理解和掌握抽象的理论,更多内容请在 b 站搜索 Coding 迪斯尼。
相关文章:

自己动手写编译器:语法解析的基本原理
在前面系列章节中我们完成了词法解析。词法解析的基本任务就是判断给定字符串是否符合特定规则,如果符合那么就给这个字符串分配一个标签(token)。词法解析完成后接下来的工作就要分配给语法解析,后者的任务就是判断一系列标签的组合是否符合特定规范。 …...

VS Code解决乱码
在上边搜索栏输入“>Change File Encoding”,更改编码格式,解决乱码格式。 VS Code会帮助确认编码格式,然后选择就好。 最后完成如下:...

宝塔Linux:部署His医疗项目通过jar包的方式
📚📚 🏅我是默,一个在CSDN分享笔记的博主。📚📚 🌟在这里,我要推荐给大家我的专栏《Linux》。🎯🎯 🚀无论你是编程小白,还是有…...

Vim命令大全(超详细,适合反复阅读学习)
Vim命令大全 Vim简介Vim中的模式光标移动命令滚屏与跳转文本插入操作文本删除操作文本复制、剪切与粘贴文本的修改与替换文本的查找与替换撤销修改、重做与保存编辑多个文件标签页与折叠栏多窗口操作总结 Vim是一款文本编辑器,是Vi编辑器的增强版。Vim的特点是快速、…...
爬虫持久化保存
## open方法- 方法名称及参数markdown **open(file, moder, bufferingNone, encodingNone, errorsNone, newlineNone, closefdTrue)****file** 文件的路径,需要带上文件名包括文件后缀(c:\\1.txt)**mode** 打开的方式(r,w,a,x,b,t…...

统一大语言模型和知识图谱:如何解决医学大模型-问诊不充分、检查不准确、诊断不完整、治疗方案不全面?
统一大语言模型和知识图谱:如何解决医学大模型问诊不充分、检查不准确、诊断不完整、治疗方案不全面? 医学大模型问题如何使用知识图谱加强和补足专业能力?大模型结构知识图谱增强大模型的方法 医学大模型问题 问诊。偏离主诉和没抓住核心。…...
读写分离之同步延迟测试
背景 读写分离是快速提高数据库性能的手段,主库只负责写入,从库负责查询。但在性能得到提升的同时,编程的复杂度就会提升。由其碰到主从同步延迟的情况,在数据写入后,在从库无法读取到最新数据,会对业务逻…...
SpringBoot+OCR 实现PDF 内容识别
一、SpringBootOCR对pdf文件内容识别提取 1、在 Spring Boot 中,您可以结合 OCR(Optical Character Recognition)库来实现对 PDF 文件内容的识别和提取。 一种常用的 OCR 库是 Tesseract,而 pdf2image 是一个用于将 PDF 转换为图…...
Go和Java实现抽象工厂模式
Go和Java实现抽象工厂模式 本文通过简单数据库操作案例来说明抽象工厂模式的使用,使用Go语言和Java语言实现。 1、抽象工厂模式 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创 建型模式,它…...
深入理解Java虚拟机---内存分配
深入理解Java虚拟机---内存分配 GC日志内存分配与回收策略对象优先在Eden分配大对象直接进入老年代长期存活的对象将进入老年代动态对象年龄判定空间分配担保 GC日志 以下两段典型的GC日志: 33.125: [GC [DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K-&…...

计算机网络2
OSI参考模型七层: 1.应用层 2.表示层 3.会话层 4.传输层 5.网络层 6.数据链路层 7.物理层 TCP/IP模型 5层参考模型...

jenkins-Generic Webhook Trigger指定分支构建
文章目录 1 需求分析1.1 关键词 : 2、webhooks 是什么?3、配置步骤3.1 github 里需要的仓库配置:3.2 jenkins 的主要配置3.3 option filter配置用于匹配目标分支 实现指定分支构建 1 需求分析 一个项目一般会开多个分支进行开发,测试&#x…...
源码解析8-QSS原理-案例-Qt的qss特殊设置多个子控件的颜色与伪状态
Qt源码解析 索引 源码解析8-QSS原理-案例-Qt的qss特殊设置多个子控件的颜色与伪状态 有些时候我们想特殊设置QSS,比如某一类标题栏目,某一个窗口中的颜色。 重要的是我们需要同时设置多个特殊的按钮等。 统一设置所有 单一按钮全局设置 QPushButton…...

Nginx+Tomcat实现负载均衡和动静分离
目录 前瞻 动静分离和负载均衡原理 实现方法 实验(七层代理) 部署Nginx负载均衡服务器(192.168.75.50:80) 部署第一台Tomcat应用服务器(192.168.75.60:8080) 多实例部署第二台Tomcat应用服务器(192.168.75.70:80…...

linux系统的u盘/mmc/sd卡等的支持热插拔和自动挂载行为
1.了解mdev mdev是busybox自带的一个简化版的udev。udev是从Linux 2.6 内核系列开始的设备文件系统(DevFS)的替代品,是 Linux 内核的设备管理器。总的来说,它取代了 devfs 和 hotplug,负责管理 /dev 中的设备节点。同时…...

使用Python将OSS文件免费下载到本地:项目分析和准备工作
大家好,我是水滴~~ 本文将介绍如何使用Python编程语言将OSS(对象存储服务)中的文件免费下载到本地计算机。我们先进行项目分析和准备工作,为后续的编码及实施提供基础。 《Python入门核心技术》专栏总目录・点这里 文章目录 1. 前…...

从Gitee克隆项目、启动方法
从gitee克隆VUE项目到本地后,不能直接运行,需要进行npm install安装node_modules文件夹里面的内容,因为在git上传的时候,一般都会过滤到node_modules中的依赖文件。 安装依赖以后,启动通过npm run serve启动项目出错。…...

不用再找了,这是大模型实践最全的总结
随着ChatGPT的迅速出圈,加速了大模型时代的变革。对于以Transformer、MOE结构为代表的大模型来说,传统的单机单卡训练模式肯定不能满足上千(万)亿级参数的模型训练,这时候我们就需要解决内存墙和通信墙等一系列问题&am…...
QT 记录
qml 移动窗口会闪烁 int main(int argc, char *argv[]) {QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);//orQCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); }window 拉取qml程序依赖文件 打开QT自带的命令窗口,转到exe程序目录: …...

智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.黑寡妇算法4.实验参数设定5.算法结果6.参考文…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...