编译原理——自下而上的语法分析方法(LR分析法)
自下而上的语法分析(LR分析法)
概述
- 上下文无关文法的LR分析法
- LR:自左至右扫描,最右推导的逆过程(也就是最左归约)
LR方法:
在归约的过程中,一方面记住移入和归约的整个符号串,另一方面通过产生式推测未来可能碰到的输入符号
优缺点:
- 优点:文法范围广,识别能力强,可以识别出错位置
- 缺点:工作量大,需要构造这种分析程序的产生器
产生器作用:
- 应用产生器产生一大类上下文无关文法的LR分析程序
- 对二义性文法或难分析的特殊方法,施加一些限制使之能用LR分析法
LR分析器:
包括两部分:总控程序,分析表
总控程序:控制程序的运行,查分析表的内存做简单动作
产生器的任务就是产生分析表分析表:
- 一个文法的LR分析器对应四种不同分析表,所以分析表都恰好识别产生的所有语句
- LR(0),SLR,LR(1),LALR四种分析表
LR分析法
- LR分析法的基本思想
- 规范归约时,当一串貌似句柄的符号串呈现于栈顶,LR分析法根据三方面来寻找句柄:历史,展望,现实
- 下推栈:
- 分析表:
- 总控程序的动作:
解释:移进动作就是将在两个栈的栈顶(si,a)si表示状态,a表示栈顶的字符,因为a是终结符,所以去该状态列对应的终结符行,相交成的动作,需要先将下一个字符移入,然后将某一个状态加入状态栈中栈顶变为(sj,b)
LR分析器
分析过程:
0状态遇到i,跳到5状态
5状态遇到*,按照6产生式归约
F入栈,0状态遇到F非终结符,入栈状态3
LR文法:
- 定义:如果可以根据某一文法可以构造一张分析表,使得该表中每一个元素至多只有一种明确的动作,这个文法就是LR文法
LR(0)项目集族和LR(0)分析表的构造:
基本思想:
- 只根据历史来识别呈现于栈顶的句柄
LR(0)是其他分析法的基础
构造表的策略:
- 构造文法G的优先自动机,他能识别文法中的所有活前缀
活前缀:
- 字的前缀是指字的任意首部
- 例如:字ABC的前缀有空,A,AB,ABC
- 活前缀概念:
- 指规范句型的前缀,这种前缀不含句柄之后的任何符号
- 规范句型:通过规范推导和归约得到的句型
- 例子:
例如:ab[2]b[3]cd[4]e[1]
先去识别ab得到[2],通过2号产生式得到对b归约,aAb[3]cd[4]e[1],通过[3],aAcd[4]e[1],通过[4],aAcBe[1],通过[1],的得到S
- 字的前缀是指字的任意首部
活前缀的两种类型:
- 归态活前缀:活前缀的尾部正好为句柄尾部,可以进行归约 前文中的ab[2]就是
- 非归态活前缀:句柄未形成,需要继续移进若干符号之后才能形成句柄
构造自动机识别活前缀:
- 对于一个文法,我们可以构造一个自动机来识别它的所有活前缀
- 由于产生式的右部符号串就是句柄,若这些符号串以进栈,则表示它已处于归态活前缀,若只有部分进栈则属于非归态活前缀。要想要知道活前缀有没有大部分入栈,可以为每一个产生式构造一个自动机,由它的状态来记住当前情况,这个状态称为项目,这些自动机的全体是能识别所有活前缀的优先自动机
项目:
由项目构造NFA的方法:
文法拓展的必要性:通过对文法的扩展,不会出现单单只识别了一个开始符号就确定是这个句子的情况。例如S->bS’A | asd,这时候,当我们,读入了b,进入bS‘A状态,然后需要读入S’,这时我们返回去,通过读入asd进入了终态,这时候,我们结束,但是也可以继续,这时候机器就不知道怎么选择了
例子:
列出所有项目
对于识别空串就是,小圆点到达了一个非终结符前面,可以通过读入这个非终结符的首符集来进入这个非终结符。LR(0)项目集族的机器构造法:
例子:
解释:(这里使用了*表示点)
首先找到开始符号S‘的e闭包状态集S’->E,E->*aA,E->bB,为状态集0
找状态集族里的状态集0,发现可以通过E到达状态S‘->E ,可以通过a到达状态E->aA,可以通过b到达状态E->bB,
对三个终态集求闭包
以此类推构造LR(0)分析表:
解释:
这里的go函数表示的就是当栈顶符号为Ik,读头下符号为a,那么就将a入栈,并入栈一个识别了a的状态
当小点出现在一个产生式的最后位置,那就表示对于读头下任何符号,都可以使用归约,将符号栈中已有的部分符号按照某个产生式进行归约,
SLR语法分析方法:
当使用LR(0)分析法,出现归约和归约之间的冲突,移进和归约之间的冲突,可以尝试使用SLR分析法,可以解决LR(0)分析法的部分问题。
例如在一个项目中A->a* ;B->b*;这时候,到这个状态按照LR(0)有两种归约方法,因此发生了冲突。
在归约时除了考虑历史情况之外,还考虑一些现实
消除冲突
构造SLR分析表:构造LR(0)项目集族,使用SLR分析法填表。
2):对于读头下面是follow集中的字符,才使用归约操作
为什么不能解决移进-归约:信息不足,因为当follow(A)存在a字符,可以对A进行归约也可以对X进行移进操作。例子:
上图为产生移进-归约冲突,提示:为什么LR(0)不能避免归约-移进操作,LR(0)分析法,对于可以进行归约操作的字符串,将所有字符都作为归约操作,这样对于可以移进操作的字符,就会出现重定义。为什么不能避免归约-归约冲突:因为如果一个字符串有两个选择进行归约,同样因为将所有的读入字符都可以进行归约,这样会导致可以对所有的字符都可以进行两个选择进行归约。
为什么SLR文法可能不会产生移进-归约冲突:因为当归约项的follow集中不包含移进项的字符,就可以明确下一个动作就是归约
例如I1状态,其中按照SLR分析法,有归约动作我们需要求FOLLOW(S’)={#}可以归约操作,对于+可以进行移进操作,当时这时候+不属于FOLLOW(S’)所以没有发生冲突。
可以看到这张表中,有些带有归约动作的行,不是如LR(0)文法,一行都是归约动作,可以看3状态T->F*;按照SLR规则我们需要找到T的follow()集合{*,+,),#},当读头下出现这四个符号时,表示可以对T->F归约。一个非SLR的例子:
对于状态2:follow®中存在=,这就造成了移进和归约的冲突
为什么会出现这种情况:当follow集中有某个字符,当读头下是这个符号时;但是不能将栈中符号串进行归约,也就是上图中的项目2,R的follow集中有{=}但是,不能将L归约成R,原因是,follow集中的符号是忽略了前提的,它只是告诉我们后面可能会出现的符号,但是当某些前提达不到时,其实后面跟随的符号是永远不会出现的;就像题中的R的follow集,存在"=“但是只有S‘->S;S->L=R;L->*R时,R后面才可能出现”=",所以当R前面是" * “时,后面读入的符号才可能是”=";否则,如果将这题中的L归约成R,就可能造成,两条路,向一条走的可以走通,但是我们走向了另外一条,导致了错误,程序认为该句子不能识别。
如上图对于一个字符串i=进行归约,按照上图步骤推出错误,所以当我们推导i=R(这里的R只是一个R只是代指一个R可以推出的字符串)也是会推出错误,但是这样的字符串可以通过S->L=R归约得到,就是因为将i归约成了L又错误的归约成了R,导致了错误。
规范LR分析表构造:
SLR的缺陷:
对于项目集2,产生了移进归约冲突,因为当读头下为=,可以进行移进,当时follow®中也存在=,这是为什么,因为follow()集指的是,这个符号后面可能出现的符号,这时忽略了前提条件的。例如对于这个文法,在2项目的情况下,读头下是=,但是如果我们将L归约成了R,那也就是说我们认为R后面可以跟着=,但是我们根据文法推导得到,要出现R=的情况,只有在R前面是*的时候才成立,也就是R‘->R->L=R->*R=R,但是我们显然知道项目2是通过S‘->S->R->L得到的,也就是栈中没有 * ,所以在项目2中没有L归约成R的可能性。我们应该关系的是这样的规范推导后面跟着的符号是什么,在S‘->S->R->L也就是first(#),因为S‘后面跟着的就是#好,也就是说,当读头后面跟着的是#的时候,才可以将L归约成R,这样一路归约下去,到R’。
规范LR:
这个也就是表示栈里面放的是α,读头下面是β,预计当我们读入β后,
这个也就是表示栈里面
在这种情况下,我们在x项目下,我们可以知道的是我们栈中有ae,遇到了c可以进行移进操作也就是S->aec,也可以使用归约操作A->e,因为A的follow集中有=,产生冲突了,那就是因为,follow集只考虑了会出现了,但是没有考虑在规范推导中会出现的,我们进行规范推导,发现当ae在栈中,只有读头下面是first(d)时,才可以通过将e归约成A,然后读入d,将栈归约成S,再归约成S‘,而此时的读头下面是c,所以当我们将e归约成了A,栈中变成了aA,读头下面是c,则出现了错误,因为当栈中是aA时,之后读头下面是d,才能读入。
follow(A)={c,d},当A后面出现c,那正确的条件是栈中有a;当A后面跟d,那正确的条件是栈中有b,这两种中,只有aAd是规范推导
规范LR项目集族的构造过程:
(表示点号)对于{(A->α * Bβ,a)}项目集,(A->α * Bβ,a)表示栈中有了α,我们需要读入B,再读入β,这时候进行归约,只有当读入下面是a的时候才能归约;我们先使用LR(0),将空串产生式加入项目集{(A->α * Bβ,a),(B-> γ,first(βa))},这里的first(βa)是因为,我们需要找到规范推导后,可以进行γ归约成B的条件,也就是读头下面是first(βa)。
因为还是针对同一个需要被归约的式子,搜索符只是作为一个归约是读头的判断条件而已。
解释:从(S’-> * S,#)产生(S-> * L=R,#),当读头下面是#对L=R进行归约,再产生(L-> (点) *R,first(=R#))……
此处的图在《编译原理及编译程序构造第三版》的p121页
LR(1)分析表:
只有对后文中的first()才进行归约。
1),对于一个项目k,如果k读入一个终结符到j项目,将action[k,a]置为读入并转到状态j
2),对于一个归约状态k,只有读头下是a的时候,才会归约,也就是将action[k,a]置为归约产生式的编号
LALR分析法:
基本思想:
合并同心:
假设有同心项目m和n,则,m和n通过识别X到达了m’和n’状态,我们就可以将两个项目合并,假设去除n项目那一栏,然后将原来指向n项目的指向m项目,原来指向n’项目的指向m’项目
!移进和移进合并,因为当前项目是同心的,所以当这个项目读一个非终结符之后,得到的项目也是同心的,则我们去掉一个项目,让其他本来指向去除项目的关系,指向对应的同心项目
归约和出错合并,因为规定做归约的原因,所以放松了报错条件,因为可能遇到了报错的那种情况,但是我们去做了归约处理,但是报错能力没有减弱,时间推后了
在这种情况下,第一个项目,当读头下是d归约为A,是e归约成B,当两个项目合并后,因为两个搜索符都一样,当出现这种情况,就不知道怎么进行归约了,出现了归约归约冲突。所以LALR文法是LR(1)的子集
构造算法:
比LR(1)多个一个合并同心的操作,action表的构造一致
构造goto表,需要将删去的那些项目,读入一个X填写的值,置为还存在的那个项目集读入一个X填写的值一致
定义
编译原理——自下而上的语法分析方法(LR分析法)相关推荐
- lr1分析器c语言实验报告怎么写,编译原理课程的设计构造LR分析法语法分析器.doc...
编译原理课程的设计构造LR分析法语法分析器 太 原 学 院 课程设计报告书 课程名称 设计题目 构造LR(0)分析法语法分析器 专业班级 学 号 姓 名 指导教师 2016年 12 月 15日 目 录 ...
- 编译原理中词法分析的递归下降分析法实例--能被5整除的二进制数---c语言实现
一.前言 又到了一周一度的编译原理实验课,一次实验课上完了,又是大学生必备技能-写实验报告.行了,废话不多说,我直接展现,如何实现编译原理中词法分析的递归下降分析法实例–能被5整除的二进制数的思路.作 ...
- 编译原理:语法分析实验(LR分析法)
语法分析实验 一.实验目的 根据LR分析法的原理,对指定文法构造识别活前缀的DFA,做出相应的LR分析表,并编程实现相应的语法分析程序.或根据预测分析法的原理,对指定文法构造预测分析表,并编程实现相应 ...
- 编译原理——自上而下的语法分析方法(LL分析法)
自上而下的语法分析方法(LL分析法) 概述: 语法分析的地位:编译程序的核心部分 任务:词法分析出来的单词序列是否是给定文法的句子 理论:上下文无关文法和下推自动机 方式:自上而下的语法分析(推导)和 ...
- 【编译原理】 实验三 LL(1)分析法(LL1分析表的自动生成)
写在前面 由于代码较长,csdn对文章总长度有字数限制,想只看完整代码的请移步另一篇博客. https://blog.csdn.net/qq_46640863/article/details/1257 ...
- 编译原理--语法分析:LR
归约 可将自底向上语法分析过程看成将一个串ω"归约"为文法开始符号的过程. 在每个归约步骤中, 一个与某产生式体相匹配的特定子串被替换为该产生式头部的非终结符号. 句柄剪枝 如有S=>^{*}_ ...
- 编译原理--语法分析:LR(1)
规范LR(1)项 对LR(0)中本来需要归约的行为,再往前看一步,考察归约后, 下一步是否会报错. 入股归约后下一步不会报错,按LR(0)进行归约. 否则,不进行归约.正式地将, 可行前缀&有 ...
- 编译原理(六)自底向上分析之LR分析法
自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...
- 【编译原理】Python语法分析LL(1)、LR(1)
目录 一.实验目的 二.实验任务 三.实验原理 1 LL(1)文法 2 LR文法 四.实验过程 1 LL(1)文法 2 LR文法 五.实验结果 1 LL(1)文法 2 LR(0)文法 3 ...
- 编译原理实验(三)——LR(0)语法分析
编译原理实验(三)--LR(0)语法分析 实验要求 参考程序 实验结果 程序输入说明 截图 实验要求 根据LR(0)分析法编写一个语法分析程序 直接输入根据已知文法构造的分析表M;对于输入的文法和符号 ...
最新文章
- 通过python+ftps远程备份企业数据
- squid缓存服务器
- Spring Security 实战:基于配置的接口角色访问控制
- windows mobile开发循序渐进(4)移动应用程序的数据存储之本地数据存储第二篇
- 遇到的JDBC的一个问题
- php 前置匹配,浅析PHP正则表达式匹配的特定实现
- sql基础之DDL(Data Definition Languages)
- 蓝桥杯 ADV-9 算法提高 递归倒置字符数组
- Linux系统的日志服务器syslogd
- VTD学习记录——八大进程概括(一)
- css 标签上 title 和 alt 的区别
- Microsoft Navision 4.0帮助您消除日常工作流程中的烦恼的7条途径
- 求冠唐干部管理系统的数据库设计
- 字节跳动 AI Lab 总监李航:语言模型的过去、现在和未来
- 现场总线->无线网络的技术->泛在网络
- 陶哲轩实分析 4.4 节习题试解
- 终于考过了驾照考试,现在就=驾照下来了
- 玉米社:百度竞价推广否词什么意思?在哪里查看?怎么添加?【全】
- 宽带服务器维护查询,网络连接状态查询方法
- 基于tesseract的文字识别