【编译原理】一篇搞定LR分析法(LR(1)、LR(0)、SLR、LALR)

🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏: 🏀编译原理_十二月的猫的博客-CSDN博客

💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 

目录

1. 自底向上的语法分析技术(LR分析法)

1.1 LR分析法概述

1.2 LR分析法

1.3 总控程序

1.4 不同的LR分析表 

1.4.1 构造LR(0)分析表

LR(0)项目

后继项目 

前看符号 

等价闭包

构造LR(0)自动机 

构建分析表

冲突

1.4.2 构造SLR分析表

1.4.3 构造LR(1)分析表

展望符的生成

一个例子

1.4.4 构造LALR分析表

2. 总结 


1. 自底向上的语法分析技术(LR分析法)

1.1 LR分析法概述

  • 上下文无关文法的LR分析法
  • LR:自左至右扫描,最右推导的逆过程(也就是最左归约)

1.2 LR分析法

  • 任务:在归约的过程中,一方面记住移入和归约的整个符号串,另一方面通过产生式推测未来可能碰到的输入符号

  • 优缺点:

    • 优点:文法范围广,识别能力强,可以识别出错位置
    • 缺点:工作量大,需要构造这种分析程序的产生器
  • 产生器作用:

    • 应用产生器产生一大类上下文无关文法的LR分析程序
    • 对二义性文法或难分析的特殊方法,施加一些限制使之能用LR分析法
  • LR分析器(LR分析法的核心):

                包括两部分:总控程序,分析表
                总控程序:控制程序的运行,查分析表的内存做简单动作
                产生器的任务就是产生分析表

  • 分析表(LR分析器的核心):

    • 一个文法的LR分析器对应四种不同分析表,所以分析表都恰好识别产生的所有语句
    • LR(0),SLR,LR(1),LALR四种分析表

简单来说:

  • LR分析法 依赖于 LR分析器。
  • LR分析器 依赖于 LR分析表。
  • LR分析表的不同就能够制造出不同的LR分析器,也就有不同的LR分析法下面的分支(例如:LR(0)、LR(1)、SLR、LALR分析法)。

因此,学习方向变为:

  • 总控程序
  • 不同的LR分析表 

1.3 总控程序

总控程序就是:在已经有LR分析表的时候,程序如何判断一个句子是否符合语法要求

一句话:怎么用LR分析表进行语法分析

LR文法分析的过程要一句LR分析表进行。还需要维护一个状态栈和符号栈。

  • 对于action表中的某一列a的sn,表示将符号a、状态n入栈
  • 对于action表中的rn表示使用第n个产生式进行规约。

分析过程(可能比较抽象,但是思路不难)

注意,每次都是用状态栈的栈顶状态与剩余输入的第一个在action表中进行转移。

废话不多说,直接看下面例子就明白了~~~

例1:

 解答:

1、初始状态:状态为0,符号栈为#

2、输入i,按照分析表进行状态转化s5,以及符号入栈i

(最下面一条产生式没截全)

3、输入*,按照分析表进行状态转化r6,是第六条产生式规约,因此*不做输入。将i弹出,同时将状态5弹出,并放入符号F。

4、F入栈,0状态遇到F非终结符,入栈状态3

1.4 不同的LR分析表 

通过上面的算法,想必大家已经熟悉LR分析器中的——总控程序,也就是大家已经可以自如地使用LR分析表完成LR分析了🥰🥰~~

下面,我们就来进入LR分析器中的——LR分析表


1.4.1 构造LR(0)分析表

LR(0)项目

右部某位置标有圆点的产生式称为相应文法的一个LR(0)项目。例如

同属于一个产生式的项目,如果圆点的位置只相差1,那么后者是前者的后继项目。例如A→a⋅Xβ的后继项目是A→aX⋅β

后继项目 

原项目M+输入符号a = 原项目M的a符号后继项目M‘

例如原项目如下:

输入符号为b,则后继项目为:

前看符号 

前看符号就是项目中圆点后面所有符号的集合

例如原项目如下:

前看符号为:

S、B、a、b

等价闭包

当一个项目的圆点后面是非终结符的时候,那么他就存在等价项目,例如S→v⋅I;与I→⋅I,i就是一个等价项目。因为第一个项目的圆点后面是I,所以I作为左部的产生式中,所有以圆点开头的都是他的等价项目。所有等价项目构成一个等价闭包

构造LR(0)自动机 

如图所示,从初始状态开始,对于每个项目,都求一下后继项目,然后连一条边到那个项目的等价闭包。最后可以构建出如上图的自动机。

构造LR(0)自动机 过程(必记!!😘😘):

  1. 求出原项目的前看符号集
  2. 一一选出所有前看符号集中的符号,作为输入符号a
  3. 将输入符号a放入原项目,得到它的后继项目,并将两个项目集相连
  4. 求出后继项目的等价闭包
构建分析表

由上面的自动机可以构建出分析表。方法就是行上列出所有状态号,列上,终结符放入action中,非终结符放入GOTO中。可以构建出如下的分析表:

冲突

LR(0)文法是存在冲突的:

  • 移入--归约冲突:某一产生式的右部是另一产生式的前缀
  • 归约--归约冲突:不同产生式有相同的右部 或者 产生式的右部是另一产生式的后缀

温馨提示(必看!!):

  • 冲突出现的根本原因就是归约和移入本身的判断并不准确,根据一个前看符号就选定产生式作归约着太不准确了!!!所以会出现冲突。
  • 因此后面的分析表改进出发点都是想办法让规约选定产生式更加准确,也就是给他提供更多的信息

1.4.2 构造SLR分析表

SLR分析表就是对LR(0)分析表的一个改进

