ANTLR隨筆(二)


安裝ANTLR

作者的電腦是MAC的操作系統macOS Catalina 10.15.2。

安裝步驟后linux操作的系統的一樣, Windows系統大致步驟一樣,但是環境變量等配置有差別,作者很久沒使用過win系統,只能基於MAC的系統介紹了。

環境准備

ANLTR是用JAVA編寫的,需要先安裝好JAVA,需要的JAVA版本是1.6以上。相信看這篇文章的各位同學電腦上應該都有安裝JAVA。😊

下載ANTLR

使用ANTLR的功能其實很簡單, 下載一個ANTLR的jar包即可。
官方下載地址

配置

最后一步配置環境變量,方便后面在命令行操作ANTLR
打開環境變量文件,作者安裝的是zsh,所以編輯~/.zshrc文件,各位同學應該也清楚環境變量的配置,在文件加入幾行:

export CLASSPATH=".:/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH"  #設置antlr的jar包到環境變量
alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.Tool'  #快速運行ANTLR的解釋器
alias grun='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.gui.TestRig' #快速運行ANTLR測試工具

完成上面的准備工作就可以開始體驗ANTLR的強大功能了

第一個語法解釋器

下面用一個簡單的例子展示ANTLR的使用,編譯一個最簡單的賦值語句的語法。

編寫g4文件

新建一個Hello.g4的文件,這個文件是針對語法的描述,相當於告訴ANTLR我的語法規范

Hello.g4內容如下:

 grammar Hello;  //定義一個名為 Hello 的語法
 statement: ID '=' NUM; //匹配類似 a=1 age=100 這樣的語句
 ID: [a-z]+;   // 定義了一個詞法 ID,由小寫字母組成
 NUM:[0-9]+; // 定義了一個詞法 NUM,由數字組成
 WS: [ \t\r\n]+ -> skip;  //在進行解析的過程中,忽略掉空格,換行

這樣其實就定義好了一個簡單語法。
對於不同的程序語言來說,語法結構越是復雜,想對應的g4文件也會越復雜
這個項目里面有針對目前流行的語言的ANTLR語法定義文件
各位同學可以找找接觸過哪些,看看你用的語言復雜不復雜。反正JAVA文件是很復雜💔

生成解釋器

生成ANTLR的解釋器很簡單,一條命令搞定。

antlr4 Hello.g4

運行完這條命令會生成如下幾個文件:

Hello.interp
Hello.tokens
HelloBaseListener.java
HelloLexer.interp
HelloLexer.java
HelloLexer.tokens
HelloListener.java
HelloParser.java
  • HelloParser.java

    該文件包含一個語法解釋器類的定義,負責識別我們定義的語法

public class HelloParser extends Parser { ... }
  • HelloLexer.java

    該文件包含一個詞法解釋器類的定義,負責自動識別我們定義的語法中的文法規則和詞法規則。

public class HelloLexer extends Lexer { ... }
  • HelloListener.java和HelloBaseListener.java

    這兩個類都是事件監聽類,是留給開發者自己來定義相應的事件。因為ANTLR在進行遍歷解析時,遍歷器會觸發一系列的事件。 比如進入某某標簽,讀到一個數字等。ANTLR開放了這些接口,開發者通過實現這些事件可以做到除了解釋語法以外更復雜的功能。這里就不詳細解釋,后面會再介紹。先挖個坑😊

public interface HelloListener extends ParseTreeListener {
	/**
	 * Enter a parse tree produced by {@link HelloParser#statement}.
	 * @param ctx the parse tree
	 */
	void enterStatement(HelloParser.StatementContext ctx);
	/**
	 * Exit a parse tree produced by {@link HelloParser#statement}.
	 * @param ctx the parse tree
	 */
	void exitStatement(HelloParser.StatementContext ctx);
}
  • 其他非java文件

    ANTLR會給每個定義的詞法符號指定一個數字形式的類型,然后將對應關系存儲在這些文件中。當不同的語法有相同的詞時這個文件就有大作用了。

測試解釋器

最后到了驗收結果的時候,測試一下ANTLR的語法解釋器做了什么。下面會展示兩種測試方式。

JAVA代碼
  1. 將前面生成的4個JAVA文件添加到一個測試工程內,該工程需要引入ANTLR依賴。
<dependency>
    <groupId>org.antlr</groupId>
    <artifactId>antlr4</artifactId>
    <version>4.7.1</version>
</dependency>
  1. 編寫相關測試代碼
public static void main(String[] args) {
        HelloLexer lexer = new HelloLexer(CharStreams.fromString("a = 1"));
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        HelloParser parser = new HelloParser(tokenStream);
        System.out.println(parser.statement().toStringTree(parser));
    }
  1. 運行后會有如下輸入:
    (statement a = 1)
    這個代碼ANTLR成功識別到了我們的賦值語句。
命令行

ANTLR也提供了自動的測試工具,可以直接在命令行測試。詳細用法如下

  1. 編譯java代碼,就跟一般的java代碼一樣我們需要同javac把java文件編譯成class文件。
javac *.java
  1. 使用ANTLR測試工具,輸入如下命令
grun Hello statement -gui

Hello 對應我們定義的語法 grammar Hello
statement 對應我們定義的詞法 statement: ID '=' NUM;
-gui 表示輸出圖形界面

  1. 進入測試工具后,輸入a = 1。 MAC電腦結束輸入符號 control+D。
$ grun Hello statement -gui                                 
a = 1
^D

ANTLR會輸出圖形界面

可以看到ANTLR最終解釋出來的語法樹。

總結

這篇文章帶大家完成了第一個ANTLR的語法文件,並展示了測試過程。中間有一些細節沒有在這里仔細講解,在后面的筆記會陸續更新。最后附上一個稍微復雜一點的語法樹的圖。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM