编译原理 规范LR方法

复习

我们之前学习了SLR技术,包括LR(0)文法和SLR(1)文法,不过我们还是遇到了移进-归约冲突(SLR(1)、LR(0))和归约-归约冲突(LR(0))的问题。其原因就是我们的项集构造不够精确,如果能在状态中包含更多的状态信息,在建表的时候就能排除掉一些不可能出现的归约动作。

规范LR方法

通过使用LR(1)项集,充分利用向前看(lookahead)符号,构建规范LR(1)语法分析表来实现。

规范LR(1)项

  • 为什么要使用规范LR(1)项。
    举一个例子。
    有文法(1) S -> L=R | R (2) L -> *R | id (3) R -> L
    构造项集。其中状态2为【S -> L•=R , R -> L】 构建表的时候应该有以下操作:1.当下一个输入为Follow( R)的元素即“=”时,要按照R -> L进行归约。 2.当下一个元素为“=”时,要进行移入操作。这样两者冲突。然而观察产生式,该文法并不可能产生[R = …]这样的最右句型,因此这是伪冲突。

  • 规范LR(1)项 [A -> α•β, a]:即在项的基础上添加了向前看(lookahead)符号。当然,在β不为空时,只要进行移入操作,只有当β为空时,才要根据下一个符号是否为a确定是否要进行归约操作。

  • 定义:[A -> α•β, a] 对于一个可行前缀γ有效的条件是存在一个推导S=>rm δAω =>rmδαβω,其中(1) γ = δα ,且(2) 要么a是ω的第一个符号,要么ω为空且a等于$。

构造LR(1)项集

  • 项集闭包的求法:
    对项集中的一个形如 [A -> α•Bβ, a] 的项,对于每个产生式B -> γ和FIRST(βa)中的终结符号b,将项[ B -> •γ, b] 加入到闭包中。

对增广文法:
(1) S’ -> S
(2) S -> CC
(3) C -> cC | d
构造LR(1)项集

I0 = CLOSURE( { [S’ -> •S, $] } ) = { [S’ -> •S, $], [S -> •CC, $], [C -> •cC, c/d], [C -> •d, c/d] }
//对照闭包的求法,对项[S’ -> •S, $],这产生式是S -> CC,并且FIRST($)只能是$。对项[S -> •CC, $],产生式是C -> cC和C -> d,FIRST(C$)是{c,d}。
I1 = GOTO(I0, S) = CLOSURE( { [S’ -> S•, $] } ) = { [S’ -> S•, $] }
I2 = GOTO(I0, C) = CLOSURE( { [S -> C•C, $] } ) = { [S -> C•C, $], [C -> •cC, $], [C -> •d, $] }
I3 = GOTO(I0, c) = CLOSURE( { [C -> c•C, c/d] } ) = { [C -> c•C, c/d], [C -> •cC, c/d], [C -> •d, c/d] }
I4 = GOTO(I0, d) = CLOSURE( { [C -> d• , c/d] } ) = { [C -> d• , c/d] }
//以上,完成了**I0**上的GOTO函数。同理,如果手工绘制的话可以直接画DFA转换图。
I5 = GOTO(I2, C) = CLOSURE( { [S -> CC•, $] } )= { [S -> CC•, $] }
I6 = GOTO(I2, c) = CLOSURE( { [C -> c•C, $] } ) = { [C -> c•C, $], [C -> •cC, $], [C -> •d, $] }
I7 = GOTO(I2, d) = CLOSURE( { [C -> d•, $] } ) = { [C -> d•, $] }
I8 = GOTO(I3, C) = CLOSURE( { [C -> cC•, c/d] } ) = { [C -> cC•, c/d] }
//GOTO(I3, c) = I3,不产生新状态
I9 = GOTO(I6, C) = CLOSURE( { [C -> cC•, $] } ) = { [C -> cC•, $] }
//GOTO(I6, c) = I6,不产生新状态
DFA转换图如下:
在这里插入图片描述

构造LR(1)分析表

  • 其过程和构造LR(0)分析表一致。

仍然以上面的文法为例。
在这里插入图片描述
在这里主要看一下归约的部分。我们看到,同样是当•符号移到最右侧的时候要进行归约,但此时我们不必像SLR(1)文法一样去求左边符号Follow集了,只要根据lookahead符号,就可以在相应的表格中标记了。

SLR(1)文法、LR(1)文法、LR(0)文法区分

  • 表示范围:LR(1)>SLR(1)>LR(0),区别有:LR(0)文法不能解决移进——归约冲突和归约——归约冲突,一旦出现这两种冲突就不是LR(0)文法,所以可表示范围最小。SLR(1)文法不存在归约——归约冲突,但可能存在移进——归约冲突。LR(1)文法表示范围最大,只是同一个文法,如果构造起自动机来的话LR(1)文法的状态会非常多。解决办法就是使用LALR文法(范围在LR(1)文法和SLR(1)文法之间),具体的实现下一篇再写。

  • 如何判断:
    1.判断是不是LR(0)文法:(1)构造LR(0)自动机 (2)如果自动机中有任何冲突,则不是LR(0)文法。没有冲突就是LR(0)文法。
    2.如何判断是不是SLR(1)文法: (1)构造LR(0)自动机 (2)构造SLR(1)分析表 (3)如果分析表中有任何冲突,则不是SLR(1)文法。没有冲突就是SLR(1)文法。
    3.如何判断是不是LR(1)文法: (1)构造LR(1)自动机 (2)构造LR(1)分析表 (3)如果分析表中有任何冲突,则不是LR(1)文法。没有冲突就是LR(1)文法。
    【注】:移进/归约冲突:同一个项内,点号后面既有终结符号,点号又是某产生式最右边。
    归约/归约冲突:同一个项内,点号出现在两个或更多产生式的最右边。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值