面对上面LR(0)中的冲突,我们可以进行改进得到SLR文法。方法就是在构建分析表时,根据产生式左部的follow集进行归约。

反省一下之前LR(0)文法时,如果一个状态可以归约了,那么不管他剩余输入的第一个字符是什么,都进行规约。

在SLR文法中,根据剩余输入的第一个,采取不同的规约动作。

如上图,I2I中,存在规约/规约冲突,观察B的follow集,只有d,所以在ACTION中,当待输入符号的第一个是d的时候,用第四个产生式进行归约,同理,当剩余输入的第一个是b和$的时候,采用第二个产生式进行输入。

限制:要求一个项目闭包中,归约项目的左部的follow集与移进项目的剩余输入的首字符不相同。

1.4.3 构造LR(1)分析表

        在SLR分析的最后,介绍了SLR依然可能存在语法冲突。为什么呢?
        原因:SLR只是简单地考察下一个输入符号b是否属于与归约项目A→α相关联的FOLLOW(A),但b∈FOLLOW(A)只是归约α的一个必要条件,而非充分条件
        我的理解:如果输入下一个字符是b,我们采用了归约操作,那么就一定可以说明b属于A的FOLLOW集。但是我们不能说:如果b属于A的FOLLOW集,那么就一定可以对A采用归约操作。但是在SLR中,我们就是根据follow+一个前看符号来确定产生式的规约,这并不准确。不好理解的小伙伴可以参考下面的具体实例:

        从上图右边生成树可以我们得知,此时 L=R 中的R后面跟着的终结符只能是$,不可能是=,但是R的FOLLOW中却包含了=。又比如说下一行中的 * R,R下一个终结符只可以是=,不会是 $ 。所以只凭FOLLOW集合判断是否采用归约是不合适。【如果使用FOLLOW     相当于归约的条件放宽了】所以,引入了LR(1)分析,用来解决这种问题。


LR(1)分析表是在LR(0)基础上加上展望符构成的

因此,我们只要来研究展望符如何生成就可以啦😇😇~~

展望符的生成

        LR(1)项目定义:将一般形式为 [A→α·β, a]的项称为 LR(1) 项,其中A→αβ 是一个产生式,a 是一个终结符(这里将$视为一个特殊的终结符)它表示在当前状态下,A后面必须紧跟的终结符,称为该项的展望符(lookahead)。

  • LR(1) 中的1指的是项的第二个分量的长度,也就是:往后多看一个字符
  • 在形如[A→α·β, a]且β ≠ ε的项中,展望符a没有任何作用(β中可能含有其他的终结符)
  • 但是一个形如[A→α·, a]的项在只有在下一个输入符号等于a时才可以按照A→α 进行归约:这样的a的集合总是FOLLOW(A)的子集,而且它通常是一个真子集

一个例子

文法如下:

步骤一:分析是否需要使用增广文法,确保最终接收状态只有一个
步骤二:写出FOLLOW集(可以全写 也可以不用 部分也行)

步骤三:分析初始状态,再根据下个可能输入的符号分析出之后的状态(类似LR(0)分析)

解释:

由0)可以推导出1式【0):左边橙色框中的式子 1:右边蓝色框中的式子】,有1式中的S是非终结符,所以又可以继续推出等价项目2和3。又2式中圆点后面的L属于非终结符,继续推出4、5式【注意:4、5中的展望符是=,因为2式中L后面有终结符=】然后继续对左边橙色框中的式子进行相同算法的推导即可。

展望符求法:

  • S’的展望符肯定是$,因为S'是规约到最后的符号
  • S的展望符是first_s($)
  • L的展望符是first_s(=R$)
  • R的展望符是first_s($)

1.4.4 构造LALR分析表

LALR分析表是基于LR(1)分析表的改进,改进的点仅仅在于缩小分析表大小

        我们称两个LR(1)项目集具有相同的心,如果除去展望符之后,这两个集合是相同的。LALR分析器就是试图将所有同心的LR(1)项目集合并为一,如果合并后构造的分析表不存在冲突(只存在“归约-归约冲突”),则称其为文法的LALR分析表。

  • 同一个项目中,若两个或多个式子,只是展望符不同,其他都一样,那么是可以写在一起的,就把展望符合在一起写即可
  • 如果除展望符外,两个LR(1)项目集是相同的,则称这两个LR(1)项目集是同心的

上面这三个部分可以进一步合并

2. 总结 

  本文到这里就结束啦~~

本系列专栏将专注于【编译原理】知识。

内容包括:知识点讲解、习题练习、重点知识带练等~~目前已完成:

【编译原理】编译原理知识点汇总·概论与文法-CSDN博客

【编译原理】编译原理知识点汇总·词法分析器(正则式到NFA、NFA到DFA、DFA最小化)-CSDN博客

【编译原理】词法分析器设计(山东大学实验一)_山东大学编译原理实验-CSDN博客

【编译原理】语法、语义分析器设计(山东大学实验二)_语法分析实验-实现一个简单语法分析器(自上而下方法)实验小结-CSDN博客

【编译原理】代码生成器的构建与测试(山东大学实验三)_编译原理实验语义分析代码-CSDN博客 【编译原理】一篇搞定正规式到NFA、NFA到DFA、DFA最小化-CSDN博客

【编译原理】一篇搞定语法分析器对文法的要求(上下文无法文法、消除二义性文法、消除左递归)-CSDN博客

【编译原理】一篇搞定First集、Follow集与select集(超详细)-CSDN博客

期待您的关注~~🥰🥰

猫猫陪你永远在路上💪💪

如果觉得对你有帮助,友友们可以点个赞,收个藏呀~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十二月的猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值