1.2第一个例子:加法器

作为第一个例子,我们把以下的一些数相加:

99 + 42 + 0 + 15

除了阿拉伯数字之间外,所有的地方都可以有空格和换行,剩余的字符必须是10进制数或加号”+”。

这段示例代码是”adder.jj”文件的一部分,adder.jj包含JavaCC规则的词法分析和语法分析代码,它处理上面的加法算式。

1.2.1选项和类声明

文件的第一部分是:

/* adder.jj

Adding up numbers */

options {

STATIC = false ;

}

PARSER

BEGIN(Adder)

class Adder {

static void main( String[] args )

throws ParseException, TokenMgrError {

Adder parser = new Adder( System.in ) ;

parser.Start() ;

}

}

PARSER

END(Adder)

在开头的注释之后,是选项部分,本例除了STATIC选项把默认值true改为false外,其它的都是使用的JavaCC的选项默认值,关于选项更多的信息可以参考JavaCC文档,本书的后续部分或者FAQ。接下来是一个称为Adder的Java类,这里看到的不是完整的Adder类,JavaCC会在生成Java代码的过程中添加该类的声明。这个main方法会抛出ParseException和TokenMgrError这两个异常,JavaCC会自动生成这两个异常类。

1.2.2指定一个词法分析器

在返回到这个main方法前,先看看词法分析规则。在这个简单的例子中,词法限定在如下的四行中:

SKIP : { ” ” }

SKIP : { ”\n” |

”\r” | ”\r\n” }

TOKEN : { <

PLUS : ”+” > }

TOKEN : { <

NUMBER : ([”0”-”9”])+ > }

第一行是说空格虽然是标识符,但要跳过,就是说,不传给语法分析器。第二行是换行,和空格一样处理。不同的操作系统的换行符是不一样的,在Unix和Linux系统中使用”\n”,在DOS和Windows下使用”\r\n”,在老的Macintoshes系统(Darwine内核之前,新的Macintoshes系统采用的是Unix方式的换行。译者注)中使用的是单一的”\r”。我们告诉JavaCC所有的这些可能,使用一个垂线”|”来分开它们。第三行告诉JavaCC加号是一个标识符,用PLUS符号表示。最后是第四行,告诉JavaCC数字的语法,用NUMBER符号表示这一类型的标识符。如果你对Perl或者Java的正则表达式包熟悉的话,就容易看懂前面的NUMBER符号了。我们看看正则表达式([”0”-”9”])+,[”0”-”9”]表示任意阿拉伯数字,就是说,是0和9之间的任何unicode字符。形如(x)+的正则式匹配一个或者多个字符串,其中每个字符串又匹配正则式x。所以([”0”-”9”])+匹配一个或多个阿拉伯数字组成的任意序列。这四行都被称为正则表达产生式。

还有一种标识符,被称为EOF,代表输入序列的结束,没必要用正则表达式产生EOF,JavaCC自动把文件的末尾作为EOF。

考虑包含如下字符的一个输入文件:

“123 + 456\n”

词法分析器找到7个标识符:NUMBER,空格,加号,空格,NUMBER,新行,EOF。被标记为SKIP的正则产生式不传给语法分析器,所以语法分析器得到的是:

NUMBER, PLUS, NUMBER, EOF

假设不是合法的输入文件,包含未知的字符,比如:

“123 - 456\n”

在发现第一个空格后,词法分析器会找到一个减号。由于没有减号这个标识符,词法分析器会抛出一个TokenMgrError异常。

如果是下面这个字符序列呢?

“123 ++ 456\n”

这次词法分析也可以把这个序列解析为如下的标识符:

NUMBER, PLUS, PLUS, NUMBER, EOF

词法分析器判断不出这个标识符序列是否正确,会把这些交给语法分析器。语法分析器会在词法分析器传送过来第二个PLUS符号时发现一个错误,那么,它就不再继续处理剩余的部分了。所以实际传送给语法分析器标识符序列是:

NUMBER, PLUS, PLUS

跳过一个字符或字符序列并不等同于忽略它。考虑一个输入序列:

“123 456\n”

词法分析识别出三个标识符:两个NUMBER和中间的一个空格,语法分析器会再次报错。

1.2.3指定一个语法分析器

JavaCC语法规范由NBF产生式构成,看起来有些象Java方法定义。

void Start() :

{}

{

(

)*

}

BNF产生式定义合法的标识符序列,本例中,序列由NUMBER符号开头,以EOF结尾,中间包含0个或多个子序列,这个子序列为PLUS符号后面紧跟一个NUMBER标识符。

前面说的语法分析器只检查输入序列是否含有错误,并不真正的计算数的加法。接下来我们修改这个语法分析器来修正这一点。首先,生成Java代码并运行看看。

1.2.4生成词法分析器与语法分析器

前面已经构造了adder.jj文件,下面用JavaCC来处理它。怎样处理其实是依赖于不同的操作系统的。在Windows NT,2000,XP下面,用“命令提示符”程序(CMD.exe)来运行JavaCC:

D:\home\JavaCC-Book\adder>javacc

adder.jj

Java Compiler

Compiler Version 2.1 (Parser Generator)

Copyright (c)

1996-2001 Sun Microsystems, Inc.

Copyright (c)

1997-2001 WebGain, Inc.

(type

"javacc" with no arguments for help)

Reading from

file adder.jj . . .

File

"TokenMgrError.java" does not exist. Will create one.

File

"ParseException.java" does not exist. Will create one.

File

"Token.java" does not exist. Will create one.

File

"SimpleCharStream.java" does not exist. Will create one.

Parser

generated successfully.

会产生7个Java类,每个都在自身的文件中:

•TokenMgrError一个简单的错误定义类,用于词法分析中遇到的错误,是Throwable的子类。

•ParseException另一个错误定义类,用于语法分析中遇到的错误,是Exception进而是Throwable的子类。

•Token标识符定义类。每个标识符都用一个整型的变量kind和一个字符串类型的变脸image,kind表示标识符(PLUS,NUMBER后者EOF)的类型,image是标识符表示的字符序列。

•SimpleCharStream适配器类,把字符串传给词法分析器。

•AdderConstants定义了词法分析和句法分析用到的一些类的接口。

•AdderTokenManager词法分析器。

•Adder is the parser语法分析器。

现在可以用Java编译器来编译这些类了:

D:\home\JavaCC-Book\adder>javac

*.java

注意:本blog中含源代码的文章推荐使用firefox阅读,可以获得较佳的效果。

java加法器_javacc例子:加法器相关推荐

  1. 20 个使用 Java CompletableFuture的例子

    转载自 20 个使用 Java CompletableFuture的例子 这篇文章介绍 Java 8 的 CompletionStage API和它的标准库的实现 CompletableFuture. ...

  2. java线程安全例子_Java总结篇系列:Java多线程(三)

    本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题. 一.一个典型的Java线程安全例子 1 public classThreadTest {2 3 public static voi ...

  3. 两个运放制作加法器_同相加法器电路图_反相加法器电路图_运放加法器电路图解析...

    在电子学中,加法器是一种数位电路,其可进行数字的加法计算.加法器是产生数的和的装置.加数和被加数为输入,和数与进位为输出的装置为半加器.若加数.被加数与低位的进位数为输入,而和数与进位为输出则为全加器 ...

  4. java抽象类例子_关于java抽象类的例子

    在网上找了很久,发现没有一个比较好的关于java抽象类的例子,刚好自己这些天在书上看到一个不错的猜数字游戏的例子,所以拿出来改进了下,希望能给你一些帮助,具体内容如下 建2个类依次为AbstractG ...

  5. Java swing 代码例子

    Java swing 代码例子 package com; import java.awt.Button; import java.awt.Container; import java.awt.even ...

  6. java hbase 例子,java操作hbase例子

    java操作hbase例子 java操作hbase,在eclipse中创建一个java项目,将hbase安装文件根目录的jar包和lib目录下jar包导入项目,然后就可以编写java代码操作hbase ...

  7. Java Lambda reduce 例子 全网reduce最清晰易懂的例子,不服来辩 xxx XXX

    Java Lambda reduce 例子 全网reduce最清晰易懂的例子,不服来辩 xxx XXX import java.util.Optional; import java.util.stre ...

  8. Java Lambda 分区 例子 水仙花

    Java Lambda 分区 例子 水仙花 水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI).自恋数. ...

  9. java 序列化 例子_一个简单的Java序列化的例子

    简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对 ...

最新文章

  1. ROS 使用参数以及相应的 .launch 文件编写
  2. 协议开发 中移动CMPP2.0协议API(三)
  3. 【Java设计模式】策略模式
  4. mysql将时间轴转化为时间_MySQL日期计算及格式转换有关问题
  5. 使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程
  6. ios开发跳转safari_iOS 跳转网页的四种方法
  7. 陌陌看好的移动营销 Criteo表示尚未成为主流
  8. Hbuilder连接安卓模拟器,调试app
  9. ASP.NET2.0下使用AJAX调用Webservice的方法
  10. python重复输出_python日志重复输出
  11. python安装lap_AP 升级到 LAP,或 LAP 降到 AP 的方法
  12. CSS 行内元素设置高度
  13. Apache Flink 在快手万亿级数据的应用实践总结
  14. SpringBoot项目修改JDK后报错(class file version 55.0)
  15. Linux系统下的10款非常优秀的POS开源软件
  16. owasp zap手动访问站点,chrome浏览器闪退
  17. 专业实习报告范本4篇
  18. m3u8 ts 视频流下载插件(神器)
  19. 【报告分享】 2020跨境出口电商行业白皮书-CBNDATA(附下载)
  20. 小区门禁卡可以复制到手机上吗_手机NFC可以复制小区用的门禁卡吗?

热门文章

  1. [bzoj4922]Karp-de-Chant Number
  2. #define const typedef
  3. operator new,new operator,placement new的区别
  4. python 简单图像处理(8) 直方图均衡化
  5. 用《叩响C#之门》复习C#基础知识 第八章 面向对象编程:类和对象(二)
  6. 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast(转载)
  7. CF1066F Yet another 2D Walking
  8. Redis(2)---数据持久化
  9. [NIO系列]NIO源码分析之Buffer
  10. 怎么开发一个npm包