编译原理(七)action表,goto表,LR(1)图,预测分析表与文法判断

今天是自顶向下的专场。。。

如何判别是LL(1)文法呢?

第一种判断方法:

对于文法的产生式任一产生式:

(1)文法不存在左递归

(2)假设A->α | β是其中一个产生式,  如果α 或者 β都不能推出 ε,则FIRST(α )∩FIRST( β)=∅

(3)假设A->α | β是其中一个产生式, 如果α 或者 β至多有一个能推出 ε,或者其中一个经过若干步能推出ε,

则first(α)∩follow(A)=∅(这里假设β能推出 ε)

文法所有的产生式都要满足以上三种情况才符合LL(1)文法

1.为什么要引入FIRST集的概念?
因为有公共左因子的问题,公共左公因子是指在文法的产生式集合中,某个非终结符的多个候选式具有相同的前缀。
一般来说,公共左公因子的产生式为
A→αβ1│αβ2
A→αβ1│αβ2
如果有公共左因子的问题,那么只能采取试探的方法来分析每一个候选式,分析的过程很可能产生回溯,回溯分析法是一种不确定的方法。
若所有候选式都没有公共左因子就可以选择惟一匹配的候选式,不会产生(公共左公因子引起的)回溯。
为了消除回溯,对任何一个非终结符和当前的待匹配符号,期望
要么只有一个候选式可用
要么没有候选式可用
因此引入FIRST集合的概念,就是用来处理左递归的。

当某一非终结符的产生式中含有空产生式时,它的非空产生式右部的开始符号集两两不相交,这个是一定的,如果相交,你是选该非终结符展开呢?还是选择当前为空然后用下一个非终结符展开呢?并与在推导过程中紧跟该非终结符右部可能出现的终结符集也不相交,则仍可构造确定的自顶向下分析。这个自然是对的。因此,引入了一个文法符号的后跟符号集合。这就是Follow集,就是为了,还是为了防止歧义。就是考察A在产生式右端的出现情况,哪些终结符号可以跟随在A后面?

我们得出结论:
  当某一非终结符的产生式中含有空产生式时,它的非空产生式右部的开始符号集两两不相交,并与在推导过程中紧跟该非终结符右部可能出现的终结符集也不相交,则仍可构造确定的自顶向下分析。因此,两个产生式也不能同时推导为空,不然选谁呢?还是歧义不是。

因此当文法中含有形如:
A→α

A→β

的产生式时,其中A∈VN,α、β∈V∗A∈VN,α、β∈V∗,若α和β不能同时推导出空,假定α⇏∗ε,β⇒∗ε,则当
FIRST(α)⋂FOLLOW(A)=∅ 

FIRST(β)⋂FOLLOW(A)=∅
对于非终结符A的替换仍可唯一地确定候选。

SELECT集合定义如下:
一个产生式的选择符号集SELECT。给定上下文无关文法的产生式A→α,A∈VN,α∈V∗,若α⇏∗ε,则SELECT(A→α)=FIRST(α)。

如果α⇒∗ε,则SELECT(A→α)=(FIRST(α)−{ε})⋃FOLLOW(A)。

因此一个上下文无关文法是LL(1)文法的充分必要条件是,对每个非终结符A的两个不同产生式,A→α,A→β,满足
SELECT(A→α)⋂SELECT(A→β)=∅

其中α、βα、β不同时能⇒∗ε。

这样就比较直观一点了。

关于action表与goto表的计算,这个就是找闭包:点在中间就是移进项目,点在最后就是规约项目,根据点在哪里你至少能画出一个图来,然后根据这个图至少能写出协议族来。  

求闭包操作,根据回忆,是由一个初始闭包,初始闭包里放的是所有协议族,但是点在最前面,这个也是一个闭包,因为开始的确都能推出来,然后就是几个goto函数,从而写出剩下的闭包,因此第一个是至关重要的,也叫核心,这就是SLR的求法。

