ANTLRでOracleのDDLを解析してみる #contents *文法ファイル [#e3077a65] 文法ファイルは下記のサイトで公開されていました。 http://www.antlr.org/grammar/1174072667394/PLSQLGrammar.g PLSQLGrammar.g で保存 antlrのjarファイルがあるディレクトリで実行すると、いろいろファイルができそうだったので、 olacle_ddlというフォルダをつくってそこに保存 *前回ANTLRを動かした例を参考にコンパイルしてみる [#i95dd298] 前回やってみた例ではこんなかんじ java -jar antlr-3.4-complete-no-antlrv2.jar T.g だからまねて次のようにしてみた。 java -jar ../antlr-3.4-complete-no-antlrv2.jar PLSQLGrammar.g **結果 [#r733d84a] error(10): internal error: : java.lang.Error: Error parsing PLSQLGrammar.g: 'header' not expected 'grammar' org.antlr.tool.GrammarSpelunker.match(GrammarSpelunker.java:70) java -classpath antlr-2.7.2.jar antlr.Tool T.g だと、前のバージョンでうごいたから、これをさんこうにして java -classpath ../antlr-2.7.2.jar antlr.Tool PLSQLGrammar.g **結果 [#kee796b6] なにやら、警告分がたくさんでたが、動いた。 PLSqlLexer.javaやPLSqlParser.javaなど4ファイルが出力されている さいしょから、このファイルをダウンロードできるようにしておいたほうが、面倒なコンパイルとかしなくていいんじゃない?って おもうのであった。それは、さておき **確認用のコード [#p66e8d02] 確認用のコードをつくってみなくては、 前回ためしてみたメインクラスを参考にしてみることにした、えー、前回確認してみたコードは次のコードである 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); } } } このクラスを、生成されたクラスの名前とかみて、手直しすると次のようになるのではないかとおもう。 import java.io.*; class Main { public static void main(String[] args) { try { PLSqlLexer lexer = new PLSqlLexer(new DataInputStream(System.in)); PLSqlParser parser = new PLSqlParser(lexer); parser.start_rule(); } catch(Exception e) { System.err.println("exception: "+e); } } } start_ruleメソッドを観察すると、どうやらreturnAST変数に格納されることで、満足して、戻り値を返さないという なんとも、自己満足的なメソッドとなっているようだ。 ここを改造すればよいのだな。でもどういう変数が格納されているのかわからないや。 デバックで止めるために、エクリプスにいれるのも面倒だし。。。 とりあえずコンパイルじゃ。 javac -classpath ../antlr-2.7.2.jar *.java **結果 [#v09f39df] PLSqlLexer.java:487: エラー: シンボルを見つけられません SoftwareMetrics.adjustMetrics(getText(), getLine()); ^ シンボル: 変数 SoftwareMetrics 場所: クラス PLSqlLexer SoftwareMetricsを//SoftwareMetricsに置換してコメントアウトした。 で、コンパイル if (lcnt > 0) //SoftwareMetrics.incBlanks(lcnt - 1); でこけてたので、コメントアウトしなおし //if (lcnt > 0) //SoftwareMetrics.incBlanks(lcnt - 1); こんなふうにした **結果 [#d230cd35] **コメントアウトしなおした結果 [#d230cd35] PLSqlParser.java:1075: エラー: シンボルを見つけられません SoftwareMetrics.start(pn.getText(),"Package",pk. getLine()); ^ シンボル: 変数 SoftwareMetrics 場所: クラス PLSqlParser PLSqlParserにもあるようだ。じゃまなのが、 同様にコメントアウトする **結果 [#ya550b71] **さらにコメントアウトした結果 [#ya550b71] こんなメッセージがでたが、コンパイルできた 注意:PLSqlLexer.javaの操作は、未チェックまたは安全ではありません。 注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。 **DDLのサンプルを用意する [#se5b8c97] http://oracle.se-free.com/ddl/A1_cre_tbl.html DDLを解析といっても、テーブル作成のDDLしか興味がないのだ。 プライマリ付きのテーブル create table emp ( emp_id char(3) , emp_name varchar2(10), primary key( emp_id ) ) 実行させてみます。 java -classpath .;../antlr-2.7.2.jar Main 標準入力を受け付けたままになっているはずなので、DDLをペーストしてみます。 **結果 [#v1ee495a] create table emp line 1:8: unexpected token: table ( あれ?tableって単語は、予期してませんでしたって出てる おいおい、予期してくれよう かんべんしてよ。。。っておもいながら、しょせんフリーなんてどうさ確認もとれてませんという ことなんだよねと自分を説得します。 **後述 [#l5598037] SELECT文だと通った気がする。 *他のSQLパーサの文法ファイルを検討する [#nbc385b2] ほかに、ないのかとしらべてみると、 http://www.antlr.org/grammar/list にOraclleSQLが載っていました。 ためしてみましょう。 tgzでかためられた えーと、C言語用でした。 **Javaへの変換 [#s698777b] Perlで書かれたJavaに置き換えるスクリプトも同梱されているもよう。