编译原理-自底向上的语法分析

在这里插入图片描述

5.1 引言

  1. 工作方式:移进-归约
    在这里插入图片描述
    在这里插入图片描述

2.2.3 短语、直接短语、句柄(第二章)

  • 直接短语一定是一个产生式的右部,但是产生式的右部不一定是当前句型的直接短语
  • 高人,民生,活水则都不是当前句型的直接短语,但是是其他句型的产生式右部
    在这里插入图片描述

在这里插入图片描述

设G[Z]是一个文法,假定αβδ是文法G的一个句型。
1)短语:若存在Z ⇒+ αAδ且A ⇒+ β,则称β是句型αβδ相对于非终结符A的短语。(即子树的边缘
2)直接短语:若存在Z ⇒+ αAδ且A⇒β,则称β是句型αβδ相对于产生式规则A→β的直接短语。(高度为2的子树的边缘
3)句柄:一个句型的最左直接短语称为该句型的句柄。

在这里插入图片描述

  1. 基本思想:将输入符号串中的符号从左向右逐个的移进栈,每当栈顶形成某一个可归约子串时,就把该可归约子串归约成某一个非终结符号。即先把该可归约子串从栈顶逐出,再把归约的非终结符号压进栈。

在这里插入图片描述
在这里插入图片描述

5.2 自底向上的语法分析面临的问题

  1. 如何寻找可归约子串?
  2. 可归约子串被归约到哪一个非终结符号?

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

LR分析法概述

在这里插入图片描述

LR分析法基本原理

在这里插入图片描述

LR分析器(自动机)的总体结构

在这里插入图片描述

LR分析表的结构

在这里插入图片描述

LR分析器的工作过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

LR分析算法

在这里插入图片描述
在这里插入图片描述

LR(0)分析

LR(0)项目

在这里插入图片描述
K个符号对应K+1个项目

增广文法

(文法开始符号仅出现在一个产生式左部,一个接受状态)
在这里插入图片描述

文法中的项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
. 后是非终结符则存在等价项目
在这里插入图片描述


LR(0)分析表构造算法(略)

在这里插入图片描述

LR(0)分析过程中的冲突(移进规约冲突)

在这里插入图片描述
在这里插入图片描述
不知道使用移入动作还是规约动作

移进规约冲突和规约规约冲突

在这里插入图片描述


SLR分析

在这里插入图片描述
新增的LOLLOW集,说明就算规约了,E的FOLLW集也没有,故不能规约*
借助FOLLOW集判定什么时候不能进行规约

在这里插入图片描述

例子

在这里插入图片描述
根据状态2冲突的B和T,对比他们的FOLLOW集,写出对应的ACTION

SLR分析中的冲突

移入规约冲突
所以需要引入功能更加强大的分析法
在这里插入图片描述


LR(1)分析

LR(1)分析法的提出

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

等价LR(1)项目

在这里插入图片描述

例子

在这里插入图片描述
对比多了四个状态

在这里插入图片描述

项目集同心的概念

在这里插入图片描述
8 10
4 11
5 12
7 13都是同心的项目集

例子

在这里插入图片描述


LALR分析法

基本思想

合并同心项目集

在这里插入图片描述

例子

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

合并同心项目集产生规约规约冲突

(因为展望符只在规约的时候冲突,移入不起作用,所以不会产生移入规约冲突)
在这里插入图片描述

推迟错误的发现

在这里插入图片描述

LALR(1)的特点

在这里插入图片描述


二义性文法的LR分析

在这里插入图片描述
在这里插入图片描述

例子1

在这里插入图片描述
在这里插入图片描述

例子2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二义性文法的使用

在这里插入图片描述

LR分析中的错误处理

在这里插入图片描述

恐慌层次错误恢复

在这里插入图片描述

短语层次错误恢复

在这里插入图片描述

例子(不会推迟错误的发现)

在这里插入图片描述
核心是假设获得了相应的输入或者删除相应的输入,并且转移到相应状态,并且输出相应信息
在这里插入图片描述

参考

编译原理总结,看这一篇就够了!

LR分析技术

