JavaCC使用小结

项目中用的JavaCC做查询编译,在这里小结一下,作为备忘。

JavaCC是一个很不错的词法、语法解析器的生成器,只需要编写规则就可以生成Java语言的词法、语法解析器(新版本的JavaCC还支持C/C++作为目标语言)。JavaCC相当与Yacc/Bison+Lex/Flex很类似。

[引用请注明出处:http://blog.csdn.net/bhq2010/article/details/8763920]

JavaCC首页:

http://javacc.java.net/

在首页上下载的JavaCC是最新版的,使用方法和Bison一样,在命令提示符或者终端中执行、获得生成的结果。

也可已用javacc eclipse插件:

http://sourceforge.net/projects/eclipse-javacc/files/

下载插件、解压之后,把plugins和features目录下的文件分别拷贝到eclipse的相应目录中即可。

不论哪种方式,所需编写的规则都是一样的。

通过JavaCC自带的example和文档其实就可以上手了,下面就简单小结一下:

词法和语法规则都写在一个.jj的文件中。这个文件应该这样写:

1、开头:

 

options

{

  JDK_VERSION = "1.5";

  STATIC = false;

}


这个放在.jj文件的开头,JDK_VERSION是所生成代码适用的Jdk版本,1.5、1.6、1.7都可以,STATIC指示是否生成静态的解析器类,还有其他选项,参考文档。

 

2、主类

 

PARSER_BEGIN(Sparql)

package cn.edu.ruc.iir.sparql;

import cn.edu.ruc.iir.query.*;

import cn.edu.ruc.iir.query.model.*;

import cn.edu.ruc.iir.query.util.*;

import java.text.*;



public class Sparql

{

  public static void main(String args []) throws ParseException

  {

    Sparql parser = new Sparql(System.in);

    int res = 0;

    while (true)

    {

      System.out.print("MyRDF >");

      try

      {

        res = parser.one_query();

        if (res == 0)

        {}

        else if (res == 1)

        {

          break;

        }

        else

        {

          System.out.println("Please correct your query.");

        }

      }

      catch (Exception e)

      {

        System.out.println("NOK.");

        System.out.println(e.getMessage());

        parser.ReInit(System.in);

      }

      catch (Error e)

      {

        System.out.println("Oops.");

        System.out.println(e.getMessage());

        break;

      }

    }

  }

}



PARSER_END(Sparql)


在PARSER_BEGIN和PARSER_END之间定义语法解析器的主类,这是整个解析程序的入口,里面主要有一些引用的包和类以及一个main方法(其他的方法由JavaCC生成)。由于上面把STATIC设为false了,所这这里需要创建一个parser对象,调用一次parser.one_query()就进行一条语句的解析并获得解析的结果。

 

3、定义词法规则

 

SKIP :

{

  " "

| "\t"

| "\r"

| "\n"

}



TOKEN : /* OPERATORS */

{

  < SELECT :

    "select"

  | "SELECT" >

| < WHERE :

    "where"

  | "WHERE" >

| < OBRACE : "{" >

| < CBARCE : "}" >

}



TOKEN :

{

  < UNKNOWN : "?" < KNOWN > >

| < KNOWN : ([ "<", ">", "a"-"z", "A"-"Z", "0"-"9", ":", "/", "_", "-", "\"", "'", "~", "#" ])+ >

| < MISSEDP : "[" "]" >

| < EXIT :

    "exit"

  | "EXIT" >

}


这部分定义词法解析器的规则,SKIP定义要忽略的字符串,TOKEN定义要识别的字符串。注意,不是说先将输入中符合SKIP规则的都去掉再进行解析,那样的话是不科学的,正常的词法解析都不会那么干,实际是顺序处理输入串的过程中,通过“大嘴法”识别尽可能长的子串。如果词法规则有二义性,JavaCC会给出警告,一定不要忽略这些警告。

 

4、定义语法规则

JavaCC的语法单元形如这样:

 

Token subject() :

{

  Token token = null;

}

{

  token = < UNKNOWN >

  {

    return token;

  }

| token = < KNOWN >

  {

    Token token1 = token;

  }

  (

  "." token = < KNOWN >

  {

    token1.image += "."+ token.image; 

  }

  )*

  {

    return token1;

  }

}

开头是一个声明,包括返回值类型、规则名和一个冒号。对于这样一条语法规则,JavaCC就会在语法分析器类中生成一个同名的方法。紧接着的一对花括号中写一些变量声明。下一对花括号中写该规则的具体内容。

 

一个语法单元中有多个规则时,用|分开。每个规则都有一系列词法或语法单元组成,每个词法或者语法单元之后跟着一对花括号,里面写处理的代码

基本上就是这样了。

 

你可能感兴趣的:(javac)