news 2026/5/29 5:09:32

编译原理|FIRST、FOLLOW、SELECT集超详细解读(含例题)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
编译原理|FIRST、FOLLOW、SELECT集超详细解读(含例题)

编译原理|FIRST、FOLLOW、SELECT集超详细解读(含例题)


在编译原理的自顶向下语法分析中,FIRST、FOLLOW、SELECT三个集合是核心基石——它们是构造LL(1)分析表、判断文法是否为LL(1)文法的关键。很多同学刚开始接触时会被抽象的定义和推导规则难住,今天就结合通俗解读、严谨规则和两道例题,帮大家彻底吃透这三个集合的求法与应用。


建议阅读顺序:先吃透三个集合的核心定义与规则,再跟随经典算术表达式例题实操,之后用简单例题查漏补缺,最后通过总结掌握LL(1)判定方法,循序渐进,高效吃透。

一、核心概念详解(定义+通俗解读+求法规则)

先明确三个集合的核心定位:FIRST集看“开头”,FOLLOW集看“后面”,SELECT集看“选择哪条产生式”,三者层层递进、相互关联。

1. FIRST集(首符号集)

定义

对于任意一个文法符号串α(可以是终结符、非终结符或它们的组合),FIRST(α) 就是α能够推导出的所有可能串中,第一个终结符的集合。如果α能推导出空串(ε,文中也写作varepsilon),那么ε也在FIRST集中。

通俗理解

想象你是一个“预言家”,站在一个非终结符(比如E)的门口,你想知道它变身后,第一眼能看到的终结符(实际的字符)是什么?如果它能直接隐身(变成空串ε),那ε也要算上。就像看一本书的下一章,你想知道这一章最先可能看到哪些关键线索(终结符)。

求法规则(迭代计算直到集合不再增大)

💡

  • 终结符:如果X是终结符,则FIRST(X) = {X}(自己就是自己的首符号)。
  • 空产生式:如果有X→ε,则将ε加入FIRST(X)。
  • 非终结符推导:对于产生式X→Y₁Y₂…Yₖ,先把FIRST(Y₁)中除ε以外的所有元素加入FIRST(X);如果Y₁能推出ε,则继续把FIRST(Y₂)中除ε以外的所有元素加入FIRST(X),以此类推;如果Y₁、Y₂、…、Yₖ全都能推出ε,那么把ε也加入FIRST(X)。
  • ✅ 核心要点:FIRST集的关键是“穿透空串”,非终结符推导时,只要前面的符号能推空,就继续往后找首符号。

2. FOLLOW集(后跟符号集)

定义