LR分析技术概述

  1. LR(k)分析技术
    1)L代表从左向右分析,R代表最右推导,k代表向前查看k个字符。
    2)LR分析法实际上是最右推导的逆过程——最右归约。
    3)LR(k)分析技术利用已经移进栈中的和归约后进入栈中的一切文法符号,并向前查看最多k个符号,从而确定句柄是否已经在栈顶形成,一旦句柄出现在栈顶,立即进行归约。
  2. LR(k)技术的分类:LR(0)分析法、SLR(1)分析法、LR(1)分析法、LALR(1)分析法。
  3. LR分析器组成:一个输入串、一个分析栈、一张LR分析表、LR分析器总控程序。
    在这里插入图片描述

LR(0)分析法

  1. 活前缀:将每一条规则编上序号①、②、③…,附加在规则的右边,并在推导的过程中将序号带入句型中。句型中形如βω℗的前部称为活前缀。
  2. LR(0)项目:文法G中每一条产生式规则的右部添加一个圆点,称为LR(0)项目。

eg:A→cAd可以产生四个LR(0)项目:A→·cAd,A→c·Ad,A→cA·d,A→cAd·。
1)若是空规则A→ε,则只对应一个LR(0)项目A→·。
2)含义 :
i)A→·cAd表示期望下一个符号是终结符c。
ii)A→c·Ad表示目前输入串中已经有部分符号已正确分析成功,期望剩下的输入串能与圆点右部的部分分析成功。
iii)A→cAd·表示输入串已全部正确解析成功,可以归约到非终结符A。

  1. 初始项目:S→·α,S是文法的开始符号,称该项目为初始项目。
  2. 移进项目:A→α·aβ,其中a∈VT,称该项目为移进项目。
  3. 待约项目:A→α·Bβ,其中B∈VN,称该项目为待约项目。
  4. 归约项目和接收项目:A→α·,其中A∈VN,若A不是文法G的开始符号,则称为归约项目,否则称为接收项目。
  5. 后继项目:设有两个项目A→α·aβ和A→αa·β,两者同属于一条规则,只是圆点位置相差一个终结符,则称A→αa·β是A→α·aβ的后继项目。
  6. 文法G的拓广
    1)原因:为了保证文法G只有一个接收项目,一旦达到接收项目就完成整个语法分析。当一个文法G的开始符号不是只出现在一条规则的左边,则这个文法G需要拓广。
    2)定义:设文法G的开始符号是S,现引入一个新的开始符号S‘,并加入一条新规则:S’→S。产生新文法G’[S’],称G’是文法G的拓广。
  7. LR(0)项目集:由LR(0)项目构成的集合。
  8. LR(0)项目集闭包
    已知项目集I,求I的闭包CLOSURE(I)的算法:
    1)项目集I中所有的项目加入到CLOSURE(I)集合中。
    2)若待约项目A→α·Bβ属于CLOSURE(I),则对于每一个关于B的产生式规则B→γ,将项目B→·γ加入到CLOSURE(I)中。
    3)反复执行2),直到CLOSURE(I)中不再有新的项目加入为止。
  9. LR(0)的GO函数:项目集I经过符号X的状态转换函数GO(I,X)=CLOSURE(I的后继项目集)。
  10. LR(0)项目集规范族:把识别文法G的所有活前缀的LR(0)项目集闭包组成的DFA称为项目集的规范族。
    eg:设有文法G[S]:
    S→cAd①
    A→a②
    A→Aa③
    求该文法G的LR(0)项目集规范族。

在这里插入图片描述

  1. LR(0)分析表组成:ACTION子表和GOTO子表。
------ACTIONACTIONACTIONGOTOGOTO
状态a1#SA
0s212
1acc
nr3r3r3

