ANTLRのインストール
環境
環境は以下の通りとする。
- Fedora Core 6
- bash
- JDK 1.6.0_01
- ターゲット言語はJavaとC++
gijだとうまくいかなかったので、SunのサイトからJDKをダウンロードしてインストールしておく必要がある。
ビルド
以下の手順で行った。
$ cd antlr-2.7.7 $ ./configure --disable-csharp --disable-python ... $ make ...
私が使用している環境ではC#とPaythonをインストールしていないので、上記のようにconfigureの実行時に無効にした。
テスト
以下の手順で行った。
$ cd examples $ make ...
*.gファイルからパーサソースを生成し、コンパイルして実行する。途中でWarningは多く発生するが、エラーがなければビルドは問題なく終了したことが確認できる。
Getting Started with ANTLR
言語定義ファイルの作成
実際に文法を定義して、パーサを生成してみる。
以下のページを参考にした。
Getting Started with ANTLR
http://www.antlr.org/doc/getting-started.html
以下の内容を記述したファイルを作成する。仮にファイル名はt.gとする。
class P extends Parser; startRule : n:NAME {System.out.println("Hi there, "+n.getText());} ; class L extends Lexer; // one-or-more letters followed by a newline NAME: ( 'a'..'z'|'A'..'Z' )+ NEWLINE ; NEWLINE : '\r' '\n' // DOS | '\n' // UNIX ;
環境変数CLASSPATHの設定
ANTLRを起動する前に、環境変数CLASSPATHを設定する。
$ export CLASSPATH=<install dir>/antlr-2.7.7/antlr.jar:$CLASSPATH
ANTLRの起動
以下のコマンドを実行する。先ほど作成した言語定義ファイルは、カレントディレクトリにあるものとする。
$ java antlr.Tool t.g ANTLR Parser Generator Version 2.7.7 (2006-11-01) 1989-2005 $ ls L.java L.smap P.java P.smap PTokenTypes.java PTokenTypes.txt t.g $
パーサの起動プログラムを作成
以下のファイルを作成する。ファイル名をMain.javaとする。
import java.io.*; class Main { public static void main(String[] args) { try { L lexer = new L(new DataInputStream(System.in)); P parser = new P(lexer); parser.startRule(); } catch(Exception e) { System.err.println("exception: "+e); } } }
コンパイル
以下のようにコンパイルを実行する。
$ javac *.java ... ^^^^^^^^^^^^^^^^^^^^^^^ The import antlr.SemanticException is never used ---------- 17 problems (17 warnings)$ ls L.class L.smap Main.java P.java PTokenTypes.class PTokenTypes.txt L.java Main.class P.class P.smap PTokenTypes.java t.g $
Warningメッセージがたくさんでてくるが、とりあえずclassファイルは生成される。
実行
いよいよ実行してみる。入力待ちになっているので、"takane"と打ち込んでリターンキーを押すとメッセージが表示されて終了する。
$ java Main takane Hi there, takane $
以下のようなメッセージが表示されるならば、CLASSPATHにカレントディレクトリを追加する。
$ java Main Exception in thread "main" java.lang.NoClassDefFoundError: Main at gnu.java.lang.MainThread.run(libgcj.so.7rh) Caused by: java.lang.ClassNotFoundException: Main not found in gnu.gcj.runtime.SystemClassLoader{urls=[file:.../antlr-2.7.7/antlr.jar], parent=gnu.gcj.runtime.ExtensionClassLoader{urls=[], parent=null}} at java.net.URLClassLoader.findClass(libgcj.so.7rh) at gnu.gcj.runtime.SystemClassLoader.findClass(libgcj.so.7rh) at java.lang.ClassLoader.loadClass(libgcj.so.7rh) at java.lang.ClassLoader.loadClass(libgcj.so.7rh) at gnu.java.lang.MainThread.run(libgcj.so.7rh)
> |
C言語パーサ
cgramのダウンロード
ANTLRのページhttp://www.antlr.org/ を色々と調べてみると、いくつかの文法ファイルをダウンロードできる。今回は、そのうちのC言語パーサ(cgram)のビルドを行う。環境設定については、すでに説明したものを利用する。
参考:http://d.hatena.ne.jp/takaneh/20070507#1178533339
以下のページからcgramをダウンロードする。
Files in diredtory /grammer/cgram
http://www.antlr.org/grammar/cgram
ダウンロードするファイルはcgram.tgz。
cgramのビルド
tgzファイルを展開してmakeする。
$ tar xvfz cgram.tgz ... $ cd cgram $ ls announce.txt examples/ grammars/ license.txt readme.txt tests/ todo.txt $ cd grammars $ ls CSymbolTable.java GnuCTreeParser.g StdCParser.g CToken.java LineObject.java TNode.java GnuCEmitter.g Makefile TNodeFactory.java GnuCParser.g PreprocessorInfoChannel.java $ make ... The serializable class TNode does not declare a static final serialVersionUID field of type long ---------- 18 problems (1 error, 17 warnings)make: *** [StdCParser.class] Error 255 $
実はそのままではエラーが発生する。以下の箇所をコメントアウトするとよい。
StdCParser.g 913 { 914 // import CToken; // コメントアウト 915 import java.io.*; 916 // import LineObject; // コメントアウト 917 import antlr.*; 918 } GnuCParser.g 614 { 615 // import CToken; // コメントアウト 616 import java.io.*; 617 // import LineObject; // コメントアウト 618 import antlr.*; 619 } TNode.java 9 //import CToken; // コメントアウト
上記の変更後、再びmakeを実行するとエラーが発生しないはず。ただし、相変わらずWarningは大量に出る。
実行
ディレクトリexamplesに移動し、CLASSPATHを設定してmakeする。
以下の例は、サンプルCプログラムを読み込み、出力する。
$ cd ../examples $ export CLASSPATH=../grammars:$CLASSPATH $ make ... 4 problems (4 warnings) $ ls GNUCTokenTypes.txt@ Test.class TestLex.class TestThrough.class Makefile Test.java TestLex.java TestThrough.java $ java Test ../tests/test.c static int g1 = 0 ; typedef long mylong ; static mylong z ; typedef int Length ; Length len , maxlen ; Length * lengths [ ] ; typedef char * String ; String p , lineptr [ 100 ] , alloc ( int ) ; int strcmp ( String , String ) ;
ちなみに元のファイルを見てみると、注釈行が削除されている。
$ cat ../tests/test.c static int g1 = 0; typedef long mylong; static mylong z; typedef int Length; Length len, maxlen; Length *lengths[]; typedef char *String; String p, lineptr[100], alloc(int); int strcmp(String, String); /* typedef struct tnode *Treeptr; typedef struct tnode { char *word; int count; Treeptr left; Treeptr right; } Treenode; Treeptr talloc(void) { return (Treeptr) malloc(sizeof(Treenode)); } int fun(int a, mylong b) { mylong c; return a+b; } */ $