对于非终结符A,FOLLOW(A)是在文法的某个句型中,紧跟在A后面的所有终结符的集合。注意:FOLLOW集只针对非终结符,且如果A可以是句型的最后一个符号,输入结束符(通常记作#)也属于FOLLOW(A)。

通俗理解

FOLLOW集就像是给非终结符找一个“贴身保镖”。我们要找出在所有合法的句型中,谁(终结符)有资格紧跟在这个非终结符的屁股后面。如果它可能出现在句子的末尾,那么结束符#也是它的保镖。就像某个主要角色(非终结符)的戏份暂时告一段落后,接下来可能紧接着出现哪些场景或人物(终结符)。

求法规则(迭代计算直到集合不再增大)

💡

  • 开始符号:将结束符#加入文法开始符号S的FOLLOW(S)中(开始符号的最后一定是结束符)。
  • 一般情况(A→αBβ):如果B后面跟着符号串β,则将FIRST(β)中除ε以外的所有元素加入FOLLOW(B)(β的首符号就是B的保镖)。
  • 结尾或后面能推空(A→αB 或 A→αBβ且β⇒ε):这意味着B后面可能什么都没有,或者β消失后B就到了结尾。此时,将FOLLOW(A)中的所有元素加入FOLLOW(B)(A的保镖也是B的保镖)。
  • ✅ 核心要点:FOLLOW集的关键是“继承保镖”,若后续符号能推空,就继承前面非终结符的FOLLOW集元素。

3. SELECT集(选择符号集)

定义

SELECT集是针对产生式的。对于产生式A→α,SELECT(A→α)表示在语法分析过程中,当我们处于非终结符A,且当前输入的终结符属于这个集合时,我们就应该选择使用A→α这条规则进行推导。

通俗理解

SELECT集是“行动指南”。当你在语法分析时,如果当前站在非终结符A上,且手里的输入字符属于某个产生式的SELECT集,你就必须果断选择这条产生式进行推导,不会出错。

求法规则

💡

  • 如果α不能推导出ε:SELECT(A→α) = FIRST(α)(直接取右部的首符号集)。
  • 如果α能推导出ε(即α⇒*ε):SELECT(A→α) = (FIRST(α) - {ε}) ∪ FOLLOW(A)。
    通俗解释:如果α能变成空,那么当输入符号既不在α的开头里,又恰好是A后面可能跟的符号时,我们就让A推出空串,把匹配权交给后面的符号。
  • ✅ 核心要点:SELECT集的关键是“区分空与非空”,非空右部看FIRST集,空右部看FOLLOW集。

掌握了三个集合的定义与规则后,我们通过经典算术表达式文法实操,把理论落地,手把手教你推导过程,帮你巩固核心知识点。

二、经典例题演练(深度实操)

为了帮大家巩固三个集合的求法,我们选用编译原理中经典的算术表达式文法作为例题。这个文法不仅结构清晰,还包含了空产生式(ε),非常适合用来练习。我们先对文法进行消除左递归处理,得到以下产生式(#代表输入结束符):

E → T E' E' → + T E' | ε T → F T' T' → * F T' | ε F → ( E ) | i

1. 求FIRST集(首符号集)

步骤提示:从无空串依赖的基础非终结符开始,逐步推导依赖它的非终结符,重点关注空产生式的处理。

  • F的FIRST集:看F的产生式F→(E) | i。它要么以(开头,要么以i开头,且不能推空。
    FIRST(F) = { (, i }
  • T’的FIRST集:看T’→F T’ | ε。它要么以开头,要么直接变空。
    FIRST(T’) = { *, ε }
  • T的FIRST集:看T→F T’。T的开头取决于F,因为F不能变空,所以T的开头就是F的开头。
    FIRST(T) = FIRST(F) = { (, i }
  • E’的FIRST集:看E’→+T E’ | ε。要么以+开头,要么变空。
    FIRST(E’) = { +, ε }
  • E的FIRST集:看E→T E’。E的开头取决于T,T不能变空,所以E的开头就是T的开头。
    FIRST(E) = FIRST(T) = { (, i }

2. 求FOLLOW集(后跟符号集)

步骤提示:先确定开始符号的FOLLOW集,再根据产生式中非终结符的位置,结合“继承保镖”规则逐步推导。

  • FOLLOW(E):E是开始符号,所以必须有结束符#;另外,在产生式F→(E)中,E的后面紧跟着),所以)也是FOLLOW(E)的元素。
    FOLLOW(E) = { ), # }
  • FOLLOW(E’):在E→T E’中,E’处在末尾,意味着E’的保镖就是E的保镖(E’结束后,E也就结束了)。
    FOLLOW(E’) = FOLLOW(E) = { ), # }
  • FOLLOW(T):在E→T E’中,T后面跟着E’;根据规则,E’的FIRST集(去掉ε)要加入FOLLOW(T),即+;又因为E’可以变成ε,所以E的保镖(), #)也要加入。
    FOLLOW(T) = { +, ), # }
  • FOLLOW(T’):在T→F T’中,T’在末尾,所以它继承T的所有保镖。
    FOLLOW(T’) = FOLLOW(T) = { +, ), # }
  • FOLLOW(F):在T→F T’中,F后面跟着T’;T’的FIRST集(去掉ε)里有*,加入FOLLOW(F);又因为T’可以变成ε,所以T的保镖(+, ), #)也要全部加入。
    FOLLOW(F) = { *, +, ), # }

3. 求SELECT集(选择符号集)

步骤提示:先判断产生式右部是否能推空,再根据规则选择FIRST集或FOLLOW集,明确推导时的选择依据。

  • E→T E’:右部不能推出ε,直接取FIRST(TE’)。
    SELECT(E→T E’) = { (, i }
  • E’→+T E’:右部不能推出ε,直接取FIRST(+TE’)。
    SELECT(E’→+T E’) = { + }
  • E’→ε:右部就是ε,取FOLLOW(E’)。
    SELECT(E’→ε) = { ), # }
    通俗解释:当你在E’处,发现后面的输入是)或者已经结束了#,说明E’这里不需要再匹配+了,直接让它变空隐身即可。
  • T→F T’:右部不能推出ε,直接取FIRST(FT’)。
    SELECT(T→F T’) = { (, i }
  • T’→*F T’:右部不能推出ε,直接取FIRST(FT’)。
    SELECT(T’→
    F T’) = { * }
  • T’→ε:右部就是ε,取FOLLOW(T’)。
    SELECT(T’→ε) = { +, ), # }
  • F→(E):右部不能推出ε,直接取FIRST((E))。
    SELECT(F→(E)) = { ( }
  • F→i:右部不能推出ε,直接取FIRST(i)。
    SELECT(F→i) = { i }

经典例题侧重深度实操,下面补充一道简单例题,步骤更简洁,适合入门巩固,帮你查漏补缺,强化对规则的记忆。

三、基础例题巩固(入门适配)

为了让大家进一步熟悉规则,再补充一道简单文法的演练,步骤更简洁,适合入门巩固。

假设有如下简单文法: S→AB A→aA | ε B→b

1. 求FIRST集

  • FIRST(B):B→b,所以
    FIRST(B) = {b}
  • FIRST(A):A→aA(加入a),A→ε(加入ε)。所以
    FIRST(A) = {a, ε}
  • FIRST(S):S→AB。先看FIRST(A),加入a;因为A能推ε,继续看FIRST(B),加入b。所以
    FIRST(S) = {a, b}

2. 求FOLLOW集

  • FOLLOW(S):S是开始符号,加入#。所以
    FOLLOW(S) = {#}
  • FOLLOW(A):找A在产生式右部的位置,在S→AB中,A后面跟着B。将FIRST(B)中非空元素加入FOLLOW(A),即加入b。所以
    FOLLOW(A) = {b}
  • FOLLOW(B):在S→AB中,B在最后。将FOLLOW(S)加入FOLLOW(B)。所以
    FOLLOW(B) = {#}

3. 求SELECT集

  • SELECT(A→aA):aA不能推ε,等于FIRST(aA),所以
    SELECT(A→aA) = {a}
  • SELECT(A→ε):ε能推ε,等于(FIRST(ε) - {ε}) ∪ FOLLOW(A) = ∅ ∪ {b},所以
    SELECT(A→ε) = {b}
  • SELECT(B→b):等于FIRST(b),所以
    SELECT(B→b) = {b}
  • SELECT(S→AB):等于FIRST(AB),所以
    SELECT(S→AB) = {a, b}

四、总结与应用

4.1 核心知识点总结

通过这两道例题你会发现,求这三个集合的核心,就在于对空串ε的处理,记住三句话即可:

  • FIRST集:遇到能推空的符号,要“穿透”它继续往后看。
  • FOLLOW集:如果后面的符号能推空,要把自己的保镖分给它。
  • SELECT集:能推空的产生式,它的SELECT集由FOLLOW集决定;不能推空的,由FIRST集决定。

4.2 LL(1)文法判定(应用落地)

💡 判定规则:看同一个非终结符的多个产生式的SELECT集是否有交集。如果所有非终结符的任意两个产生式的SELECT集都没有交集,那么这个文法就是LL(1)文法。

这三个集合的核心应用,就是判断一个文法是不是LL(1)文法——LL(1)文法的精髓的是“向前看一个输入符号,就能明确选择哪条产生式推导,不产生二义性”。

比如经典例题中E’的两个产生式,SELECT集分别是{+}和{), #},完全没有交集;简单例题中A的两个产生式,SELECT集分别是{a}和{b},也没有交集,所以这两个文法都是LL(1)文法。

最后提醒:FIRST、FOLLOW、SELECT集的推导,一定要遵循“迭代计算直到集合不再增大”的原则,尤其是FOLLOW集,常常需要反复推导才能得到最终结果。多练两道例题,就能熟练掌握啦!


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/29 5:09:14

2026亲测:专业AI智能降重工具选这款就对了

2026 年降 AIGC 工具已经从“基础语义改写”进化为多维度智能优化系统,核心评测指标涵盖 AI 痕迹清除精准度、学术表达一致性、格式结构完整性、长段落逻辑流畅性、降重适配范围以及高校检测合规性。本次测评覆盖 8 款主流工具,测试内容包括中英文论文处…

作者头像 李华
网站建设 2026/5/21 19:26:45

为什么我强烈推荐大学生打CTF!看完你就懂了!

前言 写这个文章是因为我很多粉丝都是学生,经常有人问: 感觉大一第一个学期忙忙碌碌的过去了,啥都会一点,但是自己很难系统的学习到整个知识体系,很迷茫,想知道要如何高效学习。 这篇文章我主要就围绕两点…

作者头像 李华
网站建设 2026/5/21 19:25:41

UVa 258 Mirror Maze

题目分析 本题描述了一个奇特的迷宫,迷宫由 M 列 N 行组成,边界处除两个入口外均为黑洞(*)。迷宫内部包含两种元素: 镜子:用 / 或 \ 表示,两种状态对应镜子的两种朝向(旋转 909090 度…

作者头像 李华
网站建设 2026/5/21 19:20:27

orcad如何创建原理图符号:3用Excel电子表格创建元件符号

1,在库文件上右击点“New Part From Spreadsheet”打开如下,spreadsheet 如下2,按照各列顺序在 Excel 中整理相同表格,如下其中Section 表示这个符号有几个部分Position 表示管脚在符号外框的位置Type是Power时Pin Visibility才可…

作者头像 李华