其中,ai是终结符号,S和A是非终结符。
1)LR(0)分析表的第一列是状态列,登记DFA中的状态编号。
2)ACTION子表中的列全是终结符(包含#),填写动作,动作分为四种:
i)移进动作:用s表示。如状态0所在行与ACTION子表中的a1列交叉处填写的是s2,表示a1进栈,当前状态从状态0变成状态2。
ii)归约动作:用r表示。如状态n所在行与ACTION子表中的a1列交叉处填写的是r3,表示用第三条规则进行归约。
iii)接受动作:用acc表示。如状态1所在行与ACTION子表中的#列交叉处填写的是acc,表示成功接收,已正确识别出句子。
iv)报错:ACTION子表中的空白处,表示出错。
3)GOTO子表的列全是非终结符,表示状态转移。如状态0所在行与GOTO子表中第A列交叉处填写的是2,表示当前状态0下若识别出非终结符A,状态将变迁到状态2。

  1. LR(0)分析表的构造步骤:
    1)若移进项目A→α·aβ属于Ik且GO(Ik,a)=Ij,其中a是终结符,则令ACTION[k][a]=sj。表示将a移进栈,且状态变迁到j。
    2)若归约项目A→β·,并设A→β的规则编号为p,则将ACTION子表中状态k所在的行与每一个终结符(包括#)所在列的交叉处填写上rp。表示无论下一个字符是什么,只要当前状态是k,就立即使用第p条规则A→β进行归约。
    3)若接收项目S‘→S·属于Ik,则令ACTION[k][#]=acc。就是将ACTION子表中状态k所在的行与符号#所在列的交叉处填写acc,表示成功接收。
    4)若GO(Ik,A)=Ip,其中A是非终结符,则令GOTO[k][A]=p,表示状态k下若识别出非终结符A,状态将变为p。
    5)分析表中不能用以上规则填写的交叉处,全部填写报错标记。
  2. LR(0)文法:若一个文法G的LR(0)项目集规范族中所有的LR(0)项目集均不含有冲突项目,则该文法是LR(0)文法。
  3. LR(0)项目集中的冲突
    1)移进-归约冲突
    面临一个终结符,同时出现了移进和归约两种动作。
    2)归约-归约冲突
    一个项目集中出现两个归约动作
  4. LR分析器总控程序的工作步骤
    1)将(状态0,#)入栈.
    2)将下一个输入符号读入变量a中。
    3)由栈顶当前状态和变量a,查找ACTION子表:
    i)对sj型动作,二元组(状态j,a)入栈,且下一个输入符号读入变量a中;
    ii)对rj型动作,用第j条规则进行归约;
    若是rj型动作,用第j条规则进行归约时,设j条规则是A→β,且规则右部β的长度为n,则首先从栈中弹出n个符号,设此时栈顶的状态为s‘,然后由当前栈顶状态s‘及第j条规则A→β的左部符号A查GOTO子表,即GOTO[状态s’][A],得到新状态w,最后将二元组(状态w,A)入栈。
    iii)acc则成功,结束;
    iv)报错,调用出错处理子程序。
    4)跳到3)。

SLR(1)分析技术

  1. 含义:简化了的LR(1)分析技术
  2. SLR(1)的移进-归约方式:
    1)若下一个符号x是b,则使用A→α·bβ项目将b移进。
    2)若下一个符号x∈FOLLOW(B),则使用B→γ·项目进行归约。
    3)若下一个符号x∈FOLLOW©,则使用C→ξ·项目进行归约。
  3. 与LR(0)的区别:ACTION子表中r型动作填写规则不同。
    对于项目集Ik={B→γ·℗}:
    1)LR(0)分析表:状态k所在的行全部填写上rp。
    2)SLR(1)分析表:只有当终结符号x∈FOLLOW(B)时,才在状态所在的行与符号x所在的列的交叉处填写上rp,其余部分和LR(0)相同。
  4. SLR(1)型文法:若文法G的SLR(1)分析表中没有多重定义项,则该文法是SLR(1)文法

LR(1)分析技术

  1. SLR(1)的缺点:对每一个项目,仅依靠FOLLOW集,没有精确指明面临哪些符号时才能归约。
  2. LR(1)项目
    1)定义:形如[A→α·β,x]称为LR(1)项目。A→α·β是LR(0)项目,x是终结符。终结符x称为该LR(1)项目的搜索符。
    2)含义:表示当A→α·β到达归约项目A→αβ·时,只有面临的下一个符号是x时才能进行归约。
    3)若一个项目集中有LR(1)项目:[A→α·β,a],[A→α·β,b],[A→α·β,c],则可合并写成[A→α·β,a/b/c]。
    4)LR(1)的开始项目:[S’→·S,#]
  3. LR(1)项目对活前缀有效:若存在推导S ⇒* δAη ⇒ δαβη,其中ω=δα,x是η的第一个符号,或者η为ε时,x为#,则称LR(1)项目[A→α·β,x]对活前缀ω有效。
  4. LR(1)项目闭包集
    设有LR(1)项目集I,计算CLOSURE(I)的步骤:
    1)将I中的任何项目全加入到CLOSURE(I)中。
    2)若项目[A→α·Bβ,x]∈CLOSURE(I),则对任何规则B→ξ,将项目[B→·ξ,First(βx)]加入到CLOSURE(I)中。
    3)反复做2),直到CLOSURE(I)中不再加入新的项目为止。
  5. LR(1)的GO函数:状态集I与符号X的状态变迁函数GO(I,X)=CLOSURE(J)。其中J是I经过X的后继项目集,即J={[A→αX·β,a]|[A→α·Xβ,a]∈I}。
  6. LR(1)分析表的构造步骤:
    1)若移进项目[A→α·aβ,x]∈Ik且GO(Ik,a)=Ij,其中a是终结符,则令ACTION[k][a]=sj。表示将a移进栈,当前状态变迁到状态j。
    2)若归约项目[A→β·,a]∈Ik,并设A→β的规则编号为p,则将ACTION[k][a]rp。
    3)若接收项目[S‘→S·,#]∈Ik,则令ACTION[k][#]=accj。表示成功接收。
    4)若GO(Ik,A)=Ip,其中A是非终结符,则令GOTO[k][A]=p。表示状态k下若识别出非终结符A,则将状态变为p。
    5)分析表中不能用以上规则进行填写的交叉处,全部填写报错标记。
  7. LR(1)文法:若LR(1)分析表中没有多重定义项,则该文法是LR(1)的文法

