语法分析的两种方式:自上而下推导,自下而上规约
1.递归下降分析器的设计(LL分析,自上而下的推导)
2.语法分析器的自动生成(LR分析,自下而上的规约)
本章的重点是语法分析的第一种方式:自上而下的推导过程
基本的原理:
让每个非终结符号对应一个递归子程序。每个子程序可以作为一个布尔过程(返回“真”或“假”):
(1)一旦发现该非终结符的某个候选式与输入串相匹配,就用这个候选式去扩展语法树,并返回“真”值;
(2)该候选式和输入串不匹配,则保持原来的语法树和IP值不变(IP回溯),并返回“假”值
基本方法遇到的几个问题:
- 文法的左递归问题
- 回溯的不确定性,要求我们将已经完成工作推倒从来,
- 虚假匹配的问题
- 不能准确地确定输入串中出错的位置
- 效率低
如何去解决:
1. 消除左递归
1) 直接左递归
特例:
设有产生式
P→Pα|β (1)
其中β不以P开头,α不为ε。那么,我们可以把P的规则改为如下的非直接左递归形式:
P→βP’
P’→αP’|ε (2)
(1)和(2)是等价的
消除直接左递归通用方式:
设有产生式
P→Pα1|Pα2|…|Pαm|β1|β2|…|βn
其中每个βi不以P开头,每个αi不为ε
消除P的直接左递归性就是把这些规则改写成:
P→β1P’|β2P’|…|βnP’
P’→α1P’| α2P’|…|αmP’| ε
2) 间接左递归
特例:例如文法
S ®Qc|c
Q ®Rb|b
R ®Sa|a
把R带入到Q中有关的候选式:
Q ® Sab|ab|b
现在Q同样不含直接左递归,把它带入S的有关候选式:
S ®Sabc|abc|bc|c
间接左递归的通法:
按任意顺序对非终结符排序,P1,P2,P3……,然后作如下工作
FORi=1 TO N{
FOR j=1 TO i-1{
对PiPjγ的产生式,改写成
Piδ1 γ| δ2 γ|…| δk γ
}
消除Pi的直接左递归;
}
最后,删除无用(从起始符永远不能到达)的非终结符的产生式
总结:消除左递归的方法:
1. 将间接左递归改造为直接左递归
2. 消除直接左递归
3. 化简改写后的文法,即去除那些从开始符号出发却永远无法到达的非终结符的产生规则。
2. 消除回溯
方式:提取公共左因子
例如:
假设A的产生式为
A→δβ1|δβ2|…|δβn|γ1|γ2|…|γm
其中每个γ不以δ开头
那么把这些产生式改写为:
A→δA’ |γ1| γ2|…|γm
A’→β1|β2|…|βn
反复提取左因子(包括对新引进的非终结符,例如A’)
LL(1)分析
LL(1)文法定义:
(1)文法不含左递归
(2)对于文法中每一个非终结符A的各个产生式的候选式的FIRST集两两不相交。即,若
A→α1|α2|…|αn
则 FIRST(αi)∩FIRST(αj)=Φ (i≠j)
(3)对于文法中的每个非终结符A,若它的某个候选首符集包含ε,则
FIRST(A)∩FOLLOW(A)=Φ
如果一个文法G满足以上条件,则称该文法G为LL(1)文法(第1个L代表从左到右扫描输入串,第2个L代表最左推导,1表示分析时每一步只看1个符号)
递归下降分析程序构造
当一个文法满足LL(1)条件时,我们就可以构造一个不带回溯的自上而下分析程序,这个分析程序由一组(可能的)递归程序组成,每个过程对应文法的一个非终结符。这样一个分析程序称为递归下降分析器。
So:对文法的每一个非终结符都编一个分析程序
当根据文法和当时的输入符号预测到要用某个非终结符去匹配输入串时,就调用该非终结符的分析程序
要掌握如何去写 递归程序
预测分析程序
这里是个重点!!! 重点!!!重点!!! 前面的FIRST和FOLLOW集的定义全部放在这里,因为这里是重点!!!
l 使用高级语言的递归过程描述递归下降分析器,只有当具有实现这种过程的编译系统时才有实际意义。
l 实现LL(1)分析的另一种有效方式是使用一张分析表和一个栈进行联合控制。我们现在介绍的预测分析程序就是属于这种类型的LL(1)分析器。
l 本节要掌握对给定文法构造出每个非终结符的FIRST和FOLLOW集合。
预测分析表:指导分析过程中候选式的选取
分析的过程:
1)LL-自左向右扫描、自左向右的分析和匹配输入串。分析过程表现为最左推导的性质。
2) 符号栈: 有四种情况
1. 开始状态
2. 工作状态
3. 出错状态
4. 结束状态
3)执行程序
知道了分析过程则最重要的是构造预测分析表:
步骤:
1. FIRST(X)
1)若X终结符,则FIRST(X)={X}
2)若X为非终结符,且有X->a …的产生式,则把a加入到FIRST(X)中;
3)若X->Y…是一个产生式,且Y为非终结符,则把FIRST (Y)-ε加入到FIRST(X)中;
若X->Y1Y2Y3….YK,是产生式, Y1Y2Y3….Yi-1是非终结符,而且ε属于 FIRST (Yj)(1<=j<=i-1),则把FIRST (Yj)-ε加入到FIRST(X)中;如果ε属于所有的FIRST(Yj),则ε加入到FIRST(X)中
2. FOLLOW(X)
1)对于文法的开始符,置#于FOLLOW(S)中
2)若A->αBβ, 则把FIRST (β)-ε加入到FOLLOW(B)中,
3)若A->αB 是一个产生式,或 A->αBβ是一个产生式,而β-> ε,则把FOLLOW(A)加入到FOLLOW(B)中
3. 预测分析表的构造
对文法G的每个产生式, A->α,进行下面的处理
1)对每个终结符a,如果a属于FIRST(α),则把该产生式写入到M[A,a]
2) 若ε属于FIRST(α),则对任何b属于FOLLOW(A), 把该产生式加入到M[A,b]
3)所有无定义的M[A,a]标上出错标志
结论:一个文法G的预测分析表不含多重入口,当且仅当该文法是LL(1)
完美!!!
作业题目: