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

如何求First集与Follow集

已知文法如下,求First集与Follow集
G[E]:E→TE′E′→+TE′∣εT→FT′T′→∗FT′∣ε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→TE′E{\rightarrow} TE'ETE,候选式中未包含终结符,暂时无法得出结果

    当前First集:

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

  3. 第二个式子:E′→+TE′∣εE'{\rightarrow}+TE'|\varepsilonE+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)∣iF{\rightarrow}(E)|iF(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→YX{\rightarrow}YXY,YYY是非终结符,就把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→TE′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′→+TE′∣εE'{\rightarrow}+TE'|\varepsilonE+TEε 可得

    • Follow(E′')可以加入到Follow(T),无变化
  5. T→FT′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′→∗FT′∣εT'{\rightarrow}*FT'|\varepsilonTFTε 可得

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

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

      当前Follow集:

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

  2. 第二次查看所有式子

  3. E→TE′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′→+TE′∣εE'{\rightarrow}+TE'|\varepsilonE+TEε 可得

  • Follow(E′')可以加入到Follow(T),无变化
  1. T→FT′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′→∗FT′∣εT'{\rightarrow}*FT'|\varepsilonTFTε 可得
  • Follow(T′')可以加入到Follow(F),无变化
  1. F→(E)∣iF{\rightarrow}(E)|iF(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→TE′E{\rightarrow} TE'ETEE遇到(,( ϵ{ \epsilon}ϵ First(E),且E只有一个候选式,填入E→TE′E{\rightarrow} TE'ETE
E’+ ϵ{ \epsilon}ϵ First(E′'),在E’的候选式中选择+开头的, 填入E′→+TE′E'{\rightarrow}+TE'E+TEFirst(E′')中含有ε{\varepsilon}ε,故E’遇到Follow(E′')中的终结符时均填入E′→εE'{\rightarrow} {\varepsilon}EεE′→εE'{\rightarrow} {\varepsilon}Eε
TT→FT′T{\rightarrow}FT'TFTT→FT′T{\rightarrow}FT'TFT
T’T′→εT'{\rightarrow} {\varepsilon}TεT′→∗FT′T'{\rightarrow}*FT'TFTT′→εT'{\rightarrow} {\varepsilon}TεT′→εT'{\rightarrow} {\varepsilon}Tε
FF→iF{\rightarrow}iFiF→(E)F{\rightarrow}(E)F(E)

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

总结:

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

如有错误欢迎指正

### FOLLOW 集合的定义 FOLLOW(A) 是一个用于描述非终结符 A 后可能跟随哪些符号的集合。这些符号可能是终结符也可能是文件结束标志 $ 。对于文法 G 的每个非终结符 A ,FOLLOW(A) 定义为:如果 S 是起始符号,则始终有 `$` 属于 FOLLOW(S)[^1]。 ### 计算 FOLLOW 集合的方法 计算 FOLLOW 集合的过程依赖于已知的 FIRST 集合以及文法规则中的产生式关系: #### 初始化 - 如果 `S` 是文法的开始符号,则将 `$` 加入到 FOLLOW(S) #### 更新规则 1. **直接跟在右侧** - 对于形如 `A -> αBβ` 的任何产生式,其中 B 是任意非终结符, 将 FIRST(β)\{ε\} 添加至 FOLLOW(B),即不包括 ε 在内的 FIRST(β) 中的所有成员都应加入到 FOLLOW(B) 中[^3] 2. **传递属性** - 若存在产生式形式为 `A → αB` 或者当 β 可能为空时(即 `A→αBβ` 并且 ε ∈ FIRST(β)`),那么 FOLLOW(A) 应该被添加到 FOLLOW(B) 中 3. **迭代直到稳定** - 上述过程需重复执行直至不再发生变化为止;也就是说,在一次完整的遍历之后如果没有新的元素能够加入任何一个 FOLLOW 集合,则说明所有的 FOLLOW 已经完全得 ```python def compute_follow(grammar, first_sets): follow = {} # Initialize with empty sets and add '$' to start symbol's FOLLOW set for non_terminal in grammar.non_terminals: follow[non_terminal] = set() follow[grammar.start_symbol].add('$') changed = True while changed: changed = False for production in grammar.productions: head, body = production for i, symbol in enumerate(body[:-1]): if symbol.is_nonterminal(): beta_firsts = first_sets[first(body[i+1:])] - {'ε'} if beta_firsts != follow[symbol]: follow[symbol].update(beta_firsts) if 'ε' in first_sets.get(first(body[i+1:]), []): new_elements = follow[head] - follow[symbol] if new_elements: follow[symbol].update(new_elements) changed |= bool(new_elements) last_symbol = body[-1] if len(body) > 0 else None if isinstance(last_symbol, str) and last_symbol.isupper(): # Non-terminal check if (follow[last_symbol] | follow[head]) != follow[last_symbol]: follow[last_symbol].update(follow[head]) changed = True return follow ```
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RENSRM

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

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

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

打赏作者

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

抵扣说明:

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

余额充值