【编译原理复习笔记】语法分析(二)

自底向上的语法分析

从分析树的底部(叶节点)向顶部(根结点)方向构造分析树
自顶向下的语法分析采用最左推导,与之对应自底向上采用最左规约(反响构造最右推导)

移入规约分析

(1)从输入中移动终结符到栈中
(2)若此时栈中终结符无法与产生式列表中的右部任何一项对应,则继续移入终结符
(3)若此时栈中某一部分可以进行规约,则转换成对应可规约产生式的左部,然后再次进行(1)
(4)当输入中最后不含有终结符,且栈中最后只剩下开始符号的时候,证明规约结束
栈内符号串+剩余输入=“规范句型”
每规约一次,规范句型才会变化一次(而不是移入栈内就会规约

存在的问题

在规约的过程中,可能栈中的符号串满足多个产生式的右部,此时会出现类似二义性的问题

LR 分析法

LR 文法是最大的,可以构造出相应移入-规约语法分析器的文法
L:对输入进行左到右的扫描
R:反向构造最右推导序列
LR(k)中的 k 代表需要向前查看 k 个输入符号
基本原理就是正确识别句柄:
e.g.
S → b B B S\to bBB SbBB
对于该例子,我们可以认为其分为下面几种状态:
S → ⋅ b B B S\to ·bBB SbBB移进状态
S → b ⋅ B B S\to b·BB SbBB待约状态
S → b B ⋅ B S\to bB·B SbBB待约状态
S → b B B ⋅ S\to bBB· SbBB规约状态

LR 分析表

对于产生式
S → B B S \to BB SBB
B → a B B \to aB BaB
B → b B \to b Bb
在这里插入图片描述

s 代表移入栈,后面的符号代表了移入栈的状态,rn代表用第 n 个产生式进行规约
(这里不需要深究分析表如何构成的,后面会解释)
假如输入为:bab$
(1)此时状态栈顶为 0,指针指向 b,对应状态表将其放入栈中,栈中现在为 b ,然后跳转到 4 号状态( 2 )此时状态栈顶为 4 ,指针指向 a ,对应状态表使用第三个产生式对栈顶符号( b )进行规约,状态栈中 4 和符号栈中 b 被拿掉,栈中现在为 b,然后跳转到 4 号状态 (2)此时状态栈顶为 4,指针指向 a,对应状态表使用第三个产生式对栈顶符号(b)进行规约,状态栈中 4 和符号栈中 b 被拿掉,栈中现在为 b,然后跳转到4号状态(2)此时状态栈顶为4,指针指向a,对应状态表使用第三个产生式对栈顶符号(b)进行规约,状态栈中4和符号栈中b被拿掉,栈中现在为B
(3)此时状态栈顶为 0,遇到刚规约的 B,此时查看 GOTO 表可知进入 2 号状态

按照这个顺序不断进行,直到符号栈最后只剩下 S 为止,此时结束

LR(0)分析

在产生式右部中某位置标有圆点的产生式称为相应文法的一个 LR(0)项目,每个项目表示了一个句柄的识别状态

增广文法

在原本产生式的基础上定义一个新的开始符号,以及新的开始符号指向原开始符号的产生式,可以避免原本产生式中出现多个开始符号,保证分析器只有一个接受状态

等价状态

如果每个产生式的每个状态都认为是状态表中的一种状态,此时的状态个数会十分庞大,所以我们引入等价状态来削减状态数量,多个状态构成的等价状态才是状态机中的一个状态
e.g.
S ’ → S S’ \to S SS
S → B B S \to BB SBB
B → a B B \to aB BaB
B → b B \to b Bb
这是上述例子的增广文法,此时对这四条产生式分析等价状态
在这里插入图片描述

我们就可以得到一共 7 种等价状态,而如果每个产生式都单独考虑的话就需要 10 个状态

项目集闭包

在 LR0 分析这一节中,我们定义了什么是项目,项目集就是项目的集合,而项目集的闭包则包括了所有可以从初始项目通过 0 次或多次产生式推导而到达的项目

CLOSURE 函数

CLOSURE 函数用于计算一个给定项目集的闭包,给定一个项目集 I和一个文法 G,CLOSURE(I)会返回一个新的项目集,包含 I 中的所有项目以及 I 可以推导出的所有项目
在这里插入图片描述

GOTO 函数

返回项目集 I 对应于文法符号 X 的后继项目集闭包,其实就是起到了跳转的作用。如在例子中,如此时处于项目集 I0,那么 GOTO(I0,a)表示的就是项目集 I3
在这里插入图片描述

构造 ACTION 表

(1)对于某个项目集 Ii,遍历其所有项目
如果某个项目为有移进项目的形式: A → α ⋅ β A \to \alpha·\beta Aαβ
且 beta 的第一个符号为终结符 a,则 action 表第 i 行第 a 列填入 sk,k 为将 a 放入栈中后跳转的状态
(2)如果某个项目为有移进项目的形式: A → α ⋅ A \to \alpha· Aα,则 action 表第 i 行所有列填入 rj,j 为对应产生式的序号
(3)如果某个位置没有任何移进或规约,则该行打上 err
(4)如果某个状态完成了所有规约只剩开始符号,该行打上 acc

构造 GOTO 表

(1)识别产生式中所有的非终结符
(2)计算当前状态集的闭包,确定通过当前栈顶的非终结符可以到达的下一个状态,重复的项目需要去重
(3)在 GOTO 表的对应位置,填入可以到达的下一个状态

LR(0)文法的形式化定义

M = ( C , V N ∪ V T , G O T O , I 0 , F ) M=(C,V_N\cup V_T,GOTO,I_0,F) M=(C,VNVT,GOTO,I0,F)
KaTeX parse error: Expected 'EOF', got '}' at position 73: …T,I=GOTO(J,X)\\}̲
I 0 = C L O S U R E ( S ’ → ⋅ S ) I_0=CLOSURE(\\{S’ \to ·S\\}) I0=CLOSURE(SS)
F = C L O S U R E ( S ’ → S ⋅ ) F = \\{ CLOSURE(\\{S’ \to S·\\})\\} F=CLOSURE(SS)

