编译原理1

1: ambiguious:

条件:

出现至少两个parse tree或者两种最左/右推导,

一般来说形式是A->aAbA,A->c|d,此时只需要利用第二个式子的两种情况分别替换第一个式子的两个A,如果得到相同结果即可。

2: 生成最小状态

1: 根据是否是终结状态分为两个集合

2: 看第一个集合输入a是否会进入第二个集合,将其细分

3: 看第二步分好的集合输入b是否会进入不同的集合

有时候可以从DFA的表格中直接看出来

3: 正则表达式转为NFA:

闭包: 增加两个状态和两个转移
在这里插入图片描述

或: 增加2个状态和n个转移
在这里插入图片描述
连接:增加一个转移
在这里插入图片描述

4: NFA转为DFA

需要列出的列:S, S ˉ \bar{S} Sˉ, Sa, Sb, Sc,…

S表示初始状态, S ˉ \bar{S} Sˉ表示S经过 ϵ \epsilon ϵ转移到达的状态,包括S状态本身,Sx表示输入x后到达的状态。其中 S ˉ \bar{S} Sˉ需要比较大的空间,其他的空间较小。

1: 列出哪几个状态可以通过输入a,b,c,d,…到达

2: 从开始状态开始,作为S, 然后计算 S ˉ \bar{S} Sˉ,在上面的表对应项找是否有可以输入x到达下一个状态的。

5: 构造LL(1) parse table

表格的列:所有的非终结符,行:所有的终结符+$

对于表格M[N,T]:

  1. 把或的都写开来
  2. 对于每一行,如果非终结符在FIRST集中,找一条规则填入
  3. 填完以后观察有FIRST(A)中是否有e,将A->e填入FOLLOW(A)中

在这里插入图片描述

6: 判断是否是LL(1)

如果已经有LL(1) table,则
LL(1) table includes/doesn’t include anyentry that has more than one item

如何求了FIRST集和FOLLOW集:

1: 对于A-> B1|B2|B3|…, 要求任意两个FIRST(Bi) ∩ FIRST(Bj) = Φ

2: 对于A->e|b , 要求FIRST(b) ∩ FOLLOW(A) = Φ

7: 消除left-recursion:

1: 对于A->Ax1|Ax2|y1|y2|…用A’表示递归产生的式子:

A->y1A’|y2A’|…

然后用A’->x1A’|x2A’|e生成递归产生的符号, 小心注意不要忘记e

2: 如果有A->B, B->Axx|yy这种隐式的,需要将B代入到A

改为A->Axx|yy,然后进行修改

8: 求FIRST集和FOLLOW集:

加入的顺序:

在这里插入图片描述

first集:

1: 终结符和e的first集就是其本身

2: 计算非终结符的first集,对于A->abc
将First(a)-{e}加入到First(A)中,注意不是First(A)等于First(a),而是First(a) in First(A)

3: 如果First(a)包含e, 则将First(b)-{e}加入First(A),依次类推

4.对于A->abcd, 只有当a,b,c,d都包含e时,将e加入First(A)

注意:

1: 计算时的顺序,先算右侧是终结符开始的式子

2: 出现|符号的,两边都加入FIRST集

follow集:

将FOLLOW集看成水杯,

1 if A is the start symbol, the $ is in the Follow(A).

2 if there is a production B→ α Aγ, then First(γ)-{ε} is in Follow(A).

3 if there is a production B→α Aγ, such that ε in First(γ), then Follow(A) contains Follow(B)

注意:

1: 不要忘记开始时将$加入FOLLOW(S)

2: 先观察右侧的非终结符,将后面的FIRST集导入该终结符,
然后将左边的FOLLOW集倒入右边的最后一个
此时注意如果右边最后一个可能为e时,需要再倒入倒数第二个

3: 后面倒入前面的时候,是First集倒入,不是follow集,一定要小心

4: FOLLOW集中不包含e

5: FOLLOW集只计算非终结符的

例子:

P → A | L
L → (S)
S→ PS’
S’→ PS’| ε
A → n|i

写开来:

