antlr4を使う(2)

シーマークすずきです。

前回の続きで、antlr4が生成したパーサーソースをjavaから呼び出して、利用してみます。

■ eclipseのGradleプロジェクト作成

build.gradleは以下としました。antlr4が生成するソースをjp.co.seamark.csv.generatedパッケージに吐かれる様にします。また、構文木を捜索する方式は、リスナー方式とビジター方式がありますが、今回は、リスナー方式としました。

 

■ CSVの単純なパース

前回生成したソースのCSVBaseListenerクラスを拡張します。簡単にcsvファイルの全行をString型で受け取る方式とします。まずは、構文木の文字列形式に変換して返すだけにします。

実行すると、以下の様に前回grunでコンソール出力した結果と同じ結果が表示されました。(注意)fileToString()は割愛します。

テスト用のtest.csvは前回と同じ以下。

CSVSimpleParserの実行結果。

>AST=>(file (hdr (row (field user.name) , (field string#!user.age) , (field *omit*user.gender) \n)) (row (field suzuki) , (field 50) , (field male) \n) (row (field ange) , (field 12) , (field female) \n) (row (field seamark) , (field 20) , (field male) \n))

■ 構文木をウォークスルーしてみましょう

ParseTreeクラスをParseTreeWalkerクラスでwalk()することで、構文木の各構文ノードへのenter,とexitのリスナーイベントが呼ばれますのでメソッドをOverrideすることで自分用に処理を追加できます。

プログラムで処理する場合、構文ルール毎にexitほげほげのタイミングが分かりやすいでしょう。以前のCSV.gの文法を記述した際、構成要素はfieldというルールで各行rowが構成される、としました。fieldの構文ノードを抜けるタイミング、つまり、exitField()の関数でrowリストにfield文字列を追加していきます。先頭行のヘッダー行として、headerに、取り込みたい場合、exitHdr()のタイミングです。各CSV行の行毎のタイミングであれば、exitRow()となります。headerが空でない場合にCSVデータをheaderのラベルと一緒にMapに取り込みましょう。

■ JSON形式に変換してみる。

List<Map<String,String>> rowsに全ての行が取り込まれましたので、exitFile()をOverrideしてJSON形式に出力してみましょう。以下のメソッドを追記します。

出力結果は、以下。

もう少し考慮すれば、以前のNode.jsのcsvtojson.jsと同じ様な変換ができそうです。”string#!”や”number#!”がヘッダーに付いていれば、JSON型を文字列、数値型にするとか、”*omit*”が付いていれば、JSON出力しない、とか。残りは、後日。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です