1. 背景
今天学习了编译原理中的语法分析-自上而下分析的基本问题
这一章节,我参考了国防工业出版社《编译原理》教材1 和中国大学MOOC-国防科技大学《编译原理》的PPT,整理了这一章的内容,希望能够理解这部分的知识。
2. 语法分析
2.1. 语法分析的前提
-
采用正规式和有限自动机描述和识别语言的单词符号
-
用上下文无关文法来描述语法规则
2.2. 语法分析的任务
-
语法分析的任务
-
语法分析器的功能
- 按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)
2.3. 语法分析器在编译器中的地位
2.4. 语法分析的方法
2.4.1. 自下而上(Bottom-up)
2.4.2. 自上而下(Top-down)
2.5. 自上而下分析方法的问题
2.5.1. 文法左递归问题
P⇒Pα
含有左递归的文法使上述的自上而下分析过程陷入无限循环。
2.5.2. 回溯问题
- 定义:分析过程中,当一个非终结符用某一个候选匹配成功时,这种匹配可能是暂时的。出错时,不得不“回溯”。
3. 消除文法的左递归
3.1. 直接左递归的消除
P−Pα1∣Pα2∣⋯∣Pαm∣β1∣β2∣⋯∣βn
(每个
α都不等于
ϵ,每个
β都不以
P开头)
P→β1P′∣β2P′∣⋯∣βnP′
P′→α1P′∣α2P′∣⋯∣αmP′∣ϵ
3.2. 间接左递归的消除
- 间接左递归定义:给定文法
G(S):
S→Qc∣c
Q→Rb∣b
R→Sa∣a
虽然不存在直接左递归,但
S、Q、R都是左递归的,例如有
S⇒Qc⇒Rbc⇒Sabc
- 一个文法消除左递归的条件
- 不含以ε为右部的产生式
- 不含回路
P⇒P
- 把文法G的所有非终结符按任一种顺序排列
P1,P2,⋯,Pn;
- 按此顺序执行如下伪代码
FOR i:=1 TO n DO
BEGIN
FOR j:=1 TO i-1 DO
(1)
(2)
END
(1) 把形如
Pi→Pjγ的规则改写成
Pi→δ1γ∣δ2γ∣…∣δkγ;
( 其中
Pj→δ1∣δ2∣⋯∣δk是关于
Pj的所有规则 )
(2) 消除关于
Pi规则的直接左递归性
- 化简由 2 所得的文法,去除从开始符号出发永远无法到达的非终结符的产生规则。
- 举例:给定文法
G(S)如下
S→Qc∣c
Q→Rb∣b
R→Sa∣a
- 将非终结符排序为
R、Q、S。对于
R,不存在直接左递归。
- 把
R带入到
Q 的有关候选后,我们把
Q 的规则变为
Q→Sab∣ab∣b
现在
Q 同样不包含直接左递归,把它带入到
S 的有关候选后,
S 变成
S→Sabc∣abc∣bc∣c
接着消除
S 的直接左递归,最后得到的文法为
S→abcS′∣bcS′∣cS′
S′→abcS′∣ϵ
Q→Sab∣ab∣b
R→Sa∣a
- 显然,其中关于
Q 和
R 的规则已经多余了,我们可以对它们进行化简,最后得到的结果如下。
S→abcS′∣bcS′∣cS′
S′→abcS′∣ϵ
- 注意:由于对非终结符排序的不同,最后所得的文法在形式上可能不一样。但不难证明,它们都是等价的。
4. 消除回溯
- 条件:
- 对文法的任何非终结符,当要它去匹配输入串时,能够根据它所面临的输入符号准确地指派它的一个候选去执行任务,并且此候选的工作结果应是确信无疑的。
即假设现在轮到非终结符
A 去执行匹配任务,
A 共有
n 个候选,即
A→α1∣α2∣⋯∣αn
A 面临一个输入符号
x时,如果输入串是一个合法的句子,那么
A 能够指派某个唯一确定的候选
αi 来匹配
x,若不能匹配
x,说明输入串不是合法的句子。
4.1. FIRST集合
- 定义:令
G 是一个不含左递归的文法,对
G 的所有非终结符的每个候选
α 定义它的终结首符集
FIRST(α)为:
FIRST(α)={a∣α⇒a,⋯a∈VT}
特别是,若
a⇒ϵ, 则规定:
ϵ∈FIRST(α)
换句话说,
FIRST(α)是
α 的所以可能推导的开头终结符 或可能的
ϵ 。 如果非终结符
A 的所有候选首符集两两不相交,即
A 的任何两个不同候选
αi 和
αj
FIRST(αi)⋂FIRST(αj)=∅
那么,当要求
A 匹配输入串时,
A 就能根据它所面临的第一个输入符号
a,准确地指派某一个候选前去执行任务。这个候选就是那个终结首符集含
a 的
α.
4.2. 提取公共左因子
假定关于A的规则是
A→δβ1∣δβ2∣…∣δβn∣γ1∣γ2∣…∣γm
(其中,每个
γ 不以
δ开头)
那么,可以把这些规则改写成
A→δA′∣γ1∣γ2∣⋯∣γm
A′→β1∣β2∣⋯∣βn
经过反复提取左因子,就能够把每个非终结符(包括新引进者)的所有候选首符集变成为两两不相交。
如果空字
ϵ 属于某个非终结符的候选首符集,那么问题就比较复杂。引入Follow集合。
4.3. FOLLOW集合
假定
S是文法
G的开始符号,对于
G的任何非终结符
A,我们定义
A的FOLLOW集合
FOLLOW(A)={a∣S⇒...Aa...,a∈VT}
特别是,若
S⇒⋯A
则规定
#∈FOLLOW(A)
表示若
A在句子的末尾,则标示句子末尾的
# 在
A的
Follow 集合中。
注:部分内容整理自国防工业出版社《编译原理》教材和中国大学MOOC-国防科技大学《编译原理》PPT
5. 参考文献
[1] 陈火旺. 编译原理 [M]. 北京 : 国防工业出版社, 2010.
联系邮箱:[email protected]
Github:https://github.com/CurrenWong
欢迎转载/Star/Fork,有问题欢迎通过邮箱交流。