antlr4官網:http://www.antlr.org
antlr3官網:http://www.antlr3.org
剛剛成功實現從java程序中調用antlr生成的語法文件。特此記錄下。
首先需要一個php的文法文件:
https://code.google.com/p/phpparser
發現這個Php.g不能使用antlr v4編譯,下載v3的antlrworks,發現一調試一堆錯誤,很多類似
[20:04:04] E:\output\PhpParser.java:10655: 錯誤: 需要<標識符>
[20:04:04] public final void synpred23_Php_fragment() throws {
的錯誤,不明原因。
那就不要IDE了,直接下載
http://www.antlr3.org/download.html -> Complete ANTLR 3.5 Java binaries jar
里面已經包括了java的runtime。(如果使用其他語言還需要下載那個語言的runtime)
python:(需先下載python的runtime,然后安裝他,注意python的版本得根據runtime的版本,antlr_python_runtime-3.1.3這個只能支持python2.4 2.5啊。)
http://www.antlr.org/wiki/display/ANTLR3/Antlr3PythonTarget
支持的python版本太低了,新版antlr4里面runtime又只有java的,那就用java把。
下面是一個簡單例子的完整步驟。
1. 下載 antlr-3.5-complete.jar
2. 放在隨便一個目錄,比如D:/antlr/
3. 添加環境變量classpath。在后面追加 D:\antlr\antlr-3.5-complete.jar;
4. 命令行輸入 java org.antlr.Tool ,會打印出參數列表,表示antlr的命令可用了。
5. 新建一個目錄,新建一個文件命名為:E.g 內容為:
grammar E; options{ output=AST; } program : statement + ; statement: (expression | VAR '=' expression) ';' ; expression : (multExpr (('+' |'-' ) multExpr)*) | STRING; multExpr : atom ('*' atom)*; atom : INT | '(' expression ')'; VAR : ('a'..'z' |'A'..'Z' )+ ; INT : '0'..'9' + ; STRING : '"' (('A'..'Z' | 'a'..'z' | ' ') +) '"' ; WS : (' ' |'\t' |'\n' |'\r' )+ {skip();} ;
這是一個識別算術式子和字符串的文法,下面用antrl生成詞法語法分析的文件。
6. 進入到該文件的目錄,命令行輸入 java org.antlr.Tool E.g ,這時會生成三個文件 E.tokens ELexer.java EParser.java.
7. 接下來需要對生成的java代碼編譯運行,首先需要一個主函數,在該目錄新建一個文件命名為 run.java。輸入內容:
import org.antlr.runtime.*; import org.antlr.runtime.tree.*; public class run { public static void main(String[] args) throws Exception { ANTLRInputStream input = new ANTLRInputStream(System.in); ELexer lexer = new ELexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); EParser parser = new EParser(tokens); EParser.program_return r = parser.program(); System.out.println(((BaseTree)r.getTree()).toStringTree()); } }
這里的parser.program()中program()是我們文法的起點,就是第一條規則的名字,如果不是這個則需要修改,同時.program_return中下划線前面的部分跟隨一起修改。
8. 編譯所有的.java文件。命令行輸入: javac *.java ,生成class文件后,執行run。輸入 java run。此時需要輸入參數,輸入
2+4*5;
str="hello";
^Z
^Z是按Ctrl+Z產生的,表示輸入結束。回車后發現結果
2 + 4 * 5 ; str = "hello";
表示運行成功了,至於為什么打印這個結果是因為run.java里使用了toStringTree(),更多的API可見
http://www.antlr3.org/api/
9. 學習API,更詳細的分析生成的抽象語法樹。
10. over.
補充:Ast樹的簡單遍歷操作
//轉為CommonTree格式,CommonTree類提供一些操作樹的方法供我們使用 CommonTree root = (CommonTree)r.getTree(); //輸出樹的string格式 System.out.println(root.toStringTree()); //獲取節點root的子節點個數 System.out.println(root.getChildCount()); //獲取root的第1個(從0開始)孩子 CommonTree se = (CommonTree) root.getChild(1); //獲取root的第1個(從0開始)孩子的第2個孩子 CommonTree th = (CommonTree) se.getChild(2); //獲取節點 th 的父節點 System.out.println(th.getParent()); //判斷節點 root 是不是根節點 System.out.println(root.isNil()); /*這里只寫出幾個簡單的方法供參考,更多的的請參考 http://www.antlr3.org/api/Java/index.html 查看 Class CommonTree 和 Class BaseTree 的部分*/