---
tags: 開發環境, ANTLR 4, C#
---
# ANTLR 4開發環境設置
ANTLR (**AN**other **T**ool for **L**anguage **R**ecognition)是用來做語法解析的工具,可產生的解析器語言支援Java、C#、Python、JavaScript、Go、C++、Swift、PHP,本篇介紹的是C#的部分。
## Java安裝
ANTLR是用Java開發的,所以必須先安裝Java,我使用的是[AdoptOpenJDK][link-1],OpenJDK 8 (LTS) - HotSpot的版本。
1. 將下載的檔案解壓縮到C槽。
2. 在環境變數`path`加入`C:\jdk8u242-b08\bin`。
完成以上步驟可在終端機輸入`java -version`確認是否設置成功。
![Java check][img-1]
[link-1]: https://adoptopenjdk.net/
## ANTLR 4安裝
1. 到[ANTLR官網][link-2]下載`antlr-4.8-complete.jar`並儲存到`C:\jdk8u242-b08\lib`。
2. 在環境變數`CLASSPATH`加入
`.;C:\jdk8u242-b08\lib\antlr-4.8-complete.jar;%CLASSPATH%`。
3. 在`C:\jdk8u242-b08\bin`建立一個`antlr4.bat`檔案,內容為
`java org.antlr.v4.Tool %*`。
4. 在`C:\jdk8u242-b08\bin`建立一個`grun.bat`檔案,內容為
`java org.antlr.v4.gui.TestRig %*`。
完成以上步驟可在終端機輸入`antlr4`確認是否設置成功。
![ANTLR4 check][img-2]
[link-2]: https://www.antlr.org/download.html
## Visual Studio Code設置
### 環境設置
1. 安裝ANTLR4 grammar syntax support擴充套件。
![ANTLR4 grammar syntax support][img-3]
2. 在`settings.json`加入以下設定。
```json
"antlr4.generation": {
"mode": "external",
"outputDir": "antlr4-runtime", //產生的解析器檔案存放的資料夾
"language": "CSharp", //產生的解析器語言
"listeners": false,
"visitors": true
}
```
### ANTLR專案設置
1. 在`launch.json`的`configurations`加入以下設定。
```json
{
"name": "Debug ANTLR4",
"type": "antlr-debug",
"request": "launch",
"input": "input.txt", //要解析的檔案
"startRule": "expr", //起始規則
"printParseTree": true, //編譯後顯示文字樹狀圖
"visualParseTree": false //編譯後顯示圖形樹狀圖
}
```
2. 建立ANTLR的解析規則檔,副檔名為`.g4`,並在第一行加入`grammar 檔名;`。
例如:檔名為`Hello.g4`,則此檔案第一行為`grammar Hello;`。
ANTLR基本語法:`規則名稱 : 規則內容1 | 規則內容2 ;`
規則名稱第一個字母小寫為parser,大寫為lexer。
## Visual Studio C#專案設置
1. 從NuGet安裝Antlr4.Runtime.Standard套件。
![Antlr4.Runtime.Standard][img-4]
2. 將ANTLR產生的四支`.cs`檔複製到C#專案裡。
3. 加入using命名空間指示詞。
```csharp
using Antlr4.Runtime;
using Antlr4.Runtime.Tree;
```
加入以下程式碼可開始解析。
```csharp
ICharStream stream = CharStreams.fromPath(openFileDialog1.FileName);
ITokenSource lexer = new HelloLexer(stream);
ITokenStream tokens = new CommonTokenStream(lexer);
HelloParser parser = new HelloParser(tokens);
IParseTree tree = parser.expr();
HelloVisitor visitor = new HelloVisitor();
visitor.Visit(tree);
```
如果要在某些解析規則中做一些處理,需先加入以下class,然後才在這個class裡加入要處理的function。
```csharp
public class HelloVisitor : HelloBaseVisitor<object>
{
function1() {...}
function2() {...}
}
```
要處理的function是從`HelloVisitor.cs`找出和ANTLR規則名稱相對應的function後修改而成。
例如:`Result VisitExpr([NotNull] HelloParser.ExprContext context);`
function長相:
```csharp
public override object VisitExpr(HelloParser.ExprContext context)
{
do things...
return VisitChildren(context);
}
```
---
**參考資料**
[ANTLR官網](https://www.antlr.org/)
[作者GitHub](https://github.com/antlr/antlr4/tree/master/doc)
[The ANTLR Mega Tutorial](https://tomassetti.me/antlr-mega-tutorial/)
[img-1]: https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoQhugoCZZEsJoM-ywUhfd_C_HL9hkgwbL4-s_X6ltqJduyg2gsiYBoTr4DnQJXmmY8ziCI-nf_D2qijK11sQSXDmCJT4shR4QiXok8CvMxdU62PuB35fJu4qW2xCBgmY0FOEmfEiV6IdogIWiiYa_gwbB56VJidPOPwywBZm3M6NI-iH0uEJ38uBDZEjv/s1600/01_java-check.png
[img-2]: https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghx7WNoMIQK7H06hGFYg-3juXpPILZJiuo9R7a8678SMpxZibjiGw4ICew4Qil_H6sKwGXfBKclvNpMHTwU8SH1bZBgeZRUVjJ_rwjPx05R0AHijHQPAJXhvRrXs76Eu0LvYrq-YCZd8EEgMcGSHHmEIhBvw4p6Tus5IvS8qOzAQ7dDa4Ze7f6WZYWGbpE/s1600/02_antlr4-check.png
[img-3]: https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZcwJzCRJT3qHvYftMRAnu29Ne0dzhTBMZqpCjFqKelpObNPmkXD2GciXx87U4XOktnVV-MphgkTrqyNoS7wTCmVAo13qBW7pwJ0f-CaMZFG9qdgIwldLhuqazFSPugBGgT3Jl5_rqMeyHVIXNyUmWlZsjDk1J28p0sJokCxHqsq7Rb38ZvCmMaDia4LdL/s1600/03_antlr4-grammar-syntax-support.png
[img-4]: https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_WAN4T8xIehmaUuIiMfMThswUrgkwt_K8PF0m7P42h1vAEi06WWdWEQ423qE5bzdZ2j6ZY2k2TaKMMR3vYGQ_q6UGCis-ydRtoOarlBiFaySNJiNfzgP1xE4zK2KjuFJW92zzpXr67GtYMa0u9kHJJ1mxMwgvxLNb1NIqf-s_Ozxs2p-5Ru_6px7KBYpX/s1600/04_antlr4-runtime-standard.png