7.JavaCC官方入门指南-例2
例2:整数加法运算--改良版(增强语法分析器)
1.修改
上一个例子中,JavaCC为BNF生产式所生成的方法,比如Start(),这些方法默认只简单的检查输入是否匹配BNF生产式指定的规范。但是我们也可以用java代码来扩充BNF生产式,使得由生产式生成的方法中也包含java代码。
我们加下来会对上面例一中的adder.jj代码做一些修改。对于其中的Start这个BNF生产式,我们加入一些声明和java代码,如下所示:
int Start() throws NumberFormatException :
{
Token t ;
int i ;
int value ;
}
{
t = <NUMBER>
{ i = Integer.parseInt( t.image ) ; }
{ value = i ; }
(
<PLUS>
t = <NUMBER>
{ i = Integer.parseInt( t.image ) ; }
{ value += i ; }
)*
<EOF>
{ return value ; }
}
首先第一个改动是BNF生产式的返回类型,这就使得由该BNF生产式生成的方法的返回值类型由void变成了int。另外的改动是,我们声明了一个可能抛出的异常NumberFormatException。在方法内,声明了3个变量,其中变量t是Token类型的,Token类是我们编译.jj文件文件之后生成的类,而Token类中的image属性则表示匹配到的token的值。在声明完变量之后,当一个token被BNF生产式匹配到,我们就可以通过t = 的方式,将token赋值给t从而记录下来。在BNF生产式中,我们可以加上任何的合法的Java代码,这些Java代码在javacc编译生成语法分析器类时,将会被原封不动的复制到语法分析器类的相应方法中。
现在生成的Start方法将有一个返回值,因此我们对main方法做如下修改:
Public static void main( String[] args ) throws ParseException, TokenMgrError, NumberFormatException {
Adder parser = new Adder( System.in );
int val = parser.Start() ;
System.out.println(val);
}
除此之外,我们还要做如下的一点小改进,我们看到,下面的代码出现了两次:
{ i = Integer.parseInt( t.image ) ; }
{ value = i ; }
虽然在这个例子中影响并不大,但是像这种重复出现的代码还是可能会导致代码维护的问题。因此我们对这两行代码进行重构,将它重构成另外一个BNF生产式,并把这个生产式命名为Primary。
int Start() throws NumberFormatException :
{
int i ;
int value ;
}
{
value = Primary()
(
<PLUS>
i = Primary()
{ value += i ; }
)*
<EOF>
{ return value ; }
}
int Primary() throws NumberFormatException :
{
Token t ;
}
{
t=<NUMBER>
{ return Integer.parseInt( t.image ) ; }
}
下面是生成的代码,从中我们可以看出javacc如何吧java的变量声明和逻辑代码跟生产式融合起来的。
final public int Start() throws ParseException, NumberFormatException {
int i ;
int value ;
value = Primary();
label 1:
while (true) {
switch ((jj ntk==-1)?jj ntk():jj ntk) {
case PLUS:
;
break;
default:
jj la1[0] = jj gen;
break label 1;
}
jj consume token(PLUS);
i = Primary();
value += i ;
}
jj consume token(0);
{if (true)
return value ;}
throw new Error(”Missing return statement in function”);
}
final public int Primary() throws ParseException, NumberFormatException {
Token t ;
t = jj consume token(NUMBER);
{if (true)
return Integer.parseInt( t.image ) ;}
throw new Error(”Missing return statement in function”);
}
2.运行
2.1 adder2.jj
经过上面的修改,最终得到.jj描述文件内容如下,我们将其保存命名为adder2.jj:
/* adder.jj Adding up numbers */
options {
STATIC = false ;
}
PARSER_BEGIN(Adder)
class Adder {
public static void main( String[] args ) throws ParseException, TokenMgrError, NumberFormatException {
Adder parser = new Adder( System.in );
int val = parser.Start();
System.out.println(val);
}
}
PARSER_END(Adder)
SKIP : { " "}
SKIP : { "\n" | "\r" | "\r\n" }
TOKEN : { < PLUS : "+" > }
TOKEN : { < NUMBER : (["0"-"9"])+ > }
int Start() throws NumberFormatException :
{
int i ;
int value ;
}
{
value = Primary()
(
<PLUS>
i = Primary()
{ value += i ; }
)*
<EOF>
{ return value ; }
}
int Primary() throws NumberFormatException :
{
Token t ;
}
{
t=<NUMBER>
{ return Integer.parseInt( t.image ) ; }
}
2.2 运行javacc命令

2.3 编译生成的java文件

2.4 运行程序

可以看到,input.txt输入文件中的内容是1+2,运行完程序之后,即可计算出结果:3。
同样的,如果input.txt文件中的内容是1-2,则会报 词法异常 ,如下图所示:

如果input.txt文件中的内容是1++2,则会报 语法异常 ,如下图所示:

7.JavaCC官方入门指南-例2的更多相关文章
- 11.JavaCC官方入门指南-例6
例6:计算器--添加括号.一元运算符和历史记录 1.calculator3.jj 我们只需要再添加一些特色,就可以得到一个可用的四则运算计算器.在这一版的修改中 ,我们将使得程序可以接收括号.负值 ...
- 9.JavaCC官方入门指南-例4
例4:计算器--添加减法运算 1. calculator1.jj 为了使得计算器具备更多功能,我们需要更多的操作符,比如减法.乘法和除法.接下来我们添加减法运算. 在词法分析器的描述部分,我们 ...
- 8.JavaCC官方入门指南-例3
例3:计算器-double类型加法 下面我们对上个例子的代码进行进一步的修改,使得代码具有简单的四则运算的功能. 第一步修改,我们将打印出每一行的值,使得计算器更具交互性.一开始,我们只是把数 ...
- 6.JavaCC官方入门指南-例1
例1:整数加法运算 在这个例子中,我们将判断如下输入的式子是否是一个合法的加法运算: 99 + 42 + 0 + 15 并且在输入上面式子的时候,数字与加号之间的任何位置,都是可以有空格或者换 ...
- 10.JavaCC官方入门指南-例5
例5:计算器--添加乘除法运算 1.calculator2.jj 根据上一个例子,可知要添加乘法和除法运算是很简单的,我们只需在词法描述部分添加如下两个token: TOKEN : { < TI ...
- 5.JavaCC官方入门指南-概述
一.前言 在最开始使用JavaCC的时候,从网上查询了许多资料,但是网上的资料水平是参差不齐的,走了许多弯路,不得已自己查阅了英文版官网文档.令我伤心的是最后我回过头来再看那些博客资料时,发现其实 ...
- 分布式服务框架 Zookeeper(三)官方入门指南
入门指南:使用ZooKeeper来协调分布式应用 这篇文档包含了让你快速上手ZooKeeper的信息.主要是针对那些想要试一把ZooKeeper的开发人员,包含了安装一个单一ZooKeeper服务器的 ...
- Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据
Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据 在这一节中,你将新创建一个新的 MoviesController类,并编写代码,实现获取影片数据和使用视图模板在浏览器中展现 ...
- Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型
Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型 在这一节中,你将添加用于管理数据库中电影的类.这些类是ASP.NET MVC应用程序的模型部分. 你将使用.NET Framewo ...
随机推荐
- vue-property-decorator使用指南
在Vue中使用TypeScript时,非常好用的一个库,使用装饰器来简化书写. 1.安装npm i -S vue-property-decorator @Prop @PropSync @Provide ...
- ES6 -箭头函数 ,对象的函数解构
ES6 -箭头函数: //es6 中的箭头函数和扩展 //es5的写法 // function add(a,b){ // return a + b; // } // add(1,2); //3 fun ...
- Pycharm2019最新激活注册码(pycharm激活教程)
给大家分享一下PyCharm2019最新可用的激活注册码.激活Pycharm专业版的方法有很多,这里主要给大家分享最有效的两种,一种是使用最新可用的注册激活码,一种是使用破解补丁的方法,这种方法虽然麻 ...
- Mac OS 自带apache 启动不了的问题
问题:Mac OS 自带apache,启动不了,拒绝访问. 1.先看一下错误日志 /etc/apache2/httpd.conf 2.然后我去找了一下/private/var/log/apache2/ ...
- ABP入门教程2 - 体系架构
点这里进入ABP入门教程目录 介绍 应用程序代码库的分层是一种广泛接受的技术,可帮助降低复杂性并提高代码可重用性.为了实现分层体系结构,ASP.NET Boilerplate遵循域驱动设计的原理. D ...
- linux 系统下Anaconda的安装【安装python3.6环境首选】
如果你不想使用python3.6的源码安装包,不想各种繁琐的配置命令,那Anacoda里边自带的python3.6环境就最合适不过了,下面来介绍下anacoda的安装过程,~so easy~Anaco ...
- hadoop节点动态删除与增加
动态删除 1)修改配置文件 修改hdfs-site.xml文件,适当减小dfs.replication的数量,增加dfs.hosts.exclude选项 vi hdfs-site.xml <pr ...
- CK:User mode Bus Error(用户空间操作内核地址导致的异常)
关键词:VEC_ACCESS.coredump.LR.PC等. CK中存在一种VEC_ACCESS异常,可能原因是用户空间访问了内核空间,还有一种是内核访问不存在的总线地址. 下面简单构造VEC_AC ...
- spring mongodb用法
A field annotated with @Id (org.springframework.data.annotation.Id) will be mapped to the '_id' fiel ...
- 201871010113-刘兴瑞《面向对象程序设计(java)》第十三周学习总结
项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>http ...