编译原理系列之六 自底向上的LR分析法(2) – SLR(1)分析

SLR(1)分析

1.SLR(1)解决的问题

LR(0)文法的要求是①不同时含有移进项目和归约项目,即不存在移进-归约冲突。②不含有两个以上归约项目,即不存在归约-归约冲突。

例如项目集Ii中存在: Ii ={A->α•bγ , B→ γ•,C→β• },此时就同时存在移进-归约冲突和归约-归约;因为你不知道下一步是选择归约还是移进,选择归约的话选择哪个产生式归约。

而事实上一般文法满足这种要求有一定难度,但是假如在归约时出现了移进-归约冲突或者归约-归约冲突,我们可以通过在待分析的字符串中向后再看一位,大多数情况下通过这一位字符就可以确定,选择哪一个表达式归约,或是移进操作。

这种方法就叫做SLR(1)分析法,即简单的LR(1)分析法。

2.SLR(1)分析的解决方法

如上面所述,我们需要知道下一位待分析的字符,然后和现有项目进行比较。

分析过程与LR(0)一样,但是需要解决分析表上的冲突问题。

假如LR(0) 项目集规范族中有项目集 Ii 含有移进-归约冲突和归约-归约冲突: Ii ={A1->α1•b1γ1 ,… , Am->m•bm γm, B1->β 1 • ,…, Bn-> β n • },若集合{b1 ,b2,… ,bm }FOLLOW(B1)FOLLOW(B2) ,…,FOLLOW(Bn)均两两不相交,则可用SLR(1)解决方法解决分析表上第i行上的冲突问题。

假设下一个移进的字符为b,若``b∈ {b1 ,b2,… ,bm },则移进输入符; 若b∈FOLLOW(Bj) ,j=1 ,… ,n,则用Bj-> βj` 归约;

通过这个方法,就可以在知道下一位待分析的字符的情况下,解决冲突。

继续采用SLR(1)分析的方法,我们可以对出错情况进行优化:

在LR(0)和SLR(1)分析中,我们在可以归约且没有冲突时(假如归约成A),是不关心下一位待分析的字符a和和follow(A)的关系的,假如a!∈follow(A)则当前字符串是不被接受的,当然这会在之后的继续移进字符过程中发现错误,但是如果不管是否有冲突看,将SLR(1)分析方法应用到所有分析表的构建过程中,可以提前发现字符串的错误。

综上,我们可以在构建分析表时做出如下改变:

  • 若项目A ->α • aβ属于 Ik 且 GO (Ik, a)= Ij, 期望字符a 为终结符,则置ACTION[k, a] =sj (j表示新状态Ij);
  • 若项目A ->α • Aβ属于 Ik,且GO (Ik, A)= Ij,期望字符 A为非终结符,则置GOTO(k, A)=j (j表示文法中第j个产生式);
  • 若项目A ->α •属于Ik, 那么对任何终结符a,当满足a属于follow(A)时, 置ACTION[k, a]=rj;其中,假定A->α为文法G 的第j个产生式;
  • 若项目S’ ->S • 属于Ik, 则置ACTION[k, #]=“acc”;
  • 分析表中凡不能用上述规则填入信息的空白格均置上“出错标志”

3.SLR(1)分析的例子

算术表达式文法G[E]:
E→E +T | T
T→T * F | F
F→ (E)| i
求此文法的识别规范句型活前缀的DFA,分析句子i+i *i。

  1. 将文法拓广为G’[E’]:
    (0) E’ ->E
    (1) E-> E +T
    (2) E ->T
    (3) T ->T * F
    (4) T ->F
    (5) F ->(E)
    (6) F ->i

  2. 构造识别规范句型活前缀的DFA

2869373-ad08b869d250fc67.png

DFA

  1. 判断有无冲突:

    I1 ,I2 ,I9有移进_归约冲突。
    I1:E´ ->E· E ->E·+T
    I2: E ->T · T ->T · *F
    I9: E ->E+T· T ->T · *F

  2. 考虑能否用SLR(1)方法解决冲突:

    对于I1: { E´ ->E· E ->E·+T} 因为:{+} ∈FOLLOW(E´)= {+} ∩ {#} =∅, 所以可用SLR(1)方法 解决I1的冲突。

    对于I2: {E ->T· T ->T·*F} 因为:{*} ∈ FOLLOW(E)= {*} ∩ {#,),+} = ∅ 所以可用SLR(1)方法解决I2的冲突。

    对于I9: {E ->E+T· T ->T ·*F} 因为:{*} FOLLOW(E)= ∅, 所以可用SLR(1)方法解决I9的冲突。

  3. 构建分析表:

2869373-f48f0b76db25c414.png

分析表

6.句子i+i *i的分析过程:

步骤状态栈符号栈输入符剩余输入串查表操作
10#ii+i*i#Action[0,i]=S5移进i
20 5# i++i*i#Action[5,+]=r6,GOTO(0,F)=3用F -> i 归约
30 3# F++i*i#Action[3,+]=r4,GOTO(0,T)=2用F -> T归约
40 2# T++i*i#Action[2,+]=r4,GOTO(0,E)=1用F -> E归约
50 1# E++i*i#Action[1,+]=S6移进+
60 1 6# E +ii*i#Action[6,i]=S6移进+
70 1 6 5# E + i**i#Action[5,*]=r6,GOTO(6,F)=3用F -> i 归约
80 1 6 3# E + F**i#Action[3,*]=r6,GOTO(6,T)=9用F -> F 归约
90 1 6 9# E + T**i#Action[9,*]=S7移进*
100 1 6 9 7# E + T *ii#Action[7,i]=S5移进i
110 1 6 9 7 5# E + T * i##Action[5,#]=r6,GOTO(7,F)=10用F -> i 归约
120 1 6 9 7 10# E + T * F##Action[10,#]=r3,GOTO(6,T)=9用T -> T+F归约
130 1 6 9# E + T##Action[9,#]=r1,GOTO(0,E)=1用E -> E+T归约
140 1# E##Action[1,#]=acc接受
  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值