编写Lex和Yacc
大学课程设计中,有一次是编写Lex(词法分析器的生成器)和Yacc(语法分析器的生成器),编写这类工具软件不是一件容易的事情。这篇文章记录了当时编程时候的主要思想,主要还是编译原理的思想。
准备
Lex
根据输入文件生成RE—>NFA—>DFA—>简化的DFA—>根据DFA生成文件。
RE处理:
- 对正规表达式进行处理使其只有|、*、(、)等特殊符号,代换{}[]-等
- 将RE转化为后缀表达式
生成NFA:
把下列类型的string转换:
M+----->M.M*
M?------>M|e
最后一共有四种连接:
普通字符(除了.,|,*):
a*:增加三条epsilon边,并且修改终点和起点。
a|b:
新建两个节点,并把其中一个指向原来的两个nfa的起点,另一个被原来的两个终点指向。这四个边均是epsilon。修改终点和起点。
a.b:连接,合并2号和3号节点。(红色代表nfa的起点,黑色代表nfa的终点)
NFA合并:
直接添加一个起点,指向所有nfa的起点。修改起点值,并把原来的终点(每个nfa只有一个)都加入到最后的终点集合。
NFA--->DFA
求闭包
通过epsilon到达的边。迭代直到T’=T,每次
- repeat:
T1 = T;
T=T1∪T1所有点能通过epsilon到达的边
until T1==T
求通过某个字母到达的子集
- for each(Node* node in d)//对d的每一个节点
{
vector<Node*> eout = node->findNext(c);//求出每个节点的出边集合
d1.insert(eout.begin(), eout.end());//将后继的每一个节点不重复的插入d1
}
- 最后返回这个d1的闭包
生成DFA
用j标记当前遍历的节点,用p标记已经存在的节点数量
对当前遍历的节点求每个字符的出边集合,如果有的话,就求该集合的闭包,并判断是否已经存在,做相应的处理:
如果已经存在,则加边
如果不存在,新建节点,再加边,p++
DFA最小化
参考维基百科中关于Hopcroft的算法。
但是对于DFA来说,刚开始并不能简单地分为两个非终结符和终结符的集合,因为每个终结符最后应该在单独的一个集合中。
Yacc
读取文件设置符号和产生式的值—>计算FIRST和FOLLOW—>构造LR(1)预测分析器和PPT(预测分析表)—>LR(1)—>LALR—>打印到输出文件。
计算FIRST和FOLLOW
还是参考的“现代编译原理”这本书。
对于LR(1)可以不计算FOLLOW,所以只计算FIRST。
初始化:每个终结符的FIRST是自己
设置一个是否修改的bool变量,检测本次循环是否修改过
遍历每个产生式
每个产生式的右部符号,如果当前符号前面都是可为空,则将这个产生式左部的FIRST增加当前符号。
如果每个符号都是可为空的,则把这个产生式置为可为空。
构造预测分析器(FA)和预测分析表(PPT)
计算闭包和计算GOTO
类似Lex的计算闭包和子集
构造LR状态图和分析表
类似构造DFA
反思
感觉这次做的比较辛苦,可能这是因为是工具软件的原因吧。工具软件要能针对不同的输入,生成不同的代码,然后生成出来的代码可以去分析一个文件。
编写Lex和Yacc的更多相关文章
- Lex和Yacc入门
Lex和Yacc入门 标签: lexyacc 2013-07-21 23:02 584人阅读 评论(0) 收藏 举报 分类: Linux(132) 原文地址:http://coanor.blog ...
- lex与yacc快速入门
lex与yacc快速入门 [原创] 声明:原创文章,转载注明出处http://www.cnblogs.com/lucasysfeng/ 联系作者:lucasysfeng@gmail.com 第一节.l ...
- 正则语言引擎:一个简单LEX和YACC结合运用的实例
本文先描述了LEX与YACC的书写方法.然后利用LEX与YACC编写了一个简单正则语言的引擎(暂时不支持闭包与或运算),生成的中间语言为C语言. 正则引擎应直接生成NFA或DFA模拟器的输入文件,但在 ...
- Lex与Yacc学习(一)之环境配置篇
Abstract 在开发程序的过程中经常会遇到文本解析的问题,例如:解析 C 语言源程序,编写 脚本引擎等等,解决这种文本解析的方法有很多,一种方法就是自己手动用 C 或者 C++直接编写解析程序,这 ...
- Windows下lex 与 yacc的使用(2)
Windows下lex 与 yacc的使用 ...
- Windows下lex 与 yacc的使用
Windows下lex 与 yacc的使用 首先 下载下载flex和bison.网址是http://pan.baidu.com/s/1dDlfiW5 选择下载就好了,下载后解压到你电脑中的任一盘中. ...
- lex 和 yacc 的区别与联系
lex负责词法解析,而yacc负责语法解析,其实说白了就是lex负责根据指定的正则表达式,将输入的字符串匹配成一个一个的token,同时允许用户将当前匹配到的字符串进行处理,并且允许返回一个标识当前t ...
- Lex与Yacc学习(十)之Yacc库
Yacc库 每个实现都需要有用的例程库,在UNIX系统中,可以通过cc命令行尾端给出-ly标志(或通过其他系统下的等价物)来包含库. 库的内容在不同的实现之间是不同的,但总是包括main()和yyer ...
- Lex与Yacc学习(九)之Yacc语法
Yacc语法 本文讨论yacc语法的格式并描述可用的各种特征和选项 yacc语法结构 yacc语法包括三部分:定义段.规则段和用户子例程段 ...定义段... %% ...规则段... %% ...用 ...
随机推荐
- JQ 让光标在文本框最末尾
function setFocus() { //文本末尾获得焦点 var obj = event.srcElement; var txt = obj.createTextRange(); txt.mo ...
- jdbc - Insert 'Date' value in PreparedStatement
“preparedStatement.setDate()”方法接受的是 'java.sql.Date' 类型的参数,而我们一般格式化日期所使用的是'java.util.Date'中的'SimpleDa ...
- oracle 报错 :ORA-04052、 ORA-00604、 ORA-03106、 ORA-02063
最近发现一个很奇怪的问题: 创建了一个DB_LINK连接另一个Oracle数据库. select * from tablename@dblinkname; 单句执行没问题,但是把这句SQL写到存储过程 ...
- JavaScript Array(数组) 对象
更多实例 合并两个数组 - concat() 合并三个数组 - concat() 用数组的元素组成字符串 - join() 删除数组的最后一个元素 - pop() 数组的末尾添加新的元素 - push ...
- javascript 之DOM篇
要怎么样的开场白才能使我有力气再更新学习进度呢?啊啊啊啊啊,表示好累啊~~~默念“棒棒棒,我最棒~”召唤精气神开总结敲字咯.哈哈哈. --------------------------------- ...
- [转]mysql导入导出数据中文乱码解决方法小结
本文章总结了mysql导入导出数据中文乱码解决方法,出现中文乱码一般情况是导入导入时编码的设置问题,我们只要把编码调整一致即可解决此方法,下面是搜索到的一些方法总结,方便需要的朋友. linux系统中 ...
- javascript——基本包装类型
<script type="text/javascript"> //1.Boolean 类型 //2.Number 类型 //3.String 类型 //Boolean ...
- 泛型? extents super
?可以接受任何泛型集合,但是不能编辑集合值.所以一般只在方法参数中用 例子: ? extends Number 则类型只能是Number类的子孙类 ? super String 则类型只能是Str ...
- iOS图片的伪裁剪(改变图片的像素值)
0x00 原理 利用一张图片事先画好的图片(以下称为蒙板),盖在要被裁剪的的图片上,然后遍历蒙板上的像素点,修改被裁剪图片对应位置的像素的色值即可得到一些我们想要的不规则图片了(比如人脸) 0x01 ...
- 在Lufylegend中如何设置bitmap或者sprite的缩放和旋转中心
最近两天有个lufylegend游戏引擎群的群友需要做一个项目,其中要解决的需求是:获取照相机拍摄的图片,根据图片的EXIF信息让图片显示为“正常”情况,并且需要给图片添加一些事件侦听.何为正常呢?就 ...