现代编译原理--第二章(语法分析之LR(1))
(转载请表明出处 http://www.cnblogs.com/BlackWalnut/p/4472772.html)
前面已经介绍过LL(1),以及如何使用LL(1)文法。但是LL(K)文法要求在看到K个字母的情况下必须做出预测,这相比于LR(K)文法而言就逊色很多。
LR(K)文法的定义是:从左至右分析,最右推导,超前查看K个单词。先看一个例子,来对LR文法有个大致的印象。
以上就是使用LR文法对源码进行分析的例子。注意到在LR文法中只有三个动作:移进,规约和接受,这三个动作也是通过查表来得到的。任何时候如果都是唯一确定这三个动作中的一个,我们就能让LR文法正确的运行。为了更好的理解LR(K)文法,我们先介绍以下最简单的LR(0)文法。
因为动作是根据表来确定,所以,表的构建依然是我们构建的重点,先来看看一个表的最终形式:
首先要说明的是,构建这张表的时候,我们使用到了状态机,行标就代表状态。列标由两部分组成,分别是终结符,和非终结符。s代表移进,r代表规约,g代表跳转,a代表接受,他们后面跟着的数字,除了r以外,都是状态的标号,只有r后面的数字指的时规约到第几个产生式。所有空的地方都代表出现错误。可见在非终结符下只有跳转。
为了构建这个表,我们首先构建状态机。我们从一个基本的文法开始,文法如下:
我们向产生式中添加一个点,形成这种形式,称为项。这个点的位置告诉我们当前在状态是什么。点每移动一次,我们跳转一个状态。点前面的字符串表示我们已经读取的历史,点后面的字符串表示我们希望得到的。也就是这种表达方式,既可以展望未来,也可以回顾过去。上面这个起始项中,我们希望得下一次得到一个S非终结符,可以看出1和2产生式是S的等价形式,如果我们得到1和2产生式的右部,我们就相当于得到了非终结符S,所以,我们的起始状态为:
我们称第一个产生式为核心项,其他为普通项。这个状态我们称为状态1,所有的状态都是由这个状态中每个项的点的移动得到的。例如,状态1吃掉一个终结符x时,状态1的第二个项中的点要向右移动一位。得到状态2:
当然,状态1也可以吃掉一个终结符(,得到状态3:
状态3中的第一个项就是核心项。上面就我们说的移进操作。
如果状态1吃掉的是一个非终结符S,那么我们称状态需要跳转,起始和移进时相似的效果。那么得到如下状态:
我们再来看状态2,目前点的位置已经到了产生式的最后面,那么意味着这个产生式已经完全匹配了,那么就可以将其规约。具体操作根据r的下标,选择产生式,将栈中的产生式的右部字符串全部弹出,将产生式的左部符号压栈,然后跳转到相应的状态。这个规约还是不太好理解,那么我们对最上面那张图的最后四个规约来举例解释一下。
首先,要说明的是,在实际的使用过程中,在栈中的内容不包含任何的符号,只有状态编号,第一张图是为了方便大家理解,所以才将符号都放入栈中。那么,在规约弹出栈的时候,我们弹出的也都是状态编号。
那么,对于最后四个规约的第一个规约,栈顶符号以此是 +16 (8 S12 ,18 E21 )22这六个符号以及六个个状态,只有最上面的四个满足规约,此时如果用项来表示的话,可以表示为E->(S,E).也就是说在 . 之前我们已经得到一个完整的产生式的右部,可以对其规约。需要把右部所涉及到的所有符号全部弹出,但是我们实际弹出的是状态,所以,原来的16 8 12 18 21 22 弹出状态后,得到的栈为16,我们弹出的字符串规约成为了非终结符E,此时,可以将E看作是在输入队列中输入端,得到 E
现代编译原理--第二章(语法分析之LR(1))的更多相关文章
- 现代编译原理——第二章:语法分析之LL(K)
转自: http://www.cnblogs.com/BlackWalnut/p/4472122.html LL(K)语法分析技术是建立在预测分析的技术之上的.我们先来了解预测分析技术.考虑以下文法: ...
- Java 实现《编译原理》简单-语法分析功能-LL(1)文法 - 程序解析
Java 实现<编译原理>简单-语法分析功能-LL(1)文法 - 程序解析 编译原理学习,语法分析程序设计 (一)要求及功能 已知 LL(1) 文法为: G'[E]: E→TE' E'→+ ...
- 【编译原理】自底向上分析方法——LR文法分析方法的总结
LR(0).SLR(1).LR(1).LALR(1) de 若干方面的区别 目录 推导过程 分析能力 本质区别 文法对比 可以适当利用物理意义对二义性文法进行冲突处理 推导过程 LR(0)的基础上才有 ...
- 编译原理学习笔记·语法分析(LL(1)分析法/算符优先分析法OPG)及例子详解
语法分析(自顶向下/自底向上) 自顶向下 递归下降分析法 这种带回溯的自顶向下的分析方法实际上是一种穷举的不断试探的过程,分析效率极低,在实际的编译程序中极少使用. LL(1)分析法 又称预测分析法, ...
- 编译原理根据项目集规范族构造LR(0)分析表
转载于https://blog.csdn.net/Johan_Joe_King/article/details/79058597?utm_medium=distribute.pc_relevant.n ...
- 编译原理LR(0)项目集规范族的构造详解
转载于https://blog.csdn.net/johan_joe_king/article/details/79051993#comments 学编译原理的时候,感觉什么LL(1).LR(0).S ...
- 第二章 Javac编译原理
注:本文主要记录自<深入分析java web技术内幕>"第四章 javac编译原理" 1.javac作用 将*.java源代码文件转化为*.class文件 2.编译流程 ...
- 跟vczh看实例学编译原理——三:Tinymoe与无歧义语法分析
文章中引用的代码均来自https://github.com/vczh/tinymoe. 看了前面的三篇文章,大家应该基本对Tinymoe的代码有一个初步的感觉了.在正确分析"print ...
- 《编译原理》-用例题理解-自底向上的语法分析,FIRSTVT,LASTVT集
<编译原理>-用例题理解-自底向上的语法分析,FIRSTVT,LASTVT集 上一篇:编译原理-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法 本 ...
- 《编译原理》-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法
<编译原理>-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法 此编译原理确定某高级程序设计语言编译原理,理论基础,学习笔记 本笔记是对教材< ...
随机推荐
- python-django-ORM,常用查询方式
介绍django model 的一些常用查询方式 首先是一些文档性的帮助 __exact 精确等于 like ‘aaa’ __iexact 精确等于 忽略大小写 ilike ‘aaa’ __conta ...
- concurrent.futures模块
1.concurrent.futures模块介绍 2.ThreadPoolExecutor线程池使用 3.ProcessPoolExecutor进程池使用 4.其他方法使用 1.concurrent. ...
- 什么是 web 开发
什么是 web 开发 这几天因为工作需要,了解了一下Web development 的技术路线,来源自 en.wikipedia.org/wiki/Web_development ...
- [python爬虫] Selenium定向爬取PubMed生物医学摘要信息
本文主要是自己的在线代码笔记.在生物医学本体Ontology构建过程中,我使用Selenium定向爬取生物医学PubMed数据库的内容. PubMed是一个免费的搜寻引擎,提供生物医学方 ...
- leetcode344
public class Solution { public string ReverseString(string s) { var list = s.Reverse(); StringBuilde ...
- leetcode326
public class Solution { public bool IsPowerOfThree(int n) { && ( % n == ); } } https://leetc ...
- Redis主从复制原理
前言: 和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况.为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构, ...
- Simple2D-21(重构)渲染部分
以前 Simple2D 的渲染方法是先设置 Pass,然后添加顶点数据,相同 Pass 的顶点数据会合并在一起.当设置新的 Pass 时,将旧的 Pass 和对应的顶点数据添加到渲染数组中.最后在帧结 ...
- python中for循环的用法
Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串. 语法模式:for iterating_var in sequence: in 字面意思,从某个集合(列表等)里顺次取值 #遍 ...
- WDA-文档-基础篇/进阶篇/讨论篇
本文介绍SAP官方Dynpro开发文档NET310,以及资深开发顾问编写的完整教程. 链接:http://pan.baidu.com/s/1eR9axpg 密码:kf5m NET310 ABAP ...