ANTLR使ってみたよ
ANTLRっていうパーサジェネレータ使ってみた。
ANT(i)LR の意味も含んであるらしい(wiki)。
プリプロセッサを考えてみようかなって思って、ちょっと触ってみた。
環境設定
gradleのantlrのプラグインがあるので、そいつを入れる。
// build.gradle apply plugin : 'antlr'
ライブラリの追加
dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' antlr "org.antlr:antlr4:4.7.1" }
testCompileは使わないので、入れなくてもどちらでもいいです。
Intelli J のプラグインのANTLRv4のプラグインがあります。
これも入れる。
OS X ならpreference->pluginの検索タブからANTLRを入力してリポジトリからインストール。これを入れるとシンタックスハイライトとリアルタイムツリープレビューができる。
試し書き
gradleのプラグインを入れるとsrc/mainにantlrというフォルダができる。ここに、g4という拡張子のファイルを置く。
今回はLang.g4というファイルを作ってみた。
以下、Lang.g4
grammar Lang; /* @header { package sample ; } */ /* * Parser Rules */ input : stmt+ EOF ; stmt : ((assign | expr) (STMTSEP stmt)? NEWLINE?) | NEWLINE | STMTSEP ; assign : ID EQUAL (assign | expr) ; expr : ((ID | INTEGER) (unop expr)?) ; unop : (PLUS | MINUS | STAR | DIV) ; /* * Lexer Rules */ fragment LOWERCASE : [a-z] ; fragment UPPERCASE : [A-Z] ; fragment DIGIT : [0-9] ; ID : (LOWERCASE | UPPERCASE | '_')+ ; INTEGER : ('+' | '-')? DIGIT+ ; SPACE : (' ' | '¥t' | ',' | '¥n') -> skip ; EQUAL : '=' ; MINUS : '-' ; PLUS : '+' ; STAR : '*' ; DIV : '/' ; NEWLINE : ('¥r'? '¥n') | '¥r' ; STMTSEP : ';' ;
Intelli J のプラグインを入れておくと、ウィンドウ下にpreviewというタブがでる。
エディターのパーサールールの名前のところで右クリック->Test Rule XXをクリックするとpreviewに入力したのを解析してグラフにしてくれる。
他はIntelli J のターミナルプラグインを用いて、以下をbuild.gradleに追加して、runする。
apply plugin: 'application' ... mainClassName = "org.antlr.v4.gui.TestRig" ... //gradle 4.8 以下のためのコマンドライン引数を渡す処理 run{ standardInput = System.in if(project.hasProperty("args")){ //スペースで分割 args project.args.split(" ") } }
実行。
gui出力。
% gradle run --args "Lang input --gui" % gradle run --Pargs="Lang input --gui"
コンソール出力。
% gradle run --args "Lang input --tokens" % gradle run --Pargs="Lang input --tokens"
gradle 4.8 以下と 4.9 での書き方。
問題点
文法ファイルの書式がイマイチなのでよくわかんないのと、いい書き方みたいのがまだわかんないからそこらへんを調べてみたい。