这里就会有移入-规约冲突和规约-规约冲突,这里先不讲。

LR(1)文法正是为了解决这些冲突的.

LR(1)文法就是通过加上一个follow集中的终结符,从而分裂出不同的闭包。

LALR文法就是对LR(1)文法的化简。

预测分析表的构建:

递归下降分析就是一个终结符一个终结符的分析:

非下降的递归分析法也叫表驱动的分析法,用自动机完成:

它的推导过程你是知道的:

预测分析表是用select集产生的,而select还没学。。。看视频吧

1. 自上而下:从开始符号出发,根据产生式规则推导给定的句子。用的是推导
    自下而上:从给定的句子规约到文法的开始符号。用的是归约

如何填表呢?用的是协议族还是图呢?实际上,这俩是等价的,实际上,看图比较方便,因为协议族有省略的,因此协议族根本不能用来填表,它没有转移关系,而图是有转移关系。

如何填SLR表呢?就是只填follow集的那几个终结符,谁的follow集?规约产生式左部的非终结符的follow集,用哪个产生式规约,就用哪个左部的follow集。

如何填LR(1)表呢?就精确到单个字符了,就是后面的那个字符。后面就是整个产生式接的字符嘛,明白了吧。也会存在一个项集中有多个规约式,关键是它们后面的后继符不同,例如:

如果后继符还相同,那么应该就是文法的设计问题了。

LALR合并同心项就是将后面符不同的结合起来,如此而已,必然是在图上做了,用协议族做瞎眼。它会有一个重新变迷糊的过程。出现错误就是合并项集中后继符出现在多个产生式后面。

  1: SLR(1)与LR(0)的关系:

           SLR(1)与LR(0):简单的LR语法分析技术(即SLR(1)分析技术)的中心思想是根据文法构造出LR(0)自动机。

            LR(0):见到First集就移进,见到终态就归约

         SLR(1)见到First集就移进,见到终态先看Follow集,与Follow集对应的项目归约,其它报错。这个并不怎么好懂。

 2: LR(1)与LR(0)的关系:

    规范LR(1)语法分析技术的中心思想是根据文法构造出LR(1)自动机 ,而规范LR(1)自动机构造方法和LR(0)自动机的构造方法相同,只是多增加了向前搜索符号。就这一个不同。

3:规范LR(1)与LALR(1)的关系:

    LALR(1)是对LR(1)项集族I中具有同心项的项集进行合并得到I',然后根据I’进行分析的方法。

二:LL(1),SLR(1),规范LR(1),LALR(1)的判别

      1:LL(1)判断规则

   同左部的产生式的select 集不能相交

   2:SLR(1)判断规则

    方法一:画出文法的LR(0)自动机,如果没有移进--规约冲突,即shift--reduce 冲突,则该文法是SLR(1)文法,SLR也不能完全解决规约-规约冲突,如果follow集两两不相交的话,谁的follow集两两不相交?

接下来是移进还是规约看下一个字符,因此,规约后字符的follow集和那几个a不能相交,当然,一个项目集中最多只能有一个规约项,不然就会有规约-规约冲突,有没有移进-移进冲突?没有,那就是下一个项目集了。如果follow集重叠,那么就不好使了。自然也解决不了规约-规约冲突,理由是一样的

而LR(1)文法由于单独到字符,因此不会出现任何移进-规约冲突,而规约-规约冲突是由于一个项目集中有多个规约式,这个是文法问题吧。一般是文法本身错误,而且是没必要的。没错,除非一开始有一模一样的产生式。

LALR的规约-规约错误是因为合并同心项产生的,说白了就是又扩大了将终结符又扩散成一个组,这样马上又会出现规约-规约错误。

一个举例,很简单了。

   3:LALR(1)和LR(1)的判断规则

    画出文法的LR(1)自动机,如果没有同心项且没有状态冲突,则该文法是LALR(1)文法;如果有同心项且合并同心项有状态冲突,则是LR(1)文法

下一次就做做题吧。

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值