Monadic ParserでSchemeのリストをパースする
去年のGWに何をやっていたか全く記憶が無いんですが、今年も特に何もないGWになりそうですね。なんだかなぁ、という気分しかありませんが。 そんな状態ですが、最近チマチマと作っているOCamlでのScheme処理系で、Monadic Parserを作ってみたので、その紹介をちょっとできれば。 <!–more–> Monadic parserとは まずMonadic parserとは何か、ですが、あんまり明確な定義は無いというか、名は体を表すというか、そのまんまというか。モナドを利用したparserです。HaskellのParsecが有名ですね。 基本的には、 関数で構成されている モナド則により合成可能である という感じかなー、と。理論的な背景はあんまり理解しきれていないので、あくまで私の理解ではありますが。 OCamlのapplicable let Haskellだと、Monadの記述にとても役立つ、 do記法 というのがあります。OCamlには長らくそういうのがなく、PPXとかで各ライブラリごとに拡張を書いていたり、ppx_letのように汎用的な拡張を利用したり・・・というのが必要でした。 が、OCamlの4.08?くらいで導入された Applicable let というのを利用すると、do記法と同じような記述を、OCamlらしく記述することができます。 module Nanika_monad = ... let ( let* ) v f = Nanika_monad.bind f v let () = let* v = Nanika_monad.return v in ... applicable letと言っても、なんてことのない関数定義です。 let* とかだけではなく、 let+ みたいなものも定義できます(定義の中身は、定義の実装者次第です)。letが定義できるということで、同時に and* のような関数も定義することができます。 これですが、 >>= での結合をほぼそのまま変換することができ、逐次処理のように見せることができます。記号で繋げまくっていくのも楽しいですが、後から見たときに処理が明瞭になるので、最近はMonadとかを利用するときはこれを使ってます。 Applicative ParserではなくMonadic Parserになる理由 Monadic Parserとはよく呼ばれるけど、 Applicative Parser というのが無い理由ですが、これはシンプルで、 Applicableだとパースできないものが沢山ある から、という理由のようです。 具体的な例は、もっとよく説明しているサイトを参考にするのがよいと思います。私の浅い理解だと、 Applicableだと、繰り返しやバックトラックといった挙動を定義することができない 前の値を利用する、というようなことができない ため、そもそもパーサーという目的には機能が足りないのでApplicative Parserというものは事実上作成されない、ということのようです。よりシンプルなパースができればいいのであれば、Applicative Parserとかも作れると思います。 ...