序号推导规则
1P->A
2P->L
3L->(S)
4S->PS’
5S’->PS’
6S’->e
7A->n|i

算First集:先算右侧开始是终结符的:
First(L) = {(},
First(S’) = {e},
First(A) = {n,i}
然后算右侧是非终结符开始的
r1: First( P) = {n, i}
r2: First( P) = {n, i, (}
r4: First( S) = {n, i, (}
r5: Firsrt(S’) = {n, i, (, e}

算FOLLOW集:
第一轮:
P = {$}
r1: P->A: A={$}
r2: P->L: L={$}
r3: (->S: S={)}
r4: First(S’)-{e}->P, S->P P={n,i,(,),$}, S->S’ S’={)}
第二轮
r1:P->A: A={$,n,i,(,)}
r2: P->L: L={$,n,i,(,)}
完成

9. parse中的操作

LL1:

generate(将非终结符替换)
match (消去终结符)
accept(接受)

LR0:

shift(移动)
reduce(将栈中的元素替换为终结符)
accept(接受)

10. 对比LR,SLR

shift的条件相同,都是A->xx.yyy,如果下一个输入y,则移动为A->xxxy.yyy

只有reduce的条件不同

LR(0)SLR(1)LR(1)LALR(1)
什么时候选择reduce任意输入(不是$)A->abc.,当下一个输入在FOLLOW(A)中时下一个输入是lookhead下一个输入是lookhead
出现了reduce-reduce是否矛盾不能出现两条reduceA->xxx. B->yyy.中,FOLLOW(A)和FOLLOW(B)不能有交集要求两条reduce的lookhead不同要求reduce的lookhead集都不同
出现了reduce-shift是否矛盾不能同时出现reduce-shiftA->xxx.yyy, B->zzz.,要求y不在FOLLOW(B)中要求A->xxx.yyy,则y不在reduce的lookhead中要求A->xx.yyy, y不在reduce的lookhead集中

11.构建DFA:

0: 增加一条规则 S’->S, 写出所有的LR(0) item(方便核的扩充),如果是A->e,则直接写为A->.即可

1: 通过S->.Bxxx作为开始状态的核

2: 如果点后面是一个非终结符B,将B->.xxx全部加入该状态,递归进行,直到点后面全部为终结符

3: 如果出现A->xxxx.表明是一个reduce, 如果出现了A->xxx.yyy,则通过y进入核为A->xxxxy.yyy,的状态

4: 对于每一步,如果点后面是非终结符,则一定别忘记扩充。

5: 对于LR(1),后面跟上一个lookhead,

  • 开始状态lookhead是$, lookhead只有在从核扩展的时候发生改变,如果A->xxx.Byyy, z,则增加为B->.tttt, Firsrt(yyyz)
  • 值得注意的是: B的lookhead虽然是通过FIRST(yyyz)计算出来的,但是一定也在FOLLOW(B)中

12. LR(1) parse table

先构建DFA,然后构建parse table。将终结符和$写在Input下面,将非终结符写在Goto下面。
按照状态来填,

  • 如果是移动,输入是终结符则填写s+目的状态,输入是非终结符,则填写g+目的状态
  • 如果是终止状态,则填写r+哪一条规约规则
  • 如果是S’->S的,在$中填写acc

注意在LR(0)中,输入任何值都进行规约,所以reduce state整行是r,如果是SLR(1)或者LR(1)等,则需要根据输入是否符合要求看是否规约。

A→(A) | a LR(0)
在这里插入图片描述
SLR(1)
在这里插入图片描述

A→(A) | a LR(1)
在这里插入图片描述

13.能力大小比较:

LR(1)>LALR(1)>SLR(1)>LR(0)>LL(1)

14.栈溢出:

LR如果有右递归,则可能发生栈溢出。

15. viable prefixes

对于一个推导过程:E’ => E => E+n => n+n,将其倒着写:
n+n
E+n
E
E’
然后将上下不一样的元素后面加上.
n.+n
E+n.
E.
E’
则可以看出栈中的元素就是点移动过去的元素
在这里插入图片描述
栈中的元素就是可行前缀

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值