LALR(1)分析技术

  1. 概述
    1)LALR(1)分析表的结构和大小与SLR(1)相同,比LR(1)的分析表小。
    2)LALR(1)的分析能力比SLR(1)强,比LR(1)稍弱。
  2. 基本思想
    LR(1)项目集规范族中的所有同心项状态集合并。合并时,对应项目的搜索符也合并。原先各自接收有向边,都改为由合并后的项目集接收。原先各自发出的有向边都改为由合并后的项目集发出。
    1)合并后的项目集可能出现归-约归冲突。
  3. LALR(1)分析表的构造步骤:
    1)构造文法G的LR(1)项目集规范族。设项目集族为{I0,I1,…,In}。
    2)合并所有同心项集。设新的项目集族为{ I0’,I1’,…,Ij’ }。
    3)若移进项目[A→α·aβ,x]∈Ik’且GO(Ik’,a)=Ij’,其中a是终结符,则令ACTION[k][a]=sj。表示将a移进栈,且状态变迁到状态j。
    4)若归约项目[A→β·,a]∈Ik’,并设A→β的规则编号是p,则令ACTION[k][a]=rp。
    5)若接收项目[S‘→S·,#]∈Ik’,则令ACTION[k][#]=acc,表示成功接收。
    6)构造合并后的GOTO表。
    设Ik’是由It1,It2,…,Itp合并得到的,由于It1,It2,…,Itp是同心项目集,所以GO(It1,X),GO(It2,X) ,…,GO(Itn,X)也是同心项目集且它们合并后的项目集为Im’。
    若GO(Ik’,X)=Im’,其中X是非终结符,则令GOTO[k][X]=m,表示状态k下若识别处非终结符X,状态将变为m。
    7)分析表中不能用以上规则填写的交叉处,全部填写上报错标记。
  4. LALR(1)文法:若LALR(1)分析表中没有多重定义项,则该文法是LALR(1)文法
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
底向上语法分析是一种自底向上推导句子结构的方法。其中,LR分析是最常用的自底向上语法分析方法之一。它通过构建句子的右侧推导,逐步地将输入符号转化为文法中的非终结符号,直到句子被推导为文法的开始符号。 实现LR分析的程序代码通常包括以下几个步骤: 1. 读入文法规则和输入符号序列,并对输入符号序列进行分析。 2. 构建文法规则的LR分析表,该表用于指导分析过程中的状态转移和规约动作。 3. 利用分析表和状态栈来进行状态转移和推导过程。在每一步中,根据当前状态和输入符号,确定进行的动作(移入或规约)并进行相应的处理。 4. 最终得到句子结构的推导结果,即推导过程中每一步的状态和使用的规则。 通过以上步骤,我们可以编写实现LR分析的程序代码。这个程序代码可以是用任何编程语言编写的,常见的如C/C++、Java、Python等。在程序代码中,我们需要考虑如何表示文法规则、LR分析表和状态栈,并实现状态转移和规约的过程。同时,还需要考虑如何处理错误情况,比如输入符号不满足文法规则等。 总的来说,实现LR分析的程序代码是一个复杂的任务,需要对语法分析理论有深入的理解,并且需要灵活运用编程技巧。只有经过仔细设计和测试,才能够编写出高效、正确的LR分析程序代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

VengaZ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值