20220908编译原理读书笔记
前言
为啥我今天又开始读书了呢?是因为昨天拔牙之后持续的疼痛让我无法集中注意力工作,但睡觉也是有限度的,否则结果就是3点多还睡不着,依然煎熬。这种疼痛不剧烈但持久,让又人无法忽视。。。。简直是煎熬
还是找点事情分散下注意力吧,某博建议刷114514的题并没有找到这个题号(逃
还是读书吧,也许在我全神贯注的打字时可以让编译原理的复杂性来减轻我的精神负担
4. 自顶向下语法分析方法
语法分析分为自顶向下和自底向上的语法分析,还可以分为确定分析和不确定分析
本篇为确定的自顶向下分析
这种分析也成为面向目标的分析方法
4.1. 思路
从开始符号,根据当前的输入符号,寻找唯一确定的产生式,替换非终结符
如果输入的符号在满足<使用某个生成式的条件>,则就使用这个生成式
简易想法是,给每个生成式生成互不相交的符号集合,根据当前输入在哪个集合里就选取哪个生成式
这个想法贯穿到最终的SELECT集合定义,书本没说,这里提前提出方便理解FIRST集和FOLLOW集的由来
注意,这里的符号不再是单一字母,而是经过词法分析输出的token串,英文为symbol
例1 文法G1[S]:
S->pA|qB
A->cAd|a
B->dB|b
给定输入串W=pccadd,注:教科书这里其实是为了简化,所以用的都是单字母,实际一个字母对应一个symbol
推导过程显然为S->pA->pcAd->pccAdd->pccadd
例2 文法G2[S]:
S->Ap
S->Bq
A->a
A->cA
B->b
B->dB
给定输入串W=ccap
推导过程为S->Ap->cAp->ccAp->ccap
第一步选择S->Ap的原因为A->cA的右侧存在c开头的非终结符
人肉还可以比较容易的看到,但对机器来说不那么容易,需要总结规则
因此如果能知道S->Ap的第一个非终结符是什么就好了
因此定义FIRST集合如下:
设G=(Vt,Vn,P,S)是上下文无关文法
FIRST(t)={t|t=>* aq, t ∈ Vt, t,q ∈ V*}
称FIRST(t)为t的开始符号集或首符号集
给定文法G[S]:
S->aA
S->d
A->bAS
A->NULL
给定输入串W=abd
S->aA->abAS->abNULLS->abNULLd
当面临输入d时,因A的FIRST集里只有b和NULL,不包含d,因此只能认为d的匹配依赖于A后面的符号,因此选择A->NULL
同理找规律,如果我们可以直接知道d可以是A后面首个终结符,那是不是就可以直接选取确定的一个生成式了?
FOLLOW集定义也就是这样,数学表达比较抽象,懒得打了
结合FIRST和FOLLOW集合即可定义SELECT集合,前面的数学证明可保证生成的SELECT集合互不相交
设G=(Vt,Vn,P,S)是上下文无关文法
给定产生式A->t,A是终结符,t属于V的*闭包
若t无法推出空NULL,则SELECT(A->t) = FIRST(t)
显然嘛,没有空的干扰,就直接是第一个非终结符
若t可以推出空NULL,则SELECT(A->t) = (FIRST(t) – {NULL}) ∪ FOLLOW(A)
这个也好理解,排除掉NULL的干扰后,再继续往后寻找A后面的第一个非终结符就行了
LL1文法指的是,从左L到右扫描使用最左L推导,每次往后看1个符号
条件是,对于相同非终结符的两个产生式A->t A->q, 满足SELECT(A->t)∩SELECT(A->q) = {空集}
对于FIRST FOLLOW SELECT集合的生成,纯粹就是力气活了。。。细节不再赘述,相信编程能力过关的同学都能正确实现,这里说思路。可能需要多次扫描才能完成
1.求出能推出NULL的非终结符
2.计算FIRST集合,这里可以根据定义计算,使用迭代法使得每个FIRST集合不再增大即可结束
也可以使用图论的算法计算,思路类似,在图上使用增广做标记即可
3.计算FOLLOW集合,同理也是根据定义计算,使用迭代法使得每个FOLLOW集合不再增大即可结束
也可以使用图论的算法计算,思路类似,在图上使用增广做标记即可
4.计算SELECE集合,根据前面的计算结果合并生成
4.3 非LL1文法到LL1文法的等价变换
4.3.1.提取左公因子
4.3.2.消除左递归
4.4 不确定性的自顶向下分析
略
mark
当前86页
0 Comments