Java的隱祕之JavaCC

官網連接:JavaCCjava

JavaCC


JavaCC是Java的解析器生成器兼掃描器生成器。爲JavaCC描述好語法的規則,JavaCC就可以生成能夠解析該語法的掃描器和解析器(的代碼)了。多線程

JavaCC是LL解析器生成器,所以比起LR解析器生成器和LALR解析器生成器,它有着可處理語法的範圍相對狹哉的缺點。函數

可是,JavaCC生成的解析器有易於理解,易於使用的優點。且支持無限長的token超前掃描特性,因此速度很是的快。lua

巨坑


我爲何要把坑寫在前面?由於這真的是太坑了!線程

一開始我下載的是官網的javacc-6.0,配置好環境變量後仍是一隻報錯:code

找不到或者沒法加載主類 javaccblog

沒錯,官網的6.0版本有問題!因而使用javacc-5.0就行了。token

具體參考:getting-started-with-javaccget

編寫語法描述文件


語法描述文件一般會使用.jj的後綴文件it

語法描述文件的經常使用形式

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的魅力了?😊

相關文章
相關標籤/搜索