官網鏈接: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_BEGIN
到PARSER_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的魅力了?😊