0. はじめに
ANTLRを使って少し構文解析を行いましたので、備忘録として記事にしてみました。
1. ANTLRとは
アントラーと読みます。
構文解析を行うためのツールになります。
解析のためのルールを記述する**grammar(グラマー)をいうファイルを作成することで、与えられたテキストをそのルールに応じて振り分けすることができます。
グラマーはlexer(レクサー)とparser(パーサー)**という文法を使って記述します。
以下は公式サイトのサンプルgrammarファイルになります。
grammar Expr;
/**
* parser
*/
prog: (expr NEWLINE)* ;
expr: expr ('*'|'/') expr
| expr ('+'|'-') expr
| INT
| '(' expr ')'
;
/**
* lexer
*/
NEWLINE : [\r\n]+ ;
INT : [0-9]+ ;
1-1. lexer
- lexerとは、字句解析器になります。
- 正規表現を使って「この変数にはこんな値が入るよ」を定義します。
- 上記サンプルgrammarファイルの「lexer」部分になります。
1-2. parser
- parserとは、構文解析器になります。
- 「解析する構文はこんな感じで振り分けるよ」を定義します。
- 上記サンプルgrammarファイルの「parser」部分になります。
2. 環境構築
※VSCodeはインストールされている前提とさせて頂きます。
VSCodeに、神拡張機能であるANTLR4 grammar syntax supportをぶち込みます。
元々環境構築やデバッグが少し手間だったのですが、これを使えばめちゃくちゃ楽になります。
自分が使った機能としては、以下のようなものがあります。
- シンタックスハイライト機能
- デバッグ機能(構文解析結果がイメージで確認できる)
- 言語に応じたジェネレート機能
他にもたくさんのことができるようです。詳しくはvscode-antlr4をご参照ください。
3. グラマーファイルを作成する
それでは、グラマーファイルを作成していきます。
lexerとparser、1ファイルで書くことも、別々のファイルで書くこともできますが、当記事では1ファイルで書いています。
そして今回は子供達にも喜んでもらえるよう、きめつちっくな構文を解析してみます。
| 入力文字列(例) | | 種別 | 番号 | 名前 | オプション |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 水の呼吸拾壱の型凪 | | 水 | 拾壱 | 凪 | - |
| 雷の呼吸壱の型霹靂一閃(六連) | | 雷 | 壱 | 霹靂一閃 | 六連 |
「入力文字列」を与えることで、「種別」「番号」「名前」「オプション」として解析できるようにします。
オプションてなんやねんて感じですが、六連なのか八連なのか神速なのか、名前だけでは情報が不足する場合もあるので。。。
結果、グラマーファイルは以下のように書いてみました。
grammar Breathing;
/**
* parser
*/
breathing :
// [TYPE]の呼吸[NUM]の型[NAME]([OPTION])
type '\u306e\u547c\u5438' num '\u306e\u578b' name ('('option')')?
;
type :
TYPE
;
name :
(ANY)+
;
num :
NUMBER
;
option :
(NUMBER | ANY)+
;
/**
* lexer
*/
TYPE :
// 水炎雷風岩蟲花恋蛇音獣月日
[\u6c34\u708e\u96f7\u98a8\u5ca9\u87f2\u82b1\u604b\u86c7\u97f3\u7363\u6708\u65e5]
;
NUMBER :
// 壱弐参四五六七八九拾
[\u58f1\u5f10\u53c2\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u62fe]+
;
ANY :
.
;
4. テキストを与えてデバッグしてみる
4-1. launch.jsonを作成
.vscode
フォルダ配下に、launch.json
ファイルを作成し、以下のように記載します。
{
"version": "1.0.0",
"configurations": [
{
"name": "Debug ANTLR4 grammar", // 任意の名前
"type": "antlr-debug", // 決め打ち(多分)
"request": "launch", // 決め打ち(多分)
"input": "input.txt", // 入力となるテキストを記述したファイル
"grammar": "Breathing.g4", // 使用するグラマーファイル
"printParseTree": true, // デバッグ結果をデバッグコンソールに表示するか
"visualParseTree": true // デバッグ結果をグラフィカルなツリーで表示するか
},
]
}
4-2. デバッグ実行①
input.txt
に、以下を入力して、VSCodeでデバッグ実行します。
水の呼吸拾壱の型凪
以下のような実行結果になればOK!
4-3. デバッグ実行②
input.txt
に、以下を入力して、VSCodeでデバッグ実行します。
雷の呼吸壱の型霹靂一閃(六連)
以下のような実行結果になればOK!
5. プログラミング言語に合わせたコードを出力する
5-1. settings.jsonを作成
.vscode
フォルダ配下に、settings.json
ファイルを作成し、以下のように記載します。
なお、他にも色々な設定することができます。詳しくはvscode-antlr4(extension-settings)をご参照ください。
{
"antlr4.generation":{
"mode": "external", // 決め打ち(多分)
"language": "CSharp", // 出力したいプログラミング言語名
"listeners": true, // listener形式で出力するか
"visitors": false, // visitor形式で出力するか
"alternativeJar": "antlr-4.9-complete.jar", // ANTLRのjarファイル(※)
"outputDir": "parser" // 出力先のフォルダ名
}
}
(※)ANTLRのバージョンを指定したい場合に設定します。指定しないと4.8で出力されます。ANTLRの各バージョンのjarはこちらからダウンロードできます。
5-2. コードを出力する
グラマーファイルを保存(Ctrl + s)すれば、outputDir
で指定したフォルダにコードが生成されます。
6. GitHub
7. おわりに
個人的に普段は使わないような技術なので、新鮮な気持ちで取り組むことができました
当技術をピンポイントで使うことはあまりないかもしれませんが、何かしらに応用できればと思います
8. 参考