10.JavaCC官方入门指南-例5
例5:计算器--添加乘除法运算
1.calculator2.jj
根据上一个例子,可知要添加乘法和除法运算是很简单的,我们只需在词法描述部分添加如下两个token:
TOKEN : { < TIMES : "*" > }
TOKEN : { < DIVIDE : "/" > }
接下来我们修改Expression这个生产式,对它的修改跟上一步添加减号运算所做的修改很相似:
Expression --> Primary (PLUS Primary | MINUS Primary | TIMES Primary | DIVIDE Primary)*
从纯粹的句法角度来看,上面这种方法没有什么错,但是它与我们的计算方法不太吻合,因为它没有认识到乘法和除法应该比加法和减法具有更高的优先级。例如,如果我们计算下式:
2*3+4*5
  那么根据我们的表达式,我们获得的结果就会是((2×3) + 4)×5,结果是50,而不是(2×3) + (4×5)。
  因此,我们将生产式修改成如下:
Expression --> Term (PLUS Term | MINUS Term)*
Term --> Primary (TIMES Primary | DIVIDE Primary)*
这样一来,我们就将每个表达式拆分成了一个或多个式子(terms)相加或相减。在我们的例子中,式子(terms)就是两个大括号中的内容:
[ 2*3 ] +[ 4*5 ]
对Expression来说,它的改变就是修改原先对Primary的引用,把它修改到对Term的引用,如下所示:
double Expression() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Term()
    (
        <PLUS>
        i = Term()
        { value += i ; }
      | <MINUS>
        i = Term()
        { value -= i ; }
    )*
    { return value ; }
}
而Term的生产式如下所示:
double Term() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Primary()
    (
        <TIMES>
        i = Primary()
        { value *= i ; }
      | <DIVIDE>
        i = Primary()
        { value /= i ; }
    )*
    { return value ; }
}
2.测试
根据上面的修改,最终得到的calculator2.jj文件内容如下:
/* calculator0.jj An interactive calculator. */
options {
    STATIC = false ;
}
PARSER_BEGIN(Calculator)
    import java.io.PrintStream ;
    class Calculator {
        public static void main( String[] args )
            throws ParseException, TokenMgrError, NumberFormatException {
            Calculator parser = new Calculator( System.in ) ;
            parser.Start( System.out ) ;
        }
        double previousValue = 0.0 ;
    }
PARSER_END(Calculator)
SKIP : { " " }
TOKEN : { < EOL : "\n" | "\r" | "\r\n" > }
TOKEN : { < PLUS : "+" > }
TOKEN : { < MINUS : "-" > }
TOKEN : { < TIMES : "*" > }
TOKEN : { < DIVIDE : "/" > }
TOKEN : { < NUMBER : <DIGITS>
                   | <DIGITS> "." <DIGITS>
                   | <DIGITS> "."
                   | "."<DIGITS> >
        }
TOKEN : { < #DIGITS : (["0"-"9"])+ > }
void Start(PrintStream printStream) throws NumberFormatException :
{}
{
    (
        previousValue = Expression()
        <EOL> { printStream.println( previousValue ) ; }
    )*
    <EOF>
}
double Expression() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Term()
    (
        <PLUS>
        i = Term()
        { value += i ; }
      | <MINUS>
        i = Term()
        { value -= i ; }
    )*
    { return value ; }
}
double Term() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Primary()
    (
        <TIMES>
        i = Primary()
        { value *= i ; }
      | <DIVIDE>
        i = Primary()
        { value /= i ; }
    )*
    { return value ; }
}
double Primary() throws NumberFormatException :
{
    Token t ;
}
{
    t = <NUMBER>
    { return Double.parseDouble( t.image ) ; }
}
先来测试1+2:

计算 2 * 3.3:

计算 9. / 3 :

最后,计算23+45 :

可以看到,乘除的优先级确实高于加减。
10.JavaCC官方入门指南-例5的更多相关文章
- 11.JavaCC官方入门指南-例6
		
例6:计算器--添加括号.一元运算符和历史记录 1.calculator3.jj 我们只需要再添加一些特色,就可以得到一个可用的四则运算计算器.在这一版的修改中 ,我们将使得程序可以接收括号.负值 ...
 - 9.JavaCC官方入门指南-例4
		
例4:计算器--添加减法运算 1. calculator1.jj 为了使得计算器具备更多功能,我们需要更多的操作符,比如减法.乘法和除法.接下来我们添加减法运算. 在词法分析器的描述部分,我们 ...
 - 8.JavaCC官方入门指南-例3
		
例3:计算器-double类型加法 下面我们对上个例子的代码进行进一步的修改,使得代码具有简单的四则运算的功能. 第一步修改,我们将打印出每一行的值,使得计算器更具交互性.一开始,我们只是把数 ...
 - 7.JavaCC官方入门指南-例2
		
例2:整数加法运算--改良版(增强语法分析器) 1.修改 上一个例子中,JavaCC为BNF生产式所生成的方法,比如Start(),这些方法默认只简单的检查输入是否匹配BNF生产式指定的规范.但是 ...
 - 6.JavaCC官方入门指南-例1
		
例1:整数加法运算 在这个例子中,我们将判断如下输入的式子是否是一个合法的加法运算: 99 + 42 + 0 + 15 并且在输入上面式子的时候,数字与加号之间的任何位置,都是可以有空格或者换 ...
 - 5.JavaCC官方入门指南-概述
		
一.前言 在最开始使用JavaCC的时候,从网上查询了许多资料,但是网上的资料水平是参差不齐的,走了许多弯路,不得已自己查阅了英文版官网文档.令我伤心的是最后我回过头来再看那些博客资料时,发现其实 ...
 - 分布式服务框架 Zookeeper(三)官方入门指南
		
入门指南:使用ZooKeeper来协调分布式应用 这篇文档包含了让你快速上手ZooKeeper的信息.主要是针对那些想要试一把ZooKeeper的开发人员,包含了安装一个单一ZooKeeper服务器的 ...
 - 2019.10.28 IDEA入门指南(很多人问补充一篇)
		
Idea快速入门指南 1.安装 1.1.安装 我们使用的是最新的2017.3.4版本: 双击打开, 选择一个目录,最好不要中文和空格: 然后选择桌面快捷方式,请选择64位: 然后选择安装: 开始安装: ...
 - Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据
		
Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据 在这一节中,你将新创建一个新的 MoviesController类,并编写代码,实现获取影片数据和使用视图模板在浏览器中展现 ...
 
随机推荐
- sed 面试题
			
#oldboy my qq num is 49000448.$ not 4900000448. my god ,i am not oldbey,but clsn!$ #oldboy my name i ...
 - Servlet小结(面试)
			
1.doGet()和doPost()区别/get和post请求方法区别: (1)在form表单中:method = “get/post”相对应doGet和doPost方法. (2)在http协议中: ...
 - Dynamics CRM命令栏定制基础知识及手动编辑customization.xml实例
			
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复166或者20151028可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 前面的博文:Dynamics C ...
 - OpenCV:图像的水平、垂直、水平垂直翻转
			
首先导入相关的库: import cv2 import matplotlib.pyplot as plt 自定义展示图片的函数: def show(image): plt.imshow(image) ...
 - MyBtis之关于#{}和${}
			
1.${}的用法的mapper文件配置: </select> <select id="selById2" resultType="com.sus ...
 - s3c2440裸机-时钟编程(二、配置时钟寄存器)
			
s3c2440裸机编程-时钟编程(二.配置时钟寄存器) 1.2440时钟时序 下图是2440时钟配置时序: 1.上电后,nRESET复位信号拉低,此时cpu还无法取指令工作. 2.nRESET复位信号 ...
 - 迁移到MAC
			
周末折腾了2天环境,主要是从windows迁移到mac上,提升逼格告别山寨,迈向专业化.首先,终于把pomelo的c客户端在xcode上跑起来了,至此已基本解决了网络连接问题.由于是第一次用mac开发 ...
 - 函数计算自动化运维实战 2 -- 事件触发 eip 自动转移
			
函数计算 阿里云函数计算是一个事件驱动的全托管计算服务.通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传.函数计算会为您准备好计算资源,以弹性.可靠的方式运行您的代码,并提供日志查询,性能 ...
 - 踩坑---vue-cli搭建的项目中localhost不能访问
			
只需要在config文件夹里面的index.js文件里面的module.exports下面的dev中的 host:'localhost' 改为 host:'0.0.0.0' ,然后重启服务器
 - acwing 23. 矩阵中的路径
			
习题地址 https://www.acwing.com/problem/content/description/21/ 题目描述请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路 ...