移进规约冲突

在同一个状态中,可能出现一个项目需要移进,另一个项目需要规约的情况,问题源于 LR(0)算法往前看了 0 个符号

SLR

FOLLOW 集可以帮助我们判定何时规约:当规约后的非终结符的 FOLLOW 集不包含状态集中将要移进的非终结符时,此时不应该规约

SLR 分析法的基本思想

在这里插入图片描述

SLR 与 LR0

在 SLR 分析表中,原本 LR0一整行都为规约动作中,某一可能因为冲突而转为移进,其余地方没有差别

SLR 分析表中的冲突

有时候 FOLLOW 集不能够完全解决冲突的问题,我们还需要更多的限制来完成冲突的区分

LR(1)分析

SLR 只是简单的考察了规约与 FOLLOW 集的关系,下一个输入符号 a ∈ F O L L O W ( A ) a \in FOLLOW(A) aFOLLOW(A)只是规约 a 的一个必要条件,而非充分条件
对于产生式 A → a A \to a Aa的归约,在不同位置,A 会要求不同的后继符号
在特定位置,A 的后继符号集是 FOLLOW(A)的子集
在这里插入图片描述

LR(1)项目的规范

将一般产生式 [ A → α ⋅ β , a ] [A \to \alpha·\beta,a] [Aαβ,a]的项称为 LR(1)项,a 是一个终结符,它表示在当前状态下,A 后面必须紧跟终结符,称为展望符
当 beta 不等于 epsilon 时,a 不起作用;当 beta 等于 epsilon 时,只有在下一个输入符号为 a 时才可以按照产生式进行规约

等价 LR(1)项目

∣ A → α ⋅ b β , a ∣ |A \to \alpha·b\beta,a| Aαbβ,a
B → γ ∈ P B \to \gamma \in P BγP
则等价于 ∣ B → γ , b ∣ |B \to \gamma,b| Bγ,b
b ∈ F I R S T ( β a ) b \in FIRST(\beta a) bFIRST(βa)
当 beta 为空字符的时候,b=a,称为继承的后继符,否则叫自身的后继符。

LR(1)自动机

在这里插入图片描述
如果除了展望符以外,两个 LR1 项目集是相同的,则称这两个 LR1 项目集是同心的,如 I4 和 I11

LALR 分析法

同心项目集合并为同一个项目集,根据合并后的项目集族构造语法分析表,若语法分析表没有错误则为 LALR 分析法

规约规约冲突

在同心项目集中,两个相同的都需要规约的产生式对应的展望符号不相同,此时会出现矛盾无法确定合并后按照哪个展望符进行规约

LALR 分析法的特点

形式上与 LR(1)相同
大小上与 LR(0)/SLR 相当
分析能力:LR0<SLR<LALR<LR1

  • 32
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值