処理をすればいいわけだな。Larkを使って構文解析器をつくってみた(その2)こないだつくった構文解析器をちょっと改良、というか修正して、入力データをコマンド形式にしてみた。代入も制御構造もないシェルスクリプトみたいなものと考えてくれればいい。コマンド形式にしておけば、あとから機能追加によって入力データの項目が増えたとしても対応するコマンドを追加するだけ済み、パーサ(構文解析器)を修正する必要がない。これは、こないだのはデータの種類を表すラベルだったのに対して、今回のはコマンド名を表すからそれらしくした。個以上の引数からなり、改行で終わる。行末までをコメントとするのもこないだと同じ。文法定義ファイルはこうなった。WS_INLINEコメントや継続行の処理も文法でできるようだけど、今回はパースする前の前処理でやってしまうことにした。そのほうが文法が楽だったから。いうクラスが用意されている。メソッドを使うと、パースした木構造を他のデータ構造に変換する代わりに、ノードをたどりながら処理を実行できる。今回はコマンド名と引数リストを出力してるだけだけど、これでデータを構築する処理を書けばいいわけだ。parser.parse(input_data)MyInterpreter().visit(tree)実行するとこうなった。Larkを使って構文解析器をつくってみた構文解析器を「つくってみた」というと、四則演算や簡単なプログラミング言語をつくってみたというのをよく見かけるけど、個人的には何かのプログラムの入力データをパース(構文解析)することが多い。四則演算ができたところで結局は「つくってみた」以上のものではないし、プログラミング言語を(本格的に)つくってみようという人もどちらかといえば稀だろう。一方でプログラム(それが何であれ)というのはたいてい入力が必要なものだし、ファイルから入力を読み込むことも少なくない。データが並んでいればいい、というのでなければ何らかのフォーマットを決める必要がある。いった汎用のフォーマットもあるけど、必ずしも目的に対して適当とは言えないこともある。いうわけで構文解析器(パーサ)の出番になるわけだ。いうライブラリが良さげだったので試してみることにした。つくったあるプログラムの入力ファイルをサンプルとしてとりあげる。始まる文字列がデータの種類を表すラベルで、その後に1つ以上のデータが空白で区切られて続く。改行は意味を持たない(空白とみなす)。解析対象の文法を定義したファイルを用意する。ベースの構文で定義する。今回の例ではこうなった。渡せばパーサを返してくれる。parser.parse(input_data)print(tree)たったこれだけで構文解析をして構文木を返してくれる。[])])パースした結果が木構造になってるのがなんとなくわかる。メソッドを使ってみよう。end見やすくなったね。クラスを継承したクラスをつくってやる。プログラムはこうなった。メッソッドにパースした結果を渡してやると、変換した結果が返ってくる。今回は普通の辞書にした。構文木をたどりながらノード(つまり構文要素)に対応するメソッドを呼び出す。これらのメソッドから適切な値を返せば、最終的に目的の構造を持ったデータ(今回は辞書)が手に入る。これを実行するとこんなふうに出力される。10.0]}無事、目的のものが手に入った。引数にとり、自身を評価した値を返す。ように)と、メソッドの引数リストに入らない。これ、気づくまでにちょっとかかった。)は予め定義されてて、インポートして使うことができる。リポジトリでソースファイルを見るといい。