LL(1)文法--FIRST集、FOLLOW集、SELECT集


S_文法

S_文法,也被称为简单的确定性文法(Simple Deterministic Grammar),是编译原理中的一种特定类型的文法。这种文法满足以下两个条件:

  1. 每个产生式的右部都以终结符开始。
  2. 同一非终结符的各个候选式的首终结符都不同。

这意味着,在S_文法中,非终结符的每一个候选式都是由一个终结符开始的,并且对于同一个非终结符,它的各个候选式的首终结符都是不同的。这种特性使得S_文法可以进行预测分析。

然而,需要注意的是,S_文法不含有空产生式(ε产生式),这极大地限制了其应用。在某些情况下,可能需要使用ε产生式,但在S_文法中,这是不被允许的。

此外,文法中的非终结符和终结符分别构成了非空有穷集合VN和VT,而产生式则构成了非空有穷集合P。这些集合和产生式一起定义了文法的结构和规则。

总的来说,S_文法是一种具有特定规则和限制的形式文法,它可以进行预测分析,但不支持空产生式。这种文法在编译原理的学习和应用中具有一定的价值和意义。



q_文法

在编译原理中,q_文法(q-grammar)是一种特殊类型的文法,其定义涉及对产生式的右部进行特定的限制。q_文法引入了两个重要的概念:SELECT集和FOLLOW集。

q_文法的定义如下:

  1. 每个产生式的右部或为ε(空字符串),或以终结符开始。
  2. 具有相同左部的产生式有不相交的SELECT集。

SELECT集是用于确定在给定非终结符的多个候选式中应该选择哪一个进行推导的集合。对于产生式A → α,其中A是非终结符,α是符号串,SELECT(A → α)是根据α的内容来计算的。如果α是终结符a,则SELECT(A → α) = {a}。如果α是非终结符B,则SELECT(A → α) = FIRST(B)。如果α是ε,则SELECT(A → α)是空的。

FOLLOW集是另一个重要的概念,它用于确定在某个非终结符的推导结束后可能出现的终结符集合。对于非终结符A,FOLLOW(A)是根据文法的其他产生式和A在产生式中的位置来计算的。

q_文法的这些特性和限制使得它在某些编译技术的应用中很有用,特别是在需要精确控制推导过程的场景中。然而,由于q_文法的限制,它可能不适用于所有类型的语言描述。因此,在选择使用q_文法时,需要根据具体的应用需求和语言的特性进行权衡。



FIRST 集合

串首终结符
串首第一个符号,并且是终结符。简称首终结符

串首终结符集
给定一个文法符号串αα串首终结符集FIRST(α)被定义为可以从α推导出的所有串首终结符构成的集合。如果α=>*ε,那么ε也在FIRST(α)

  • 对于α(VTVN)+,FIRST(α)={a|αaβ,aVT,β(VTVN))};
  • 如果αε,那么εFIRST(α)

计算文法符号X的FIRST(X)

  • FIRST(X):可以从X推导出的所有串首终结符构成的集合
  • 如果 X ═>* ε,那么 ε∈FIRST(X)

算法
不断应用下列规则,直到没有新的终结符ε可以被加入到任何FIRST集合中为止

  • 如果X是一个终结符,那么FIRST(X)={X}
  • 如果X是一个非终结符,且 X→Y1…Yk∈P (k≥1),那么如果对于某个iaFIRST(Yi)中且ε在所有的FIRST(Y1) , … , FIRST(Yi-1)中(即Y1...Yi-1 =>* ε),就把a加入到FIRST(X)中。如果对于所有的 j = 1,2, . . . , kεFIRST(Yj)中,那么将ε加入到FIRST(X)
  • 如果X->ε∈P,那么将ε加入到`FIRST(X)中

计算串X1X2 …XnFIRST集合

  • FIRST(X1X2 …Xn)加入FIRST(X1)中所有的非ε符号
  • 如果εFIRST(X1)中,再加入FIRST(X2)中的所有非ε符号;如果εFIRST(X1)FIRST(X2)中,再加入FIRST(X3)中的所有非ε符号,以此类推
  • 最后,如果对所有的iε都在FIRST(Xi)中,那么将ε加入到FIRST(X1X2 …Xn)


FOLLOW 集合

计算非终结符AFOLLOW(A)

  • FOLLOW(A):可能在某个句型中紧跟在A后边的终结符a的集合
    FOLLOW(A)={a| S =>* αAaβ, a∈VT,α,β∈(VT∪VN)*}
  • 如果A是某个句型的的最右符号,则将结束符“$”添加到FOLLOW(A)

算法
不断应用下列规则,直到没有新的终结符可以被加入到任何FOLLOW集合中为止

  • $放入FOLLOW(S)中,其中S是开始符号,$是输入右端的结束标记
  • 如果存在一个产生式A→αBβ,那么FIRST(β)中除ε之外的所有符号都在FOLLOW(B)
  • 如果存在一个产生式A→αB,或存在产生式A→αBβFIRST(β)包含ε,那么FOLLOW(A)中的所有符号都FOLLOW(B)


SELECT 集合

在编译原理中,产生式的可选集(select set)是一个重要的概念,用于确定在某个非终结符的多个候选式中应该选择哪一个进行推导。可选集通常用于预测分析、递归下降分析以及构造自动机等场景。

产生式的可选集是基于非终结符的后继符号集和产生式的右部符号来计算的。对于产生式 A → α,其中 A 是一个非终结符,α 是一个符号串(可能是终结符、非终结符或ε),产生式的可选集 SELECT(A → α) 定义如下:

  1. 如果 α 是一个终结符 a,则 SELECT(A → α) = {a}。
  2. 如果 α 是非终结符 B,则 SELECT(A → α) = FIRST(B)。如果 FIRST(B) 包含 ε,则还需将 FOLLOW(A) 加入到 SELECT(A → α) 中。
  3. 如果 α 是 ε(空字符串),则 SELECT(A → α) = FOLLOW(A)。

这里,FIRST(B) 表示非终结符 B 可以推导出的所有字符串的首个终结符的集合。如果 B 可以推导出 ε,则 ε 也属于 FIRST(B)。


产生式的可选集
产生式A→β的可选集是指可以选用该产生式进行推导时对应的输入符号的集合,记为SELECT(A→β)

  • SELECT(A→aβ)={a}.
  • SELECT(A→ε)=FOLLOW(A).

产生式A→α的可选集SELECT

  • 如果εFIRST(α),那么SELECT(A→α)=FIRST(α).
  • 如果εFIRST(α),那么SELECT(A→α)=(FIRST(α)-{ε})FOLLOW(A).

表达式文法各产生式的SELECT集

可选集的计算对于确保语法分析的正确性至关重要。例如,在预测分析中,通过分析输入字符串的当前符号和产生式的可选集,我们可以确定应该应用哪个产生式进行推导。

请注意,不同的文法和分析方法可能会有不同的可选集计算规则。上述规则适用于一般的上下文无关文法(CFG)和预测分析方法。在实际应用中,还需根据具体的文法和分析算法进行适当的调整。


LL(1)文法

解释一
LL(1)文法是一种确定的自顶向下的判断文法。这种文法要求对于文法中的任意两个具有相同左部的产生式A→α|β,需要满足以下条件:

  1. 如果α、β均不能推导出ε,则FIRST(α) ∩ FIRST(β) = ∅。
  2. α和β至多有一个能推导出ε。
  3. 如果β═>*ε,则FIRST(α) ∩ FOLLOW(A) = ∅。

只有满足上述条件的文法才能被称为LL(1)文法。此外,LL(1)文法既不是二义性的,也不含左递归,对LL(1)文法的所有句子均可进行确定的自顶向下语法分析。但需要注意的是,并不是所有的语言都可以用LL(1)文法来描述,而且不存在判定某语言是否是LL(1)文法的算法。也就是说,确定的自顶向下分析只能实现一部分上下文无关语言的分析,这就是LL(1)文法所产生的语言。

解释二
LL(1)文法是编译原理中用于描述上下文无关文法(Context-Free Grammar, CFG)的一个子集,这类文法适合于自顶向下、向前看一位的分析方法。LL(1)中的“L”代表从左到右扫描输入串(Left to Right scan),第二个“L”表示构造分析栈和语法树时采用最左推导(Leftmost derivation),而“1”表示在做决定时仅需查看下一个输入符号(Lookahead of 1 symbol)。

LL(1)文法的特点:

  • 文法必须是无二义性的(Unambiguous),即对于任何输入字符串,只能有一棵唯一的语法分析树。
  • 对于每个非终结符A,在任意时刻基于当前栈顶符号A以及下一个输入符号,只有一条可能的推导路径。
  • LL(1)文法允许构建预测分析表(Predictive Parsing Table),该表可以指导解析器无需回溯地分析整个输入串。

为了判断一个文法是否为LL(1)文法,通常需要计算两个集合:FIRST集合和FOLLOW集合,并检查是否存在冲突。FIRST(A)是一个非终结符A能推出的第一个终结符或ε(空字串)的集合;FOLLOW(A)是所有可能出现在非终结符A之后的第一个终结符的集合。

当文法满足以下条件时,它是LL(1)文法:

  • 对于文法中的每一个非终结符A,对所有产生式 A -> αA -> β,如果存在某个终结符a,使得FIRST(α)FIRST(β)都包含a(或者它们分别包含a和ε),则要求FOLLOW(A)不包含a。
  • 不存在任何关于选择产生式的冲突。

通过消除左递归和提取左公共因子等手段,可以将一些非LL(1)文法转换为等价的LL(1)文法。一旦文法被证明是LL(1)的,就可以利用其特性设计出简单且高效的LL(1)解析器。



预测分析表

预测分析表(Prediction Analysis Table)是编译原理中的一个重要概念,特别是在自顶向下的语法分析过程中。预测分析表是一个二维表,通常表示为M[A, a],其中A是非终结符的集合,a是终结符或句子结束标记(通常表示为$)的集合。这个表存储了每个非终结符A面临输入符号a时应该采取的动作。

预测分析表的构建基于两个关键集合:FIRST集合和FOLLOW集合。FIRST集合表示一个非终结符或产生式序列可以推导出的字符串的首个终结符(串首终结符)的集合。FOLLOW集合表示一个非终结符在规范推导的某一步之后可以紧跟的终结符的集合。

预测分析表的构建过程通常包括以下步骤:

  1. 计算FIRST集合和FOLLOW集合:对于文法中的每个非终结符和产生式,计算其FIRST集合和FOLLOW集合。
  2. 填充预测分析表:对于每个非终结符A和终结符a,根据A的FIRST集合和FOLLOW集合来确定M[A, a]的值。通常,M[A, a]的值是一个产生式编号或一个指示动作(如“出错”或“接受”)。
  3. 检查LL(1)条件:确保文法满足LL(1)条件,即对于每个非终结符A,其所有产生式的FIRST集合两两不相交,并且至多有一个产生式可以推导出ε。

预测分析表的主要用途是在自顶向下的语法分析过程中指导分析器的动作。当分析器面临一个输入符号时,它查看预测分析表中相应的条目来确定下一步的动作,如选择哪个产生式进行推导或报告语法错误。

posted @   guanyubo  阅读(1813)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示