LR(1)项目集族的构造:如何确定前向搜索符(新版)

旧版链接 https://blog.csdn.net/hhhhhhhhhhkkkkkkkkkk/article/details/19990287
按照这个标题搜进来的各位是不是以为这也是和课本一样的内容呢,其实这是我看了两天课本才理解出来的内容啊,绝对和课本不一样。 课本上LR(1)项目集族的构造内容如下
以S′→·S,#属于初始项目集中,把’#‘号作为向前搜索符,表示活前缀为γ(若γ是有关S产生式的某一右部)要归约成S时,必须面临输入符为’#'号才行。我们对初始项目S′→·S,# 求闭包后再用转换函数逐步求出整个文法的LR(1)项目集族。具体构造步骤如下:
(1) 构造LR(1)项目集的闭包函数。
a)假定I是一个项目集, I 的任何项目都属于CLOSURE(I)。
b) 若有项目 A→α·Bβ,a 属于CLOSURE(I),B→γ是文法中的产生式,β∈V*,b∈FIRST(βa), 则 B→·γ,b 也属于CLOSURE(I)中。
c) 重复b)直到CLOSURE(I)不再增大为止。
大家是不是看的一头雾水呢。课本上还给出了一个例子:
文法:

0 S'->S
1 S->aAd
2 S->bAc
3 S->aec
4 S->bed
5 A->e

项目集簇:

S
a
b
A
e
A
e
d
c
c
d
I0:
S'->.S,#
S->.aAd,#
S->.bAc,#
S->.aec,#
S->.bed,#
I1:
S'->S.,#
I2:
S->a.<font color=#F00>A</font><font color=#0F0>d</font><font color=#080>,#</font>
S->a.ec,#
<font color=#F00>A</font>->.e,<font color=#0F0>d</font>
I3:
S->b.<font color=#F00>A</font><font color=#0F0>c</font><font color=#080>,#</font>
S->b.ed,#
<font color=#F00>A</font>->.e,<font color=#0F0>c</font>
I4:
S->aA.d,#
I5:
S->ae.c,#
A->e.,<font color=#F0F>d</font>
I6:
S->bA.c,#
I7:
S->be.d,#
A->e.,<font color=#F0F>c</font>
I8:
S->aAd.,#
I9:
S->aec.,#
I10:
S->bAc.,#
I11:
S->bed.,#

大家是不是在想I2中

A->e.,d

后的d,
I7中

A->e.,c

后的c是怎么来的呢?

课本的答案是对的,但是写法很是让我们一头雾水,下面让我们来看看答案是怎么出来的:

  • 1.一开始,S’是整个句子,所以后面理所当然跟句子结束符#。
    然后S后面是‘ε’(就是什么都没有)所以β=ε,
    接着逗号后面是‘#’即a=#,
    这样FIRST(βa)=FIRST(ε#)={#}。这就是I0中S后面#号的来历。

  • 2.在I2:S->a. Ad,#中
    A的后面是d,所以FIRST(d#)={d}(就是“d#”的第一个终结符d),所以接下来A的后面跟的是d如图中绿色所示。

  • 3.在确定了A的逗号后面的搜索符后,基本上就可以直接照搬下去了,如图中的紫色所示。(其实#号一直都在照搬来着,大家注意到没?)

下面再讲一点FIRST(β)的计算。

  • 1.如果β的第一个字符是终结符,如:
β=aAbbC
β=eBbbD

那么

β
aAbbC
eBbbD
a
e
a,e

即:

FIRST(β)
=FIRST(aAbbC)+FIRST(eBbbD)
={a}+{e}={a,e};   (‘+’代表‘并’,那个符号不好打,用‘+’来代替了。​)
  • 2.如果β的第一个字符是非终结符,如:
β=AEbC
A=DBac
D=ε
B=ea
B=bd
E=ε

那么:

β
AEbC
(DBac)EbC
((ε)Bac)EbC
(εBac)EbC
(Bac)EbC
εEbC
(Bac)EbC
(E)bC
(Bac)EbC
(ε)bC
(Bac)EbC
bC
((ea)ac)EbC
((bd)ac)EbC
b
(eac)EbC
(bac)EbC
b
eEbC
bEbC
b
e
b
e,b

即:

FIRST(β)
=FIRST(AEbC)
=FIRST(FIRST(A)EbC)
=FIRST(FIRST(DBac)EbC)
=FIRST(FIRST(FIRST(D)Bac)EbC)
=FIRST(FIRST(εBac)EbC)        (ε表示空,如果不是空,就结束了,但是空还要计算ε后面的Bac)
=FIRST(FIRST(εBac)EbC)+FIRST(FIRST(Bac)EbC)
=FIRST(εEbC)+FIRST(FIRST(Bac)EbC)
=FIRST(FIRST(E)bC)+FIRST(FIRST(Bac)EbC)
={εbC}+FIRST(FIRST(Bac)EbC)
={bC}+FIRST(FIRST(FIRST(ea)ac)EbC)+FIRST(FIRST(FIRST(bd)ac)EbC)        (由于B有两个推导式,所以分开来写并求并集,‘+’代表‘并’)
={b}+FIRST(FIRST(eac)EbC)+FIRST(FIRST(bac)EbC)
={b}+FIRST(eEbC)+FIRST(bEbC)
={b}+{e}+{b}
={e,b}

为了普遍性,我把β搞的复杂了点,多看几遍,你就会了。如果不会,在下面留言。我可是看了两天才看懂的。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值