JavaCC使用小结

来源:互联网 发布:ios数组动态添加元素 编辑:程序博客网 时间:2024/05/19 14:39

原文地址:http://blog.csdn.net/bhq2010/article/details/8763920


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、开头:

[java] view plain copy
  1. options  
  2. {  
  3.   JDK_VERSION = "1.5";  
  4.   STATIC = false;  
  5. }  

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

2、主类

[java] view plain copy
  1. PARSER_BEGIN(Sparql)  
  2. package cn.edu.ruc.iir.sparql;  
  3. import cn.edu.ruc.iir.query.*;  
  4. import cn.edu.ruc.iir.query.model.*;  
  5. import cn.edu.ruc.iir.query.util.*;  
  6. import java.text.*;  
  7.   
  8. public class Sparql  
  9. {  
  10.   public static void main(String args []) throws ParseException  
  11.   {  
  12.     Sparql parser = new Sparql(System.in);  
  13.     int res = 0;  
  14.     while (true)  
  15.     {  
  16.       System.out.print("MyRDF >");  
  17.       try  
  18.       {  
  19.         res = parser.one_query();  
  20.         if (res == 0)  
  21.         {}  
  22.         else if (res == 1)  
  23.         {  
  24.           break;  
  25.         }  
  26.         else  
  27.         {  
  28.           System.out.println("Please correct your query.");  
  29.         }  
  30.       }  
  31.       catch (Exception e)  
  32.       {  
  33.         System.out.println("NOK.");  
  34.         System.out.println(e.getMessage());  
  35.         parser.ReInit(System.in);  
  36.       }  
  37.       catch (Error e)  
  38.       {  
  39.         System.out.println("Oops.");  
  40.         System.out.println(e.getMessage());  
  41.         break;  
  42.       }  
  43.     }  
  44.   }  
  45. }  
  46.   
  47. PARSER_END(Sparql)  

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

3、定义词法规则

[java] view plain copy
  1. SKIP :  
  2. {  
  3.   " "  
  4. "\t"  
  5. "\r"  
  6. "\n"  
  7. }  
  8.   
  9. TOKEN : /* OPERATORS */  
  10. {  
  11.   < SELECT :  
  12.     "select"  
  13.   | "SELECT" >  
  14. | < WHERE :  
  15.     "where"  
  16.   | "WHERE" >  
  17. | < OBRACE : "{" >  
  18. | < CBARCE : "}" >  
  19. }  
  20.   
  21. TOKEN :  
  22. {  
  23. < EXIT :  
  24.   | "exit"  
  25.   | "EXIT" >  
  26.  | < UNKNOWN : "?" < KNOWN > >  
  27. | < KNOWN : ([ "<"">""a"-"z""A"-"Z""0"-"9"":""/""_""-""\"""'""~""#" ])+ >  
  28. | < MISSEDP : "[" "]" >  
  29.   
  30. }  

这部分定义词法解析器的规则,SKIP定义要忽略的字符串,TOKEN定义要识别的字符串。注意,不是说先将输入中符合SKIP规则的都去掉再进行解析,那样的话是不科学的,正常的词法解析都不会那么干,实际是顺序处理输入串的过程中,通过“大嘴法”识别尽可能长的子串。如果词法规则有二义性,JavaCC会给出警告,一定不要忽略这些警告。此外,JavaCC只对开头存在二义性的词法给出警告(一个字符可以作为两个词法规则的第一个字符),有些词法上的冲突是需要我们自己去注意的,比如要在词法解析时识别一些关键词,这些关键词同时也符合一般标识符的规则,那么在JavaCC中就要把关键词的定义写在标识符定义之前,写在前面的,JavaCC会优先识别。

4、定义语法规则

JavaCC的语法单元形如这样:

[java] view plain copy
  1. Token subject() :  
  2. {  
  3.   Token token = null;  
  4. }  
  5. {  
  6.   token = < UNKNOWN >  
  7.   {  
  8.     return token;  
  9.   }  
  10. | token = < KNOWN >  
  11.   {  
  12.     Token token1 = token;  
  13.   }  
  14.   (  
  15.   "." token = < KNOWN >  
  16.   {  
  17.     token1.image += "."+ token.image;   
  18.   }  
  19.   )*  
  20.   {  
  21.     return token1;  
  22.   }  
  23. }  
开头是一个声明,包括返回值类型、规则名和一个冒号。对于这样一条语法规则,JavaCC就会在语法分析器类中生成一个同名的方法。紧接着的一对花括号中写一些变量声明。下一对花括号中写该规则的具体内容。

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

0 0
原创粉丝点击