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

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

作者: getianao | 来源:发表于2018-12-07 17:28 被阅读0次

    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

    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. 构建分析表:

    分析表

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

    步骤 状态栈 符号栈 输入符 剩余输入串 查表 操作
    1 0 # i i+i*i# Action[0,i]=S5 移进i
    2 0 5 # i + +i*i# Action[5,+]=r6,GOTO(0,F)=3 用F -> i 归约
    3 0 3 # F + +i*i# Action[3,+]=r4,GOTO(0,T)=2 用F -> T归约
    4 0 2 # T + +i*i# Action[2,+]=r4,GOTO(0,E)=1 用F -> E归约
    5 0 1 # E + +i*i# Action[1,+]=S6 移进+
    6 0 1 6 # E + i i*i# Action[6,i]=S6 移进+
    7 0 1 6 5 # E + i * *i# Action[5,*]=r6,GOTO(6,F)=3 用F -> i 归约
    8 0 1 6 3 # E + F * *i# Action[3,*]=r6,GOTO(6,T)=9 用F -> F 归约
    9 0 1 6 9 # E + T * *i# Action[9,*]=S7 移进*
    10 0 1 6 9 7 # E + T * i i# Action[7,i]=S5 移进i
    11 0 1 6 9 7 5 # E + T * i # # Action[5,#]=r6,GOTO(7,F)=10 用F -> i 归约
    12 0 1 6 9 7 10 # E + T * F # # Action[10,#]=r3,GOTO(6,T)=9 用T -> T+F归约
    13 0 1 6 9 # E + T # # Action[9,#]=r1,GOTO(0,E)=1 用E -> E+T归约
    14 0 1 # E # # Action[1,#]=acc 接受

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/ubtacqtx.html