编译原理FIRST集、FOLLOW集、SELECT集求法通俗解释 & LL(1)文法判定

1.为什么要引入FIRST集的概念?

  • 因为有公共左因子的问题,公共左公因子是指在文法的产生式集合中,某个非终结符的多个候选式具有相同的前缀。
  • 一般来说,公共左公因子的产生式为
    Aαβ1αβ2
  • 如果有公共左因子的问题,那么只能采取试探的方法来分析每一个候选式,分析的过程很可能产生回溯,回溯分析法是一种不确定的方法。
  • 若所有候选式都没有公共左因子就可以选择惟一匹配的候选式,不会产生(公共左公因子引起的)回溯。
  • 为了消除回溯,对任何一个非终结符和当前的待匹配符号,期望
    • 要么只有一个候选式可用
    • 要么没有候选式可用

因此引入以下FIRST集合的概念:

  • α(VTVN) ,有
    FIRST(α){a|αa,aVT}

    特别地,若 αε ,则 εFIRST(α)

因此对于每一文法符号 XVTVN ,构造 FIRST(X) 的方法为:
使用下列规则,直至每个FIRST集不再增大为止:

  • XVT ,则 FIRST(X)={X} (意思是如果 X 是终结符,则其FIRST集合为其自身);
  • XVN ,那么 X 的产生式分以下三种情况:

    • Xε

    • εFIRST(X)
    • Xa
    • aFIRST(X)
    • XY ,且 YVN
    • FIRST(Y){ε}FIRST(X)

    • 特例: XY1Y2Yi1YiYk
          且 Y1,Y2,Yi1VN
            Y1,Y2,Yi1ε

      • FIRST(Yj){ε}FIRST(X)(1ji1)FIRST(Yi)FIRST(X)
    • 特别地,当 Y1Y2Yi1YiYkε

      • εFIRST(X)

    结论:针对无空产生式的文法G,同一非终结符的任两个产生式的右部符号串的FIRST集无交集,即可进行确定的自顶向下分析。

    2.为什么要引入FOLLOW集的概念?

    考虑文法G[S]:
    SaA
    Sd
    AbAS
    Aε
    求得各终结符和符号串的FIRST集合如下:
    FIRST(S)={a,d}
    FIRST(A)={b,ε}
    FIRST(aA)={a}
    FIRST(d)={d}
    FIRST(bAS)={b}
    FIRST(ε)={ε}
      若输入串 W=abd ,则试图推导出abd串的推导过程为 SaAabASabSabd
      从以上推导过程中可以看到,在第2步到第3步的推导中,即 abASabS 时,因为当前面临的输入符号为 d ,但是最左非终结符A的产生式右部的开始符号集都不包含 d ,但有ε,因此对于 d 的匹配自然认为只能依赖于在可能的推导过程中A的后面的符号,所以这时候选用产生式 Aε 向下推导。而当前 A 后面的符号为S S 产生式右部的开始符号集包含了d,所以例子中可用 Sd 推导得到匹配。
    语法树如下所示:
    这里写图片描述
    很显然,我们从以上叙述中可以得出:
      当某一非终结符的产生式中含有空产生式时,它的非空产生式右部的开始符号集两两不相交,并与在推导过程中紧跟该非终结符右部可能出现的终结符集也不相交,则仍可构造确定的自顶向下分析。因此,引入了一个文法符号的后跟符号集合。
    引入以下FOLLOW集的概念:

    • AVN ,有
      FOLLOW(A)={a|SAaaVT}
      SA ,则规定 #FOLLOW(A)
      这里用#作为输入串的结束符,也称为输入串括号。

    因此对于每一文法符号 AVN ,实际上求 FOLLOW(A)
    就是考察A在产生式右端的出现情况,哪些终结符号可以跟随在A后面?

    使用下列规则,直至每个FOLLOW集不再增大为止:

    • 首先,设S为文法的开始符号,把 {#} 加入 FOLLOW(S) 中(这里#为句子括号)
    • BαAβ 是一个产生式,则 FIRST(β){ε}FOLLOW(A)
    • 如果 BαA 或者 BαAβ βε ,则 FOLLOW(B)FOLLOW(A)
      • 解释: 因为在推导过程中可能出现如下的句型序列:
      • Sα1Bβ1α1αAββ1α1αAβ1

    例题:
    ABCc | gDB
    BbCDE | ε
    CDaB | ca
    DdD | ε
    EgAf | c

    非终结符FIRSTFOLLOW
    A{a, b, c, d, g}{f, #}
    B{b, ε }{a, c, d, g, f, #}
    C{a, c, d}{c, d, g}
    D{d, ε }{a, b, c, g, f, #}
    E{c, g}{a, c, d, g, f, #}

    对于FIRST集合,解释其中的FIRST(A)的求解。

    • ABCc 属于上述产生式的特例情况,很显然 BεCε ,因此
      (FIRST(B){ε})FIRST(C)FIRST(A)
    • AgDB 属于上述产生式的第二种情况,因此 gFIRST(A)
    • 最后得出:
      FIRST(A)=(FIRST(B){ε})FIRST(C){g}
    • FIRST(B)={b,ε}FIRST(C)={a,c,d}
    • FIRST(A)={a,b,c,d,g}

    对于FOLLOW集合,有如下的计算情况:

    FOLLOW(A)=(FIRST(f){ε}){#}={f,#}

    FOLLOW(B)   =(FIRST(Cc){ε})FOLLOW(A)FOLLOW(C)={a,c,d}{f,#}FOLLOW(C)={a,c,d}{f,#}{c,d,g}={a,c,d,g,f,#}

    FOLLOW(C)  =(FIRST(c){ε})(FIRST(DE){ε})={c}(FIRST(D){ε})FIRST(E)={c,d,g}

    FOLLOW(D)  =(FIRST(B){ε})FOLLOW(A)(FIRST(E){ε})(FIRST(aB){ε})={b}{f,#}{c,g}{a}={a,b,c,g,f,#}

    FOLLOW(E) =FOLLOW(B)={a,c,d,g,f,#}

    3.为什么要引入SELECT集的概念?

    由于从2中我们得出结论:
      当某一非终结符的产生式中含有空产生式时,它的非空产生式右部的开始符号集两两不相交,并与在推导过程中紧跟该非终结符右部可能出现的终结符集也不相交,则仍可构造确定的自顶向下分析。
      因此当文法中含有形如:

    AαAβ

    的产生式时,其中 AVN,αβV ,若 α β 不能同时推导出空,假定 αεβε ,则当
    FIRST(α)FOLLOW(A)= FIRST(β)FOLLOW(A)=

    也即是 FIRST(α)(FIRST(β)FOLLOW(A))= 时,对于非终结符A的替换仍可唯一地确定候选。为了表示和分析方便,因此引入了SELECT集合。
    SELECT集合定义如下:

    • 一个产生式的选择符号集SELECT。给定上下文无关文法的产生式 Aα,AVN,αV ,若 αε ,则 SELECT(Aα)=FIRST(α)

    • 如果 αε ,则 SELECT(Aα)=(FIRST(α){ε})FOLLOW(A)

    因此一个上下文无关文法是LL(1)文法的充分必要条件是,对每个非终结符A的两个不同产生式, AαAβ ,满足

    SELECT(Aα)SELECT(Aβ)=

    其中 αβ 不同时能 ε

    再次回到上述例题

    ABCc | gDB
    BbCDE | ε
    CDaB | ca
    DdD | ε
    EgAf | c


    非终结符FIRSTFOLLOW
    A{a, b, c, d, g}{f, #}
    B{b, ε }{a, c, d, g, f, #}
    C{a, c, d}{c, d, g}
    D{d, ε }{a, b, c, g, f, #}
    E{c, g}{a, c, d, g, f, #}


    右部产生式FIRST
    BCc{a, b, c, d}
    gDB{ g }
    bCDE{ b }
    ε { ε }
    DaB{a, d}
    ca{ c }
    dD{ d }
    gAf{ g }
    c{ c }

      因此根据以上所求得的FIRST集和FOLLOW集,可求得各产生式的SELECT集合如下:

             SELECT(ABCc)={a,b,c,d}SELECT(AgDB)={g}SELECT(BbCDE)={b}SELECT(Bε)={a,c,d,g,f,#}SELECT(CDaB)={a,d}SELECT(Cca)={c}SELECT(DdD)={d}SELECT(Dε)={a,b,c,g,f,#}SELECT(EgAf)={g}SELECT(Ec)={c}

      由上可知,有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。

  • 83
    点赞
  • 268
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值