0.概述:

  看了编译器龙书和虎书后,自己手动写了一个LALR(1)语法分析生成器,使用的语法文件格式和lemon的差不多。

  程序里面很多的算法也都是摘录自虎书,龙书虽然讲的很详细,但是真正动手写的时候还是虎书上面的算法给力点。程序相对来说比较简单,没有做任何优化,如果看过虎书和龙书,看懂代码难度不大。代码文件bytes.hpp和bytes.cpp中是主要的代码,TEMPLATE.hxx和TEMPLATE.cxx是语法分析生成器的模板文件。首先直接用make进行编译,然后进入到test目录中,运行生成器程序文件,参数是语法说明文件。执行成功后会生成会文件PARSER.hxx和PARSER.cxx,这两个文件就是你需要的语法分析器了。下面是个简单的实例说明下。

  1.语法说明文件:

这里用一个简单的计算器来说明语法说明文件的用法。下面是计算器的语法说明文件。

%include { #include <iostream> }
%token { int }
%syntax_error { std::cout << "Error: Syntax error.\n" << std::endl;}
#left PLUS MINUS
#left TIMES DIV program -> exp(A). { std::cout << "Result=" << A << std::endl; } exp(A) -> exp(B) MINUS exp(C). { A = B - C; std::cout << A << "=" << B << "-" << C << std::endl; }
exp(A) -> exp(B) PLUS exp(C). { A = B + C; std::cout << A << "=" << B << "+" << C << std::endl; }
exp(A) -> exp(B) TIMES exp(C). { A = B * C; std::cout << A << "=" << B << "*" << C << std::endl; }
exp(A) -> exp(B) DIV exp(C). {
if(C != )
{
A = B / C;
}
else
{
std::cout << "Divide by zero." << std::endl;
} std::cout << A << "=" << B << "/" << C << std::endl;
} exp(A) -> INT(B). { A = B; std::cout << A << "=" << B << std::endl;}

终结符:终结符的名称只能由大写字母组成,在生成PARSER.hxx文件中会包括所有终结符的枚举定义。词法分析器的分析结果要和这里定义的枚举值一致。

  非终结符:非终结符由小写字母、下划线组成,非终结符只存在于生成语法分析器的过程中。生成的语法分析器不会包括非终结符。

  %include:这个说明符指定了生成的语法分析程序中要包含的头文件,这个指示符的格式是后面必须用大括号。如果有多个头文件可以用回车。

  %token:这个是token结构的指示符,必须在大括号中指定,目前只支持内建的数据类型。

  %syntax_error:语法分析过程中出现错误时,需要执行的代码。

  #left:左结合指示符。同时会指定优先级,越往后面的优先级越高。

  #right:右结合指示符。同left一样会指定优先级。

  program:是语法开始指示符,语法说明文件必须指定program生成式,否则会报错。

  BNF范式(产生式):每个产生式必须以非终结符开始,以 . 符号结束。产生式中的每个非终结符都可以起别名,方便在语义代码中使用,别名必须紧跟在非终结符后面,而且要括在小括号中。需要注意的是xbytes不支持,一行多个产生式,因此每行只能写一个产生式。

  语义代码:每个产生式的后面可以在大括号中指定产生式的语义代码。这个大括号要放到产生式最后的 . 点前面。语义代码只要是C++或者C代码就可以,没有其他限制。

  语法说明文件名:因为我写的语法分析生成器的名字叫xbytes,所以我把语法说明文件的后缀名指定为.x。比如上面计算器的语法说明文件名:calculate.x 。当然这个文件的后缀名是可以随便起的,即使没有也没有关系。

  ACTION.txt:在生成语法分析器的同时,会生成一个名为ACTION.txt的文件。文件中以很友好的方式将语法分析器的动作表打印出来了。可以帮助用户理解LALR(1)语法分析器的运作过程。

  备注:在xbytes.cpp代码文件中,包含许多dump_开头的函数。这些函数可以输出很多生成分析器过程中的数据。包括Symbol集合、规则集合、First集、Follow集、状态集和动作表等。

  2.语法分析器使用方式:

在根目录下直接输入 make 。编译xbytes,生成的可执行程序会被移入test目录中,进入test目录,然后执行./x calculate.x 就可以生成,简单计算器的语法分析程序了。使用这个程序的方式是自己写一个main.cpp文件,文件内容如下:

#include "PARSER.hxx"
#include <iostream> int main()
{
xbytes::parser p; //5 * 3 + 6 / 2 - 8
p.eat(INT, );
p.eat(TIMES, );
p.eat(INT, );
p.eat(PLUS, );
p.eat(INT, );
p.eat(DIV, );
p.eat(INT, );
p.eat(MINUS, );
p.eat(INT, );
p.eat(, ); return ;
}

使用方式很简单,首先要自己写个词法分析器,来进行词法分析,然后将词法分析得到的token一个个的喂给parser就可以了。parser::eat函数的第一个参数是token的类型,第二个参数是token的值。读取结束后,最后写入0,就是结束分析。

3.运行结果:

这里计算的是算式 5 * 3 + 6 / 2 - 8 的值。打印的是规约的过程,具体要打印的信息可以自己在语法说明文件的语义代码中自己定制。

[kiven@localhost test]$ ./XP
=
=
=*
=
=
=/
=+
=
=-
Result=

4.代码:

目前的代码我只在CentOS下面测试过,其他平台没有经过测试。代码地址:https://github.com/kiven-li/xbytes

  5.展望:

  目前程序也仅仅只是能够生成语法分析器,但是性能不是很好,实用性也不是很高。后续要优化下程序性能,token要支持自定义结构。

LALR(1)语法分析生成器--xbytes的更多相关文章

  1. JavaCC首页、文档和下载 - 语法分析生成器 - 开源中国社区

    JavaCC首页.文档和下载 - 语法分析生成器 - 开源中国社区

  2. 之前博客中的代码都放到github上

    之前一直把代码托管在taocode上,现在已经不能用了,所以把代码整理了一下,统一都放在gibhub上了. LALR(1)语法分析生成器:https://github.com/kiven-li/xby ...

  3. About Webkit

    http://blog.csdn.net/spacetiller/article/details/5784461 一 . WebKit 简介 Webkit 是一个开放源代码的浏览器引擎 (web br ...

  4. 几个不常见但非常出色的 .NET 开源库

    NLog NLog 目前最为出色的 .NET 日志库,非常容易配置,且极具灵活性.最重要的是与 log4net 相比,NLog 的开发很活跃.顺带提一句,NLog 完全兼容 Mono. Mono.Ce ...

  5. WebKit介绍和总结(一)

    一 . WebKit 简单介绍 Webkit 是一个开放源码的浏览器引擎 (web browser engine) ,最初的代码来自 KDE 的 KHTML 和 KJS( 均开放源码 ) . 苹果公司 ...

  6. WebKit介绍及总结(一)

    一 . WebKit 简单介绍 Webkit 是一个开放源码的浏览器引擎 (web browser engine) ,最初的代码来自 KDE 的 KHTML 和 KJS( 均开放源码 ) .苹果公司在 ...

  7. SQLite Lemon 语法分析器学习与使用

    本文是浙江大学出版社的<LEMON语法分析生成器(LALR 1类型)源代码情景分析>学习笔记. 用到的Windows下的编译器介绍MinGW(http://www.mingw.org/): ...

  8. YACC、LEX、JAVACC-------常用的编译工具

    CC(Compiler Compiler) CC的意思就是"编译器的编译器". 你可以定义一种上下文无关文法(CFG),然后针对这个特定的CFG你可以写出一个C程序来解释这种CFG ...

  9. Python之父新发文,将替换现有解析器

    花下猫语: Guido van Rossum 是 Python 的创造者,虽然他现在放弃了"终身仁慈独裁者"的职位,但却成为了指导委员会的五位成员之一,其一举一动依然备受瞩目.近日 ...

随机推荐

  1. SQL Server 2008 R2 开启数据库远程连接

    今天要测试一个.net系统~因为配置的数据库是SQL Server~我就不得不安装SQL Server 2008 R2~现在我们就一起来看看SQL Server 2008 R2是如何打开远程连接端口1 ...

  2. WCF之常见异常整理(不断更新中...)

    系统Win7   IIS7.5 异常1.找不到具有绑定 NetTcpBinding 的终结点的与方案 net.tcp 匹配的基址.注册的基址方案是 [http]. 产生原因:网站没有配置net.tcp ...

  3. c++ 全局变量初始化的一点总结

    注意:本文所说的全局变量指的是 variables with static storage,措词来自 c++ 的语言标准文档. 什么时候初始化 根据 C++ 标准,全局变量的初始化要在 main 函数 ...

  4. 购物车增加、减少商品时动画效果:jQuery.Fly.js插件使用方法

    某些电商网站加入购物车和减少购物车商品数量时,有个小动画,以抛物线形式增减,如图:      这里用到了第三方jQuery.Fly.js插件(底层依赖Jquery库,地址:https://github ...

  5. 蓝凌表单的表体调用Javascript

    应用场景:像请假类表单会在从表输入开始时间.结束时间等字段 需求1:客户希望根据开始.结束时间自动计算小时数 解决方法: 1.主表单增加一行,设三个字段[开始时间合计].[结束时间合计].[开始结束时 ...

  6. SNF开发平台WinForm之二-开发-单表表单管理页面-SNF快速开发平台3.3-Spring.Net.Framework

    2.1运行效果: 2.2开发实现: 2.2.1 这个开发与第一个开发操作步骤是一致的,不同之处就是在生成完代码之后,留下如下圈红程序,其它删除. 第一个开发地址:开发-单表表格编辑管理页面 http: ...

  7. 数据可视化(5)--jqplot经典实例

    本来想把实例也写到上篇博客里,最后发现太长了,拆成两篇博客了. 实例来源于官方文档:http://www.jqplot.com/tests/ 这篇博客主要是翻译了官方文档关于经典实例的解说,并在相应代 ...

  8. Tips11:用[Rang]来限制Inspector中的变量

    我们在写脚本的过程中可能会用到很多Public变量,如INT型,Float型,这些变量在项目中可能有着一个默认的实际范围,如血量不能为负数,而且int float本来就是有一个范围的,如果对这些变量加 ...

  9. Tools - Notepad++

    NotePad++ https://notepad-plus-plus.org/ 修改主题 依次点击设置---语言格式设置---选择主题,在显示界面中修改相关设置(背景色.前景色.字体等). 双文本横 ...

  10. Feathers JS – 基于 Express 构建数据驱动的服务

    Feathers 是一个轻量的 Web 应用程序框架,基于 NodeJS 最流行​​的 Web 框架——Express.这使得它很容易使用 socket.io 来创建 RESTful Web 服务和实 ...