🔖 编译原理语法分析计算机

FIRST

FIRST(X)

  • 如果 X 是一个终结符号,那么 FIRST(X)=X

  • 如果 Xε 是一个产生式,那么 εFIRST(X)

  • 如果 X 是一个非终结符号,且 XY1Y2Yk 是一个产生式:

    • FIRST(Y1)FIRST(X)

    • 对于 1tk,如果 1s<t 都有 εFIRST(Ys) 成立,则 FIRST(Yt)FIRST(X)


FIRST(X1X2Xk)

  • FIRST(X1X2Xk) 加入 FIRST(X1) 的所有非 ε 符号

  • 如果 εFIRST(X1),再加入 FIRST(X2) 的所有非 ε 符号;以此类推

  • 如过 εFIRST(Xt)1tk 均成立,则将 ε 加入 FIRST(X1X2Xk)

HINT

FIRST 集合大概就是语法分析树中,当前节点即将扩展的下一个节点的点集。

FOLLOW

S 是开始符号,$ 是输入右端的结束标记

  • $ 放到 FOLLOW(S)

  • 如果存在一个产生式 AαBβ,将 FIRST(β) 中所有的非 ε 符号放入到 FOLLOW(B)

  • 如果存在一个产生式 AαB 或存在一个产生式 AαBβεFIRST(β),将 FOLLOW(A) 中所有符号放到 FOLLOW(B)

HINT

FOLLOW 集合大概就是语法分析树中,以当前节点为根节点的子树扩展完毕后,回溯时所即将扩展的下一个节点的点集。

自顶向下的语法分析

LL(1) 文法

  • 有二义性和左递归的文法都不是 LL(1)

  • 一个文法是 LL(1) 的,当且仅当 G 的任意两个不同的产生式 Xαβ 满足:

    • FIRST(α)FIRST(β) 是不相交的集合。也就是不存在左公因子。

    • 如果 ϵFIRST(α),则 FIRST(X)FIRST(β) 是不相交的集合

    • 如果 ϵFIRST(β),则 FIRST(X)FIRST(α) 是不相交的集合

预测分析表

对于 G 的每个产生式 Aα

  • 对于 FIRST(α) 中的每个终结符号 a,将 Aα 加入到 M[A,a]

  • 如果 ϵFIRST(α) 中:

    • 那么对于 FOLLOW(A) 中的每个终结符号 b,将 Aα 加入到 M[A,b]

    • 如果 $FOLLOW(A) 中,将 Aα 加入到 M[A,$]

自底向上的语法分析

规范 LR(0) 项集族

项集的闭包

  • 如果 I 是文法 G 的一个项集,那么 CLOSURE(I) 可由下面两个规则从 I 构造得到。

    • I 中的各个项加入到 CLOSURE(I)

    • 如果 AαBβCLOSURE(I) 中, Bγ 是一个产生式,并且项 B γ 不在 CLOSURE(I) 中,就将这个项加入其中。 不断应用这个规则,直到没有新项加入到 CLOSURE(I) 中为止

直观地讲,CLOSURE(I) 中的项 AαBβ 表明在语法分析过程的某点上,我们认为接下来可能会在输入中看到一个能够从 Bβ 推导得到的子串。


GOTO 函数

  • GOTO(I,X),其中 I 是一个项集,X 是一个文法符号。

  • GOTO(I,X) 被定义为 I 中所有形如 [AαXβ] 的项所对应的项 [AαXβ] 的集合的闭包

直观地讲,GOTO 函数用于定义一个文法的 LR(0) 自动机中的转换,描述了当输入为 X 时离开状态 I 的转换。


构造项集族

  1. 初始时,C=I0={CLOSURE({[SS]})}

  2. 对于 C 中的每个项集 I

    • 对于每个文法符号 X

      • 如果 GOTO(I,X) 非空且不在 C 中,将 GOTO(I,X) 加入到 C
  3. 重复过程 2


构造 SLR 语法分析表

  1. 构造 G 的规范 LR(0) 项集族 C={I0,I1,,In}.

  2. 根据 Ii 构造得到状态 i。状态 i 的语法分析动作按照下面的方法决定:

    • 如果 [Aαaβ]Ii 中,并且 GOTO(Ii,a)=Ij,令 ACTION[i,a]=sj,即移入 j;其中,a 必须是终结符。

    • 如果 [Aα]Ii 中,那么对于 FOLLOW(A) 中的所有 a,令 ACTION[i,a]=rj,即规约 j;其中,j产生式 Aα 的编号AS.

    • 如果 [SS]Ii 中,令 ACTION[i,$]=acc,即接受

  3. 如果根据上面的规则生成了任何冲突动作,则这个文法不是 SLR(1) 的。状态 i 对于各个非终结符号 AGOTO 转换使用下面的规则构造得到:

    • 如果 GOTO(Ii,A)=Ij, 那么,GOTO[i,A]=j
  4. 规则 (2) 和规则 (3) 没有定义的条目均设为 “报错”

  5. 语法分析器的初始状态是根据 [SS] 所在项集构造得到的状态。


有效 LR(1) 项集族

  • 可行前缀

    • 可以出现在一个移入--规约的语法分析器的栈中的最右句型前缀,称为可行前缀
  • LR(1)

    • 形如 [Aαβ,a] 的项,称为 LR(1);其中 Aαβ 是一个产生式,a 是一个终结符或右端结束标记 $

    • 形如 [Aα,a] 的项只有在下一个输入符号为 a 时才选择 Aα 规约。

  • 可行前缀的有效项

    • LR(1)[Aαβ,a] 对于可行前缀 γ 有效的条件是:

      • 存在一个最右推导 SrmδAωrmδαβω,且

      • γ=δα,且

      • 要么 aω 的第一个符号,要么 ω=εa=$


项集的闭包

如果 [AαBβ,a] 对可行前缀 γ=δα 有效,那么必然存在一个最右推导 SrmδAαxrmδαBβax。假设 βax 推导出终结符号串 by,那么对于某个形如 Bη 的产生式,有推导 SrmγBbyrmγηby. 因此,[Bη,b]γ 的有效项。其中, bFIRST(βa).

  • 如果 I 是文法 G 的一个项集,那么 CLOSURE(I) 可由下列规则从 I 中构造得到。

    • 对于 I 中的每个项 [AαBβ,a]

      • 对于 G 中的每个产生式 Bγ

        • 对于 FIRST(βa) 中的每个终结符号 b

          • [Bγ,b] 加入到集合 I
Hint
  • 本质上,SLR 是利用 LR(0) 自动机能够识别可行前缀这一事实构造的语法分析方案;LR(1) 在此基础上考虑了对可行前缀的有效性

  • LR(1)LR(0) 构造闭包的算法的区别在于:

    • 不再对于任意的 [AαBβ] 添加到闭包中了,这样做的目的是为了减少移入--规约冲突。 也就是,如果 I 中有产生式 AαBβ,对于产生式 Bη

      • SLR: 直接将 Bη 加进 I 的闭包中

      • LR(1): 由于有一个向前看符号,不妨记 AαBβ 的向前看符号为 a,那么仅当满足 aFIRST(βa) 时才能将 Bη 加进 I 的闭包


GOTO 函数

计算 GOTO(I,X)

  • J 初始化为空集

  • 对于 I 中的每个项 [AαXβ,a]

    • 将项 [AαXβ,a] 加入到集合 J
  • 返回 CLOSURE(J)


构造项集族

  • 初始时, C=I0={CLOSURE({[SS,$]})}

    • 对于 C 中的每个项集 I

      • 对于每个文法符号 X

        • 如果 GOTO(I,X) 非空且不在 C

          • GOTO(I,X) 加入 C

构造规范 LR(1) 语法分析表

  1. 构造 G 的规范 LR(0) 项集族 C={I0,I1,,In}.

  2. 根据 Ii 构造得到状态 i。状态 i 的语法分析动作按照下面的方法决定:

    • 如果 [Aαaβ,b]Ii 中,并且 GOTO(Ii,a)=Ij, 令 ACTION[i,a]=sj,即移入 j;其中,a 必须是终结符。

    • 如果 [Aα,a]Ii 中,且 AS; 那么令 ACTION[i,a]=rj,即规约j;其中,j产生式 Aα 的编号

    • 如果 [SS,$]Ii 中,令 ACTION[i,$]=acc,即接受

  3. 如果根据上面的规则生成了任何冲突动作,则这个文法不是 LR(1) 的。状态 i 对于各个非终结符号 AGOTO 转换使用下面的规则构造得到:

    • 如果 GOTO(Ii,A)=Ij, 那么,GOTO[i,A]=j
  4. 规则(2) 和规则(3) 没有定义的条目均设为“报错”。

  5. 语法分析器的初始状态是根据 [SS,$] 所在项集构造得到的状态。

© 2017-2025 光和尘有花满渚、有酒盈瓯

Comments