ANTLR勝手訳-Cheat Sheet-

いきなりCheat Sheetから訳そうという外道な方向で。
原文

訳すに当たって参考にしたページとか

以下は訳

grammar T;
def : modifier+ 'int' ID '=' INT ';'
    | modifier+ 'int' ID ';'
    ;
modifier : 'public' | 'static' ;
INT : '0'..'9'+ ;
ID  : 'a'..'z'+ ;
WS  : (' '|'\r'|'\n')+ {$channel = HIDDEN;} ;

これはpublic static int i = 3;などにマッチする。
以下はコマンドライン引数で受け取ったファイルをパーズするメインプログラム(Java)。

import java.io.*;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
public class Test {
    public static void main(String args[]) throws Exception {
        TLexer lex = new TLexer(new ANTLRFileStream(args[0]));
        CommonTokenStream tokens = new CommonTokenStream(lex);

        TParser parser = new TParser(tokens);
        TParser.startRule_return r = parser.startRule(); // launch parsing
        // print tree if building trees
        if ( r!=null ) System.out.println(((CommonTree)r.tree).toStringTree());
    }
}

以下はパーサでAST*1を構成して、ツリーパーザで処理(walk)する叩き台(test rig)。

import java.io.*;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
public class Test {
    public static void main(String args[]) throws Exception {
        TLexer lex = new TLexer(new ANTLRFileStream(args[0]));
        CommonTokenStream tokens = new CommonTokenStream(lex);

        TParser parser = new TParser(tokens); // created from T.g
        TParser.startRule_return r = parser.startRule(); // launch parsing
        if ( r!=null ) System.out.println(((CommonTree)r.tree).toStringTree());

        CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);
        nodes.setTokenStream(tokens);
        TP walker = new TP(nodes); // created from TP.g
        TP.startRule_return r2 = walker.startRule();
        CommonTree rt = ((CommonTree)r2.tree);
        // if tree parser constructs trees
        if ( rt!=null ) System.out.println(((CommonTree)r2.tree).toStringTree());               
    }
}

ANTLRの記号

文法(原文)及びアクション中での特殊な記号(原文)も参照のこと。

記号 説明
$ 属性
@ アクション
:: アクションまたは属性名のスコープ指定子(意訳)
: ルール定義
; ルール終了
|((実際には半角。表組み記法の中では が使いにくいので)) 選択肢(というかOR)
's' 文字または文字列リテラル
. ワイルドカード
= ラベルへの代入
+= リストのラベルへの代入(なんか違うかも)
[..] 引数または戻り値指定子
{...} アクション(つまりこの内側にはtarget languageのソースが記述可能)
{{...}} 強制アクション;バックトラックした場合でも実行される
(...) サブルール(というか正規表現のグルーピングと同じ)
+ 1つ以上
*2 0個以上
? 0または1回の表現、あるいはsemantic predicates*3の指定
~ 否定
! 続く要素をASTに含めない
^ ASTのルートノードを作る
=> 常に実行される述語
-> rewrite rule
トークンのオプション指定子。例:ID
^(...) tree grammarまたはrewrite要素(つまりツリーパーザのマッチングルールまたは書き換えルール?)
// 単行コメント
/*...*/ 複数行コメント
キーワード 説明
scope 動的スコープを持つ属性
fragment 補助的なルールであってパーザが扱うトークンではない(意訳:複雑なルールを分割して書く場合の「断片ルール」で単独では意味を成さないことを明示する)。
lexer 文法タイプ
tree 文法タイプ
parser 文法タイプ
grammar 文法ヘッダ
returns ルールが返す値(複数でも可)
throw エラーを投げる
catch エラーを捕獲
finally 必ず実行される
options 文法またはルールのオプション
tokens トークンを列挙する;大抵は名前だけのトークン(imaginary tokens)に使う。
import 文法のインポート

*1:Abstract Syntax Tree. まぁフツーの構文木ですわな

*2:これももちろん半角

*3:参考ページBの2参照。構文定義の中にプログラムによる条件分岐を混ぜちゃう->syntacticではなくsemanticな判定ということらしい。