官网链接:JavaCC

JavaCC


JavaCC是Java的解析器生成器兼扫描器生成器。为JavaCC描述好语法的规则,JavaCC就能够生成可以解析该语法的扫描器和解析器(的代码)了。

JavaCC是LL解析器生成器,因此比起LR解析器生成器和LALR解析器生成器,它有着可处理语法的范围相对狭哉的缺点。

但是,JavaCC生成的解析器有易于理解,易于使用的优势。且支持无限长的token超前扫描特性,所以速度非常的快。

巨坑


我为什么要把坑写在前面?因为这真的是太坑了!

一开始我下载的是官网的javacc-6.0,配置好环境变量后还是一只报错:

找不到或者无法加载主类 javacc

没错,官网的6.0版本有问题!于是使用javacc-5.0就好了。

具体参考:getting-started-with-javacc

编写语法描述文件


语法描述文件通常会使用.jj的后缀文件

语法描述文件的常用形式

options {
JavaCC 的选项
} PARSER_BEGIN(解析器类名)
package 包名;
import 库名; public class 解析器类名 {
任意的Java代码
}
PARSER_END (解析器类名) 扫描器的描述 解析器的描述

实例编写

Person.jj(文件名称可以任意命名)

options {
STATIC = false;
} PARSER_BEGIN(Person)
import java.io.*; class Person {
static public void main (String[] args) {
for (String arg : args) {
try {
System.out.println(evaluate(arg));
}
catch (ParseException ex) {
System.err.println(ex.getMessage);
}
}
} static public long evaluate (String src) throws ParseException {
Reader reader = new StringReader(src);
return new Person(reader).expr();
}
}
PARSER_END(Person) SKIP: { < [" ","\t","\r","\n"] > } TOKEN: {
<INTEGER: (["0"-"9"])+>
} long expr(): {
Token x,y;
}
{
x=<INTEGER> "+" y=<INTEGER> <EOF>
{
return Long.parseLong(x.image) + Long.parseLong(y.image);
}
}

具体分析:

  • options块中,将STATIC选项设置为false的意思是解析器可以在多线程环境下使用。设置为true亦反。
  • PARSER_BEGINPARSER_END是解析器类的定义。解析器类中需要定义的成员和方法也写在这。为了实现及时只有Person类也能够运行,这里定义类main函数。
  • SKIP和TOKEN部分定义类扫描器。SKIP表示要跳过空格,制表符和换行符。TOKEN表示扫描整数字符并生成TOKEN。
  • 从long expr...开始到最后的部分定义了狭义的解析器。这部分解析token序列并执行某些操作。

使用JavaCC来处理语法描述文件Person.jj

命令如下:

javacc Person

如果描述文件有问题,处理的时候会报错:

➜  java javacc Person.jj
Java Compiler Compiler Version 5.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file Person.jj . . .
org.javacc.parser.ParseException: Encountered " ";" "; "" at line 33, column 12.
Was expecting one of:
"throws" ...
":" ...

处理成功后类似:

➜  java javacc Person.jj
Java Compiler Compiler Version 5.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file Person.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.

除了生成Person.java文件以外,还会生成其他的辅助类,如ParseException

编译Person.java文件

这应该就很熟悉了

javac Person.java

生成.class文件。大功告成!

执行java文件

命令如下

➜  java java Person '111 + 222'
333

计算结果没毛病!

所以我们编写的语法规则,现在已经可以正常的计算了。

是不是体会到JavaCC的魅力了?

Java的隐秘之JavaCC的更多相关文章

  1. java开源模板引擎

      Velocity  Velocity是一个基于java的模板引擎(template engine).它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义 ...

  2. antlr v4 使用指南连载1——简介

    antlr v4简介        antlr是一个强大语言解析工具,可以用于处理结构化文本.二进制文件.说白了,其实可以这么认为,antlr是一个更强大的正则表达式工具.它可以完成更多正则表达式无法 ...

  3. 从定义到AST及其遍历方式,一文带你搞懂Antlr4

    摘要:本文将首先介绍Antlr4 grammer的定义方式,如何通过Antlr4 grammer生成对应的AST,以及Antlr4 的两种AST遍历方式:Visitor方式和Listener方式. 1 ...

  4. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  5. Java资源大全中文版(Awesome最新版)

    Awesome系列的Java资源整理.awesome-java 就是akullpp发起维护的Java资源列表,内容包括:构建工具.数据库.框架.模板.安全.代码分析.日志.第三方库.书籍.Java 站 ...

  6. Java工程师成神之路

    学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 一.基础篇 1.1 JVM 1.1.1. J ...

  7. 国外程序员整理的Java资源大全分享

    Java 几乎是许多程序员们的入门语言,并且也是世界上非常流行的编程语言.国外程序员 Andreas Kull 在其 Github 上整理了非常优秀的 Java 开发资源,推荐给大家. 译文由 Imp ...

  8. 基于java平台的常用资源整理

    这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...

  9. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

随机推荐

  1. 【C#】Convert.ToInt32、(int)和int.Parse三者的区别

    前者适合将object类类型转换成int类型 (int)适合简单数据类型之间的转换: int.Parse适合将string类类型转换成int类型.

  2. Java笔记(十五) 并发包

    并发包 Java中还有一套并发工具包,位于包java.util.concurrent下,里面包括很多易用 且很多高性能的并发开发工具. 一.原子变量和CAS 为什么需要原子变量,因为对于例如count ...

  3. 用STM32CudeMX 配置用到的函数(记住他!)

    1.设置PB5的电平:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);2.读取PB5的电平值:int a = HAL_GPIO_ReadPin(GPIOB, GPIO_ ...

  4. Error watching file for changes: EMFILE

    运行reactnative项目时在编译过程中报错 Error watching file for changes: EMFILE 故障原因: 是升级后watchman不可用了,需要重装watchman ...

  5. acm--博弈入门1(巴什博弈1)--(HDU 1846 HDU 2049)

    一开始听大佬讲巴什博弈,听成巴士博弈,后来知道了巴什博弈的大名,还知道了博弈不止一种.所谓博弈,就是一场心机的对抗. 好巴什,好巴什......(记得有一个广告语是这么来着) 切入正题: 巴什博弈,问 ...

  6. C++知识点:拷贝构造函数例子

    //拷贝构造函数: //函数参数传递时调用一次拷贝构造函数,给对象赋值时调用一次拷贝构造函数,对象作为参数传递后会被及时销毁. #include <fstream> #include &l ...

  7. Jsp俩大内置对象学习

    https://www.cnblogs.com/smyhvae/p/4065790.html post与get的区别 最直观的区别就是GET把参数包含在URL中,POST通过request body传 ...

  8. Java API实现Hadoop文件系统增删改查

    Java API实现Hadoop文件系统增删改查 Hadoop文件系统可以通过shell命令hadoop fs -xx进行操作,同时也提供了Java编程接口 maven配置 <project x ...

  9. PAT基础6-8

    6-8 简单阶乘计算 (10 分) 本题要求实现一个计算非负整数阶乘的简单函数. 函数接口定义: int Factorial( const int N ); 其中N是用户传入的参数,其值不超过12.如 ...

  10. “百度杯”CTF比赛 九月场---123

    右键查看源代码 然后构造user.php,显示空白,源码也是空白,既然上边说用户名,密码了,参考大佬的博客,放文件user.php.bak这是备份文件,一打开上边全是用户名,有戏,爆破 添加字典,也就 ...