Antlr (ANother Tool for Language Recognition) 是一款強大的語法分析器生成工具,可用於讀取、處理、執行和翻譯結構化的文本或者二進制文件。它被廣泛應用於學術領域和工業生產實踐,是衆多語言、工具和框架的基石。我們可以使用Antlr來開發DSL(Domain Specific Language,領域特定語言),或者一些實用工具,比如配置文件讀取器、遺留代碼轉換器和Json解析器等等。
作爲Antlr入門的第一章,我們的目標是大體上知道Antlr能做什麼。爲此,我們需要先安裝Antlr,並編寫運行我們的第一個程序“Hello World”.
1. 安裝Antlr插件
打開IDEA,在File—Settings—Plugins中,安裝ANTLR v4 grammar plugin插件。
2. 第一個項目—“Hello World”
新建一個Maven項目,在pom文件中添加如下依賴:
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.8-1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.8-1</version>
<executions>
<execution>
<id>antlr</id>
<goals>
<goal>antlr4</goal>
</goals>
<phase>none</phase>
</execution>
</executions>
<configuration>
<outputDirectory>src/test/java</outputDirectory>
<listener>true</listener>
<treatWarningsAsErrors>true</treatWarningsAsErrors>
</configuration>
</plugin>
</plugins>
</build>
新建一個.g4文件,用來編寫要識別語言的詞法規則和語法規則,比如這裏我們的文件名爲Hello.g4
grammar Hello; // 定義一個名爲Hello的語法,名字與文件名一致
r : 'Hello' ID // 定義一個r規則,匹配一個關鍵字Hello和緊隨其後的標識符ID
| 'hello' ID; // "|"是備選分支的分隔符
ID : [a-z]+; // 定義ID標識符,由小寫字符組成
WS : [ \t\r\n]+ -> skip; // 忽略空格、Tab、換行以及\r (Windows)
然後我們就可以使用Antlr工具來將該語法文件轉換成可以識別該語法文件所描述語言的程序。這句話有點拗口,舉個例子來說的話,就是給定一個識別JSON的語法,antlr工具將會根據該語法生成一個程序,此程序可以通過antlr運行庫來識別輸入的JSON,即輸入的字符串是否符合JSON格式。
不過在此之前,我們需要先配置下生成的程序輸出路徑,右鍵Hello.g4,找到Configure ANTLR
接着配置文件的輸出路徑和目錄
接着我們就可以使用antlr工具來將語法文件轉換成可以識別該語法文件所描述語言的程序了。
右鍵Hello.g4,點擊Generate ANTLR Recognizer,接着可以看到目錄下面生成了許多文件
其中HelloLexer是詞法分析器,HelloParser是語法分析器,HelloVistor和HelloListener是兩種遍歷樹的機制,分別是訪問者模式和監聽器模式。有關Antlr概念與術語的部分,我們第二章在講,這裏瞭解個大概就行。
最後,我們就可以來編寫主程序來調用上訴代碼了。
import hello.HelloLexer;
import hello.HelloParser;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
public class HelloMain {
public static void run(String expr) throws Exception{
// 對每一個輸入的字符串,構造一個 ANTLRStringStream 流 in
ANTLRInputStream input = new ANTLRInputStream(expr);
// 用 in 構造詞法分析器 lexer,詞法分析的作用是將字符聚集成單詞或者符號
HelloLexer lexer = new HelloLexer(input);
// 用詞法分析器 lexer 構造一個記號流 tokens
CommonTokenStream tokens = new CommonTokenStream(lexer);
// 再使用 tokens 構造語法分析器 parser,至此已經完成詞法分析和語法分析的準備工作
HelloParser parser = new HelloParser(tokens);
// 最終調用語法分析器的規則 r(這個是我們在Hello.g4裏面定義的那個規則),完成對錶達式的驗證
parser.r();
}
public static void main(String[] args) throws Exception{
String[] testStr={
"Hello world",
"hello world",
"hi world"
};
for(String s : testStr){
System.out.println("Input: " + s);
run(s);
}
}
}
最後運行結果如下:
除了以上方式,我們還可以使用文法可視化工具來測試語法規則
- 在Hello.g4中選擇一個語法規則比如r,右鍵選擇Test Rule r
- 在ANTLR Preview中輸入要校驗的文本,比如hello world
右邊我們就可以看到生成的語法分析樹