ANTLR(1)
compilercompilerを勉強中。bison, JavaCCくらいしか使ったことがないので、流行りのANTLRを。
めもめも。
開発環境の起動
- > java -jar antlrworks-1.y.z.jar
- とりあえず1.1.3で確認
- 拡張子の設定してあればダブルクリックでも。
初期設定
- File > Preferences
- General Tab > Output path: Same as grammar
出力先を選べる。面倒なので構文ファイルと同じところへ。
サンプル
- File > New
- 次のコードを追加
// Chapter 1, p11 grammar T; @header { package introduction; } @lexer::header { package introduction; } // Parser r : 'call' ID ';' EOF { System.out.println("invoke " + $ID.text); } ; // Lexer ID : ('a'..'z')+ ; WS : (' '|'\n'|'\r')+ { $channel = HIDDEN; } ;
- 先頭に grammar
;。今回は言語Tを作る - @headerで生成されるParserの先頭にコードを追加。
- @lexer::headerで生成されるLexerの先頭にコードを追加。
- 記法はyacc-likeにBNF+属性なイメージ
: { } | { } | ... | { } ;
- ルール名を大文字で始めるとLexerルール扱い。この単位でトークンを作る
- 文字チャネルをトークンチャネルに変換して、パーサはそれを利用する形式みたい。
- アクション内で $channel = HIDDEN; と書くと、このトークンはスキップされるトークンとして扱われる。ルールWSはスペースや改行文字をトークンチャンネルから消す処理(空白スキップ)
- ルール名を小文字で始めるとParserルール扱い。トークン先読みができる。
- アクション内で $
.text と書くと、トークン文字列を使える。
- アクション内で $
- EOFは暗黙のLexerルールで、たぶんファイル終端。
- File > Save As
- ~/antlr/introduction/T.g (任意)
Parser/Lexerの生成
- Generate > Generate Code
- ~/antlr/introduction/build/T.tokens
- トークン一覧
- ~/antlr/introduction/build/T__.g
- lexer文法
- ~/antlr/introduction/build/TLexer.java
- lexer
- ~/antlr/introduction/build/TParser.java
- parser
- ~/antlr/introduction/build/T.tokens
利用したプログラム
- introduction/T.java
public class TTest { public static void main(String[] args) throws IOException, RecognitionException { ANTLRInputStream in = new ANTLRInputStream(System.in, "UTF-8"); TLexer lexer = new TLexer(in); CommonTokenStream tokens = new CommonTokenStream(lexer); TParser parser = new TParser(tokens); parser.r(); } }
- ANTLR本体に含まれるantlr-runtime-3.0.x.jarをパスに追加しておく
- 文字ストリームは java.io.Reader ではなく org.antlr.runtime.CharStream を使う
- org.antlr.runtime.ANTLRInputStream は CharStream の子孫
- CharStream は look-ahead や rewind などの機能を持ってる
- TLexer extends org.antlr.runtime.Lexer
- lexerはトークンマネージャではなく、単にトークンソースとして扱われる。org.antlr.runtime.Lexer implements org.antlr.runtime.TokenSource
- TParser extends org.antlr.Parser
- トークンストリームは org.antlr.runtime.CommonTokenStream をかぶせた TLexer を渡す。
- char-stream -> (token source) -> tokens -> (token stream) -> (parser) な感じ
- TParser#ルール名 で開始 (parser.r())。
実行
- EOFをEclipseで送る方法がわからん…
> echo call hoge; \ | java -cp bin;lib\antlr-runtime-3.0.1.jar introduction.TTest invoke hoge