如何求First集与Follow集(超详细)

如何求First集与Follow集

已知文法如下,求First集与Follow集
G [ E ] : E → T E ′ E ′ → + T E ′ ∣ ε T → F T ′ T ′ → ∗ F T ′ ∣ ε F → ( E ) ∣ i G[E]: E{\rightarrow} TE' \\ {\quad\quad\quad\quad\quad}E'{\rightarrow}+TE'|\varepsilon \\ {\quad\quad\quad}T{\rightarrow}FT'\\ {\quad\quad\quad\quad\quad}T'{\rightarrow}*FT'|\varepsilon\\ {\quad\quad\quad}F{\rightarrow}(E)|i\\ G[E]:ETEE+TEεTFTTFTεF(E)i

First集:

  1. 第一次查看所有式子

  2. 首先看第一个式子: E → T E ′ E{\rightarrow} TE' ETE,候选式中未包含终结符,暂时无法得出结果

    当前First集:

    First(E) = { }
    First(E ′ ' ) = { }
    First(T) = { }
    First(T ′ ' ) = { }
    First(F) = { }

  3. 第二个式子: E ′ → + T E ′ ∣ ε E'{\rightarrow}+TE'|\varepsilon E+TEε,可以得到其所有候选式的串首终结符: +、 ε {\varepsilon} ε,将其加入到First(E ′ ' )中

    当前First集:

    First(E) = { }
    First(E ′ ' ) = {+, ε {\varepsilon} ε}
    First(T) = { }
    First(T ′ ' ) = { }
    First(F) = { }

  4. 第三个式子同 1,First集无变化

  5. 第四个式子同 2,将 *、 ε {\varepsilon} ε加入到First(T ′ ' )中

    当前First集:

    First(E) = { }
    First(E ′ ' ) = {+, ε {\varepsilon} ε}
    First(T) = { }
    First(T ′ ' ) = { *, ε {\varepsilon} ε}
    First(F) = { }

  6. 第五个式子: F → ( E ) ∣ i F{\rightarrow}(E)|i F(E)i,将 (、i 加入到First(F)中

    当前First集:

    First(E) = { }
    First(E ′ ' ) = {+, ε {\varepsilon} ε}
    First(T) = { }
    First(T ′ ' ) = { *, ε {\varepsilon} ε}
    First(F) = { (,i}

  7. 第二次查看所有式子

  8. 第一个式子可得,First(T) 是First(E) ,但First(T)是空的,故无变化

    [注:参照书本58页第三行②,若有 X → Y X{\rightarrow}Y XY, Y Y Y是非终结符,就把First(Y)中非 ε {\varepsilon} ε元素加入到First(X)中]

  9. 第二个式子不能得到新的结果,下一步

  10. 第三个式子可得,First(F)是First(T),故将 ( ,i 加入到First(T)
    当前First集:

    First(E) = { }
    First(E ′ ' ) = {+, ε {\varepsilon} ε}
    First(T) = { (,i }
    First(T ′ ' ) = { *, ε {\varepsilon} ε}
    First(F) = { (,i }

  11. 后续式子均不能得到新的结果,下一步

  12. 第三次查看所有式子

  13. 第一个式子得,First(T) 是First(E),故First集产生变化

    当前First集:

    First(E) = {(,i }
    First(E ′ ' ) = {+, ε {\varepsilon} ε}
    First(T) = { (,i }
    First(T ′ ' ) = { *, ε {\varepsilon} ε}
    First(F) = { (,i }

  14. 后续式子均无法得到新的结果,求First集完毕

  15. 注:理论上每次First集产生变化就要重新查看一遍所有式子,这里为了方便进行了简写,实际做题时可以按照变化一次重新求一次

Follow集:

求Follow集是在已经求出First集的基础上进行

  1. 将#置入Follow(文法开始符号),即Follow(E)

    当前Follow集:

    Follow(E) = { # }
    Follow(E ′ ' ) = { }
    Follow(T) = { }
    Follow(T ′ ' ) = { }
    Follow(F) = { }

  2. 第一次查看所有式子

  3. E → T E ′ E{\rightarrow} TE' ETE可得

    • Follow(E)可以加入到Follow(E ′ ' ),将 # 置入Follow(E ′ ' )

    • Follow(E)可以加入到Follow(T),将 # 置入Follow(T)

      [注:因为E ′ ' 可能为 ε {\varepsilon} ε],

    • First(E ′ ' )中非 ε {\varepsilon} ε元素可以加入到Follow(T)中,将 + 置入Follow(T)

      当前Follow集:

      Follow(E) = { # }
      Follow(E ′ ' ) = { # }
      Follow(T) = { #,+ }
      Follow(T ′ ' ) = { }
      Follow(F) = { }

  4. E ′ → + T E ′ ∣ ε E'{\rightarrow}+TE'|\varepsilon E+TEε 可得

    • Follow(E ′ ' )可以加入到Follow(T),无变化
  5. T → F T ′ T{\rightarrow}FT' TFT可得

    • Follow(T)可以加入到Follow(T ′ ' ),将 #、+ 置入Follow(T ′ ' )

    • Follow(T)可以加入到Follow(F),将 #、+ 置入Follow(F)

    • First(T ′ ' )中非 ε {\varepsilon} ε元素可以加入到Follow(F)中,将 * 置入Follow(F)

      当前Follow集:

      Follow(E) = { # }
      Follow(E ′ ' ) = { # }
      Follow(T) = { #,+ }
      Follow(T ′ ' ) = { #,+ }
      Follow(F) = {#,+ ,* }

  6. T ′ → ∗ F T ′ ∣ ε T'{\rightarrow}*FT'|\varepsilon TFTε 可得

  • Follow(T ′ ' )可以加入到Follow(F),无变化
  1. F → ( E ) ∣ i F{\rightarrow}(E)|i F(E)i 可得

    • 非终结符E后有一个终结符 ),故将 ) 置入Follow(E)

      当前Follow集:

      Follow(E) = { #,) }
      Follow(E ′ ' ) = { # }
      Follow(T) = { #,+ }
      Follow(T ′ ' ) = { #,+ }
      Follow(F) = {#,+ ,* }

  2. 第二次查看所有式子

  3. E → T E ′ E{\rightarrow} TE' ETE可得

    • Follow(E)可以加入到Follow(E ′ ' ),将 ) 置入Follow(E ′ ' )

    • Follow(E)可以加入到Follow(T),将 ) 置入Follow(T)

    • First(E ′ ' )中非 ε {\varepsilon} ε元素可以加入到Follow(T)中,已有+,Follow(T)无变化

      当前Follow集:

      Follow(E) = { #,) }
      Follow(E ′ ' ) = { # ,) }
      Follow(T) = { #,+ ,) }
      Follow(T ′ ' ) = { #,+ }
      Follow(F) = {#,+ ,* }

  4. E ′ → + T E ′ ∣ ε E'{\rightarrow}+TE'|\varepsilon E+TEε 可得

  • Follow(E ′ ' )可以加入到Follow(T),无变化
  1. T → F T ′ T{\rightarrow}FT' TFT可以得到
  • Follow(T)可以加入到Follow(T ′ ' ),将 ) 置入Follow(T ′ ' )

  • Follow(T)可以加入到Follow(F),将 )置入Follow(F)

  • First(T ′ ' )中非 ε {\varepsilon} ε元素可以加入到Follow(F)中,已有*,Follow(F)无变化

    当前Follow集:

    Follow(E) = { #,) }
    Follow(E ′ ' ) = { # ,) }
    Follow(T) = { #,+ ,) }
    Follow(T ′ ' ) = { #,+,) }
    Follow(F) = {#,+ ,*,) }

  1. T ′ → ∗ F T ′ ∣ ε T'{\rightarrow}*FT'|\varepsilon TFTε 可得
  • Follow(T ′ ' )可以加入到Follow(F),无变化
  1. F → ( E ) ∣ i F{\rightarrow}(E)|i F(E)i 并不能得到新的结果
  2. 再次查看所有式子,均不能产生新的变化,求Follow集完毕
  3. 注:理论上每次Follow集产生变化就要重新查看一遍所有式子,这里为了方便进行了简写,实际做题时可以按照变化一次重新求一次

那么在已知First集和Follow集的情况下如何构造LL1分析表呢

First集与Follow集:

First(E) = {(,i }
First(E ′ ' ) = {+, ε {\varepsilon} ε}
First(T) = { (,i }
First(T ′ ' ) = { *, ε {\varepsilon} ε}
First(F) = { (,i }

Follow(E) = { #,) }
Follow(E ′ ' ) = { # ,) }
Follow(T) = { #,+ ,) }
Follow(T ′ ' ) = { #,+,) }
Follow(F) = {#,+ ,*,) }

LL1分析表:

第一列为非终结符,第一行为终结符

i+*(#
EE遇到 i,i ϵ { \epsilon} ϵ First(E),且E只有一个候选式,填入 E → T E ′ E{\rightarrow} TE' ETEE遇到(,( ϵ { \epsilon} ϵ First(E),且E只有一个候选式,填入 E → T E ′ E{\rightarrow} TE' ETE
E’+ ϵ { \epsilon} ϵ First(E ′ ' ),在E’的候选式中选择+开头的, 填入 E ′ → + T E ′ E'{\rightarrow}+TE' E+TEFirst(E ′ ' )中含有 ε {\varepsilon} ε,故E’遇到Follow(E ′ ' )中的终结符时均填入 E ′ → ε E'{\rightarrow} {\varepsilon} Eε E ′ → ε E'{\rightarrow} {\varepsilon} Eε
T T → F T ′ T{\rightarrow}FT' TFT T → F T ′ T{\rightarrow}FT' TFT
T’ T ′ → ε T'{\rightarrow} {\varepsilon} Tε T ′ → ∗ F T ′ T'{\rightarrow}*FT' TFT T ′ → ε T'{\rightarrow} {\varepsilon} Tε T ′ → ε T'{\rightarrow} {\varepsilon} Tε
F F → i F{\rightarrow}i Fi F → ( E ) F{\rightarrow}(E) F(E)

注:大写字母表示非终结符,小写字母与符号表示终结符

总结:

  1. 当非终结符遇到其First集中的终结符时填入相应候选式
  2. 当非终结符的First集中含有 ε {\varepsilon} ε 元素时,遇到其Follow集中的终结符时填入 非终结符 → ε {\rightarrow} {\varepsilon} ε

如有错误欢迎指正

这是一个计算文法的Follow的函数,主要实现以下功能: 1. 先判断是否已经计算出能够推出空串的非终结符集合,如果没有则调用MakeCanReachEmptyTable()函数计算。 2. 对于每个非终结符,都创建一个空的Follow集合。 3. 将起始符号的Follow集合设置为“#”。 4. 循环计算每个产生式的Follow集合,直到没有新元素加入集合为止。 5. 对于每个产生式A -> B1B2...Bn,将B1的Follow集合加入B2的Follow集合,B2的Follow集合加入B3的Follow集合,以此类推。 6. 如果Bn能够推出空串,则将A的Follow集合加入Bn-1的Follow集合。 7. 如果Bn是非终结符,则将A的Follow集合加入Bn的Follow集合。 现在我们来详细解释一下函数的具体实现: 首先,我们创建一个空的Follow集合,用于存储每个非终结符的Follow集合。 然后,我们将起始符号的Follow集合设置为“#”。 进入主循环,我们对于每个产生式A -> B1B2...Bn,从左到右扫描B1到Bn-1,进行如下操作: 1. 如果B1是非终结符,则将A的Follow集合加入B1的Follow集合。 2. 如果Bn能够推出空串,则将A的Follow集合加入Bn-1的Follow集合。 3. 对于B1到Bn-1中的每个非终结符B,将B的Follow集合加入B+1的Follow集合。 接下来,我们处理Bn,如果Bn是非终结符,则将A的Follow集合加入Bn的Follow集合。 最后,我们判断是否有新元素加入Follow集合,如果有则继续循环,否则跳出循环。 其中,Set是一个自定义的集合类型,Vn表示非终结符集合,P是产生式集合,cStart表示文法的起始符号。
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RENSRM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值