【编译原理笔记05】语法分析:FIRST集和FOLLOW集的计算,[非]递归的预测分析法,预测分析中的错误处理
本次笔记内容:
4-4 FIRST集和FOLLOW集
4-5 递归的预测分析法
4-6 非递归的预测分析法
4-7 预测分析法中的错误处理
本节课幻灯片,见于我的 GitHub 仓库:第5讲 语法分析_2.pdf
文章目录
- FIRST集和FOLLOW集的计算
- 计算文法符号X的FIRST(X)
- 算法总结
- 接着,计算串X1X2 …Xn的FIRST 集合
- 计算非终结符A的FOLLOW(A)
- 算法总结
- 基于FIRST于FOLLOW计算SELECT集
- 预测分析表
- 递归的预测分析法
- 非递归的预测分析法
- 递归的预测分析法vs.非递归的预测分析法
- 总结预测分析法实现步骤
- 预测分析中的错误处理
- 预测分析中的错误检测
- 预测分析中的错误恢复
承接上一节课。上一节课提出了FIRST集
和FOLLOW集
的概念,这节课先来讨论如何计算这两个集合。
FIRST集和FOLLOW集的计算
计算文法符号X的FIRST(X)
- FIRST(X):可以从X推导出的所有串首终结符构成的集合;
- 如果X⇒∗ϵX \Rightarrow * \epsilonX⇒∗ϵ,那么ε∈FIRST(X)。
取决于产生式的右部:
- 比如2、4、5产生式,
左部以终结符打头
,这个终结符就是就是产生式可以推导出的终结符,于是加入到 FIRST 集合中
; - 对于非终结符,其依赖于自己的内容,比如F的FIRST为 {( id} ,则 T 的 FIRST 也为这个; E 依赖于 T ,则 E 的 FIRST 也是这个。
算法总结
不断应用下列规则,直到没有新的终结符或ε可以被加入到任何FIRST集合中为止。
- 如果X是一个终结符,那么FIRST ( X ) = { X };
- 如果X是一个非终结符,且X→Y1…Yk∈P(k≥1),那么如果对于某个i,a在FIRST (Yi ) 中且ε 在所有的FIRST(Y1) , … , FIRST(Yi-1)中(即Y1…Yi-1 ⇒\Rightarrow⇒* ε ),就把a加入到FIRST( X )中。如果对于所有的j = 1,2, . . . , k,ε在FIRST(Yj)中,那么将ε加入到FIRST( X );
- 如果X→ε∈P,那么将ε加入到FIRST( X )中。
接着,计算串X1X2 …Xn的FIRST 集合
- 向FIRST(X1X2X3X_1X_2X_3X1X2X3)加入FIRST(X1X_1X1)中所有的非ε符号;
- 如果ε在FIRST(X1X_1X1)中,再加入FIRST(X2X_2X2)中的所有非ε符号;如果ε在FIRST(X1X_1X1)和FIRST(X2X_2X2)中,再加入FIRST(X3X_3X3)中的所有非ε符号,以此类推;
- 最后,如果对所有的i,ε都在FIRST(XiX_iXi)中,那么将ε加入到FIRST(X1X2...XnX_1X_2...X_nX1X2...Xn) 中。
计算非终结符A的FOLLOW(A)
- FOLLOW(A):可能在某个句型中紧跟在A后边的终结符a的集合;
- FOLLOW(A)={a∣S⇒∗αAaβ,a∈VT,α,β∈(VT∪VN)∗}F O L L O W(A)=\left\{\mathrm{a} \mid S \Rightarrow^{*} \alpha A a \beta, \mathrm{a} \in V_{T}, \quad \alpha, \beta \in\left(V_{T} \cup V_{N}\right)^{*}\right\}FOLLOW(A)={a∣S⇒∗αAaβ,a∈VT,α,β∈(VT∪VN)∗}
- 如果A是某个句型的的最右符号,则将结束符“$”添加到FOLLOW(A)中。
例子如上,基于 FIRST 计算:
- 文法大E本身是一个句型,它也是这个句型的最右符号,因此将 $ 加入其 FOLLOW 集中;
- 接下来逐个分析产生式。
- 第一条产生式中,E’的FIRST集中的所有终结符可以跟在T的后面,所以将E’中的终结符,也就是
+
加入到T的 FOLLOW 集中; - 由于 E’ 可以推出空串,那么能跟在 E 后面的符号,就能跟在 T 后面,因此,将E的FOLLOW的$添加到T的FOLLOW中;
- 对于E’,E’是产生式E→TE′E \rightarrow TE'E→TE′中最右边的符号,因此能跟在E后面的,自然就能跟在E’后面,因此将E中的元素添加到E’中。
- 以此类推。
- 最后,
各个产生式都过完一遍了,再回到第一个产生式。
注意到由于E’可以是空串,那么E’后面的东西,也能出现在T后面,因此将E’中有的而T中没有的反括号)
加入到T中;补充添加
以此类推。
算法总结
不断应用下列规则,直到没有新的终结符可以被加入到任何FOLLOW集合中为止:
- 将$放入FOLLOW(S)中,其中S是开始符号,$是输入右端的
结束标记
; - 如果存在一个产生式A→αBβ,那么FIRST(β)中
除ε之外
的所有符号都在FOLLOW(B)中; - 如果存在一个产生式A→αB,或存在产生式A→αBβ且FIRST(β) 包含ε,那么FOLLOW(A)中的所有符号都在FOLLOW(B)中。
基于FIRST于FOLLOW计算SELECT集
- 第一个产生式,
左部是T(非终结符
),因此是T的FIRST集中的终结符
; - 第二个产生式,
左部是终结符
,因此就是终结符
; - 第三个产生式,
左部是空串
,因此就是其FOLLOW集
。
可以看出:
- 第1个和第2个产生式,
具有相同的左部,其SELECT集互不相交
; - 第4,5同理;
因此,这个算数表达式文法是LL(1)文法
。因此可以写预测分析表
。
预测分析表
由上,我们得出了这个可以帮助我们大大提升效率,不需要再编译中回溯的预测分析表
。
LL(1)文法的分析方法分为,将在后面介绍:
- 递归的预测分析法
- 非递归的预测分析法
递归的预测分析法
递归的预测分析法是指:在递归下降分析中,根据预测分析表进行产生式的选择。
根据每个非终结符的产生式和LL(1)文法的预测分析表,为每个非终结符编写对应的过程。
一个例子:
右边为递归下降分析的主程序。
其递归过程如下。
非终结符有自己对应的程序。
非递归的预测分析法
非递归的预测分析不需要为每个非终结符编写递归下降过程
,而是根据预测分析表构造一个自动机
,也叫表驱动的预测分析
。
如图,为有穷自动机增加一个栈,用于增加记忆功能
。比如对于上图中例子,输入a,压栈,输入b,b进栈,a出栈,最终可以判断a与b的数量是否一致。
如图,通过入栈出栈的形式,实现了预测分析
。
表驱动的预测分析法总结:
递归的预测分析法vs.非递归的预测分析法
递归的预测分析法 | 非递归的预测分析法 | |
---|---|---|
程序规模 | 程序规模较大,不需载入分析表 |
主控程序规模较小 ,需载入分析表(表较小)
|
直观性 |
较好
|
较差 |
效率 | 较低 |
分析时间大约正比于待分析程序的长度
|
自动生成 | 较难 |
较易
|
总结预测分析法实现步骤
- 构造文法;
- 改造文法:消除二义性、消除左递归、消除回溯;
- 求每个变量的FIRST集和FOLLOW集,从而
求得每个候选式的SELECT集
; - 检查是不是LL(1)文法。若是,
构造预测分析表
; - 对于
递归的
预测分析,根据预测分析表为每一个非终结符编写一个过程;对于非递归的
预测分析,实现表驱动的预测分析算法;
预测分析中的错误处理
预测分析中的错误检测
两种情况下可以检测到错误:
- 栈顶的终结符和当前输入符号不匹配;
- 栈顶非终结符与当前输入符号在预测分析表对应项中的信息为空。
预测分析中的错误恢复
可以使用恐慌模式:
- 忽略输入中的一些符号,直到输入中出现由设计者选定的
同步词法单元(synchronizing token)
集合中的某个词法单元: - 其效果依赖于
同步集合的选取
。集合的选取应该使得语法分析器能从实际遇到的错误中快速恢复
;
- 其效果依赖于
- 例如可以把
FOLLOW(A)中的所有终结符
放入非终结符A的同步记号集合;
- 例如可以把
- 如果终结符在栈顶而不能匹配,一个简单的办法就是弹出此终结符。
一个例子:
先由FOLLOW(X)得到SYNCH在哪里。
【编译原理笔记05】语法分析:FIRST集和FOLLOW集的计算,[非]递归的预测分析法,预测分析中的错误处理相关推荐
- FIRST集和FOLLOW集的计算
文章目录 `FIRST`集的计算 计算`FIRST(x)` 具体算法 计算`$X_21,X_2,X_3,...,X_n$`的`FIRST`集 FOLLOW集的计算 算法 FIRST集的计算 计算FIR ...
- 【编译原理】FIRST集和FOLLOW集构造法速学
编译原理速成大法 FIRST集和FOLLOW集构造法速成 FIRST FOLLOW FIRST集和FOLLOW集构造法速成 例:对于文法G(E) 首先像E,T,E',F这样的就是非终结符 +,*, ε ...
- 【编译原理笔记07】语法分析:SLR、LR(1)、LALR、二义性分析与错误处理
本次笔记内容: 4-12 SLR 4-13 LR1分析 4-14 LALR分析法 4-15 二义性文法的LR分析 4-16 LR分析中的错误处理 本节课幻灯片,见于我的 GitHub 仓库:第7讲 语 ...
- 编译原理-First集和Follow集
刚学first集和follow集的时候,如果上课老师没有讲明白或者自己没听明白,自己看的时候还真是有点难理解,不过结合着具体的题目可以理解的更快. 先看一下两种集合的求法: First集合的求法: ...
- 【编译原理笔记06】语法分析,移入-归约分析:自底向上的分析,LR(0)分析法,LR(0)分析表的构建(基于自动机)
本次笔记内容: 4-8 自底向上的分析概述 4-9 LR分析法概述 4-10 LR0分析 4-11 LR0分析表构造 本节课幻灯片,见于我的 GitHub 仓库:第6讲 语法分析_3.pdf 本节课介 ...
- 【编译原理】First集和Follow集简易解释(偏人话)
\ε:非ε元素 First集和Follow集是集合 First集规则(相应字母在->左边,查找->右边第一个东西) ①A->aB,a加进First(A): (->右边第一个是终 ...
- 编译原理--实验2 语法分析
文章目录 前言 1.1实验目的 1.2 实验任务 1.3 实验内容 1.3.1 实验要求 1.3.2 输入格式 1.3.3 输出格式 1.3.4 样例 1.4 程序 1.4.1 程序流程图 1.4.2 ...
- 编译原理笔记(二)之词法分析
编译原理笔记(二)之词法分析 1. 词法分析中的若干问题 1.1 基本概念 1.2 记号的属性 1.3 词法分析器的作用与工作方式 1.4 输入缓冲区 2. 模式的形式化描述 2.1 字符串与语言 2 ...
- zucc 编译原理 笔记
zucc 编译原理 笔记 lec02 lec03 lec04
最新文章
- 没想到图像直方图有这么多应用场景
- gradle加载spring包
- 【项目管理】ITTO-风险管理
- php图片上传方案,php图片上传
- HoloLens开发手记 - Unity development overview 使用Unity开发概述
- 把室友的STM32换成了GD32,会被打吗?
- mysql+误操作怎么恢复_Mysql误操作恢复流程
- js室内地图开发_GIS开发_OpenLayers
- linux用shell写正则表达式,Linux命令行与Shell脚本编程大全-shell正则表达式
- oracle11g手工监听配置,手工在同一主机创建主备库oracle11g active dataguard
- 9.数据结构 --- 查找
- 第2章-系统控制原理 -> 李雅普诺夫稳定性分析
- 井口综合安检-解决方案
- word无法自动修复计算机怎么办,电脑Word问题解决办法
- 家里装电线时,为啥说“走顶”比“走地”好
- 微信公众号网页授权--前端获取code及用户信息(vue)
- 进程与程序的区别与联系
- 企业微信客户端通过jsapi调起微信扫码提示40093:jsapi签名错误
- 软件工程毕业设计课题(73)微信小程序毕业设计PHP菜谱美食小程序系统设计与实现
- 导入自己模块包导入报错:ModuleNotFoundError: No module named ‘xxx‘解决方法 晓物智联
热门文章
- php 变量传给另外一个函数,将在一个函数中创建的PHP变量传递给另一个
- 【Linux】Ubuntu输入法不能开机自启的解决方法
- 解决Android Studio卡在Gradle:Resolve dependecies ‘app:_debugCompile‘问题
- 跨站点脚本编制-XSS 描述及解决方法
- 我的世界java版联机不稳定_我的世界:你一定不会相信,时隔2年,网易这次真的“更新”了...
- car-like robot运动模型及应用分析(图片版)
- python有关迭代器和生成器的面试题_python面试题之生成器迭代器
- 手机按三角返回页面上一页_小猿圈微信小程序跳转页面都有哪些?
- 最长公共子串(10分)
- 找出数组的最大公约数