ANTLR使ってみたよ

ANTLRっていうパーサジェネレータ使ってみた。
ANT(i)LR の意味も含んであるらしい(wiki)。
プリプロセッサを考えてみようかなって思って、ちょっと触ってみた。

環境

Intelli J idea UE
ANTLR v4 4.7.1
gradle 4.9
java 10

環境設定

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のプラグインがあります。

plugins.jetbrains.com

これも入れる。
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に入力したのを解析してグラフにしてくれる。

f:id:b1u3:20180813095353p:plain

他は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 での書き方。

問題点

文法ファイルの書式がイマイチなのでよくわかんないのと、いい書き方みたいのがまだわかんないからそこらへんを調べてみたい。