JavaCC从入门到出门

1、JavaCC

  JavaCC是java的compiler compiler。JavaCC是LL解析器生成器,可处理的语法范围比较狭窄,但支持无限长的token超前扫描。java

  安装过程:git

  我是从github上down下来的zip压缩包,而后安装了下ant, 而后经过ant安装的javaccgithub

  1. 首先下载下来ant的源码,而后tar -zvxf apache-ant....tag.gz 解压缩,而后能够在解压出来的bin目录中看到ant的可执行文件shell

  2. 从github下载javacc, 进入解压缩的目录执行xxxxxx/ant。 而后会在target 目录中看到javacc.jar 包apache

  3. 这个时候能够经过以下方法将jar包作成一个可执行文件:多线程

    首先建立一个shell脚本:函数

#!/bin/sh
MYSELF=`which "$0" 2>/dev/null`
[ $? -gt 0 -a -f "$0" ] && MYSELF="./$0"
java=java
if test -n "$JAVA_HOME"; then
    java="$JAVA_HOME/bin/java"
fi
exec "$java" $java_args -cp $MYSELF "$@"
exit 1

    命名为stub.sh, 而后在jar包的所在目录执行: cat stub.sh javacc.jar > javacc && chmod +x javacc。 这样一个可执行文件就有了,不过在解析.jj文件时须要带一个javacc的参数,像这样: javacc javacc Adder.jjui

2、语法描述文件

一、简介

  JavaCC的语法描述文件是扩展名为.jj的文件,通常状况下,语法描述文件的内容采用以下形式编码

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

  JavaCC和java同样将解析器的内容定义在单个类中,所以会在PARSER_BEGIN和PARSER_END之间描述这个类的相关内容。lua

二、Example

  以下代码是一个解析正整数加法运算并进行计算的解析器的语法描述文件。

options { STATIC = false; } PARSER_BEGIN(Adder) import java.io.*; class Adder { public static void main(String[] args) { for (String arg : args) { try { System.out.println(evaluate(arg)); } catch (ParseException ex) { System.err.println(ex.getMessage()); } } } public static long evaluate(String src) throws ParseException { Reader reader = new StringReader(src); return new Adder(reader).expr(); } } PARSER_END(Adder) 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的话JavaCC生成的全部成员及方法都将被定义为static,若将STATIC设置为true则所生成的解析器没法在多线程环境下使用,所以该选项老是被设置为false。(STATIC的默认值为true)
  从PARSER_BEING(Adder)到PARSER_END(Adder)是解析器类的定义。解析器类中须要定义的成员和方法也写在这里。为了实现即便只有Adder类也可以运行,这里定义了main函数。
  以后的SKIP和TOKEN部分定义了扫描器。SKIP表示要跳过空格、制表符(tab)和换行符。TOKEN表示扫描整数字符并生成token。
  long expr...开始到最后的部分定义了狭义的解析器。这部分解析token序列并执行某些操做。

三、运行JavaCC

  要用JavaCC来处理Adder.jj(图中是demo1.jj),须要使用以下javacc命令

  运行如上命令会生成Adder.java和其余辅助类。
  要编译生成的Adder.java,只须要javac命令便可:

 

这样就生成了Adder.class文件。Adder类是从命令行参数获取计算式并进行计算的,所以能够以下这样从命令行输入计算式并执行

 

3、启动JavaCC生成的解析器

  如今解析一下main函数的代码。   main函数将全部命令行参数的字符串做为计算对象的算式,依次用evaluate方法进行计算。
  evaluate方法中生成了Adder类的对象实例 。并让Adder对象来计算(解析)参数字符串src。
  要运行JavaCC生成的解析器类,须要下面2个步骤:

  1. 生成解析器类的对象实例
  2. 用生成的对象调用和须要解析的语句同名的方法

  第1点: JavaCC4.0生成的解析器中默认定义有以下四种类型的构造函数。

  1. Parser(InputStream s)
  2. Parser(InputStream s, String encoding)
  3. Parser(Reader r)
  4. Parser(x x x x TokenManager tm)

  第1种的构造函数是经过传入InputStream对象来构造解析的。这个构造函数没法设定输入字符串的编码,所以没法处理中文字符等。
  而地2种的构造函数除了InputStream对象外,还能够设置输入字符串的编码来生成解析器。但若是要解析中文字符串或注释的话,就必须使用第2种/3种构造函数。
  第3种的构造函数用于解析Reader对象所读入的内容。
  第4种是将扫描器做为参数传入。
  解析器生成后,用这个实例调用和须要解析的语法同名的方法。这里调用Adder对象的expr方法,接回开始解析,解析正常结束后会返回语义值。

4、中文的处理

  要使JavaCC可以处理中文首先须要将语法描述文件的options快的UNICODE_INPUT选项设置为true:

options { STATUS = false; DEBUG_PARSER = true; UNICODE_PARSER = true; JDK_VERSION = "1.5"; }

  这样就会先将输入的字符转换成UNICODE后再进行处理。UNICODE_INPUT选项为false时只能处理ASCII范围的字符。  另外还须要使用第2/3种构造方法为输入的字符串设置适当的编码。

相关文章
相关标签/搜索