Camlp4 のストリームパーサ [OCaml]
Camlp4 に用意されているストリームパーサを使うと前回 [1] 作った Tcl インタプリタの以下のような部分がもっとすっきり書きなおせる。例えば、
comment (interp, strm, state) =
match (Stream.peek strm) with
| Some '\n' -> Stream.junk strm; eval (interp, strm, state)
| Some '\\' -> Stream.junk strm; ignore (backslash strm); comment (interp, strm, state)
| Some _ -> Stream.junk strm; comment (interp, strm, state)
| None -> eval (interp, strm, state)
これが以下のようになる。ソースの先頭で #load "camlp4.cma";;
とする。
comment (interp, strm, state) = (parser
[< ''\n' >] -> eval (interp, strm, state)
| [< ''\\' >] -> ignore (backslash strm); comment (interp, strm, state)
| [< '_ >] -> comment (interp, strm, state)
| [< >] -> eval (interp, strm, state)
) strm
これだと Stream.junk とか書かなくてよいし、また書く場合と書かない場合に注意しなくてよいのでかなりよい。なるほど、これは便利だ。
実際このコードを camlp4o -I . pr_o.cmo otcl2.ml > a などとすると、以下のようなコードに変換されているのが分かる。
comment (interp, strm, state) =
(fun (strm__ : _ Stream.t) ->
match Stream.peek strm__ with
Some '\n' -> Stream.junk strm__; eval (interp, strm, state)
| Some '\\' ->
Stream.junk strm__;
begin ignore (backslash strm); comment (interp, strm, state) end
| Some _ -> Stream.junk strm__; comment (interp, strm, state)
| _ -> eval (interp, strm, state))
strm
元々のコードとかなりぴったり一致する。あとこのコードを見て分かったのは Genlex のソースも元々は Camlp4 のストリームパーサを使ったものから変換しているっぽい。strm__
という変数名とかが一致するし。なんかぐるっと遠回りしてたどり着いた感じだ。
[1] http://blog.so-net.ne.jp/rainyday/2006-09-25
コメント 0