SSブログ

逆ポーランド記法を解釈する Camlp4 プリプロセッサ [OCaml]

最近 Camlp4 を本腰入れて理解しようとがんばっている。

今日は逆ポーランド記法を OCaml の構文木に変換するプリプロセッサを作ってみた。

Camlp4 は基本的には OCaml コードを構文木に変換する関数を Pcaml.parse_implem に定義しているのだけど、それを書き換えれば任意の言語を入力にすることができる。その関数は char Stream.t を読んで構文木を返すことができればいい。

(* ocamlc -c -I +camlp4 -pp "camlp4o q_MLast.cmo" pa_rpn.ml *)

let _ =
Pcaml.parse_implem := function strm ->
  let _loc = Token.dummy_loc in
  let stack = Stack.create () in
  let rec process stack strm = 
    match (Stream.peek strm) with 
      | Some ('0'..'9')
        -> let c = String.make 1 (Stream.next strm) in
           Stack.push <:expr<$int:c$>> stack;
           process stack strm
      | Some ('+')
        -> Stream.junk strm;
           let x = Stack.pop stack and y = Stack.pop stack in
           Stack.push <:expr< $y$ + $x$ >> stack;
           process stack strm
      | Some ('-')
        -> Stream.junk strm;
           let x = Stack.pop stack and y = Stack.pop stack in
           Stack.push <:expr< $y$ - $x$ >> stack;
           process stack strm
      | Some ('*')
        -> Stream.junk strm;
           let x = Stack.pop stack and y = Stack.pop stack in
           Stack.push <:expr< $y$ * $x$ >> stack;
           process stack strm
      | Some ('/')
        -> Stream.junk strm;
           let x = Stack.pop stack and y = Stack.pop stack in
           Stack.push <:expr< $y$ / $x$ >> stack;
           process stack strm
      | Some _
        -> raise (Failure "unknown char")
      | None
        -> let e = Stack.pop stack in
           <:str_item< print_int $e$ >>
  in
  [(process stack strm), _loc], false;

これを以下のようにコンパイルして

ocamlc -c -I +camlp4 -pp "camlp4o q_MLast.cmo" pa_rpn.ml

こんな感じで使う。

F:\>type rpn.ml
12-3*
F:\>ocamlc -pp "camlp4o ./pa_rpn.cmo" rpn.ml

F:\>camlprog
-3
F:\>

OCaml ソースコード上は print_int ((1 - 2) * 3) に相当する構文木に変換されるのだが pr_o.cmo で見た場合は何故か元のソースがそのまま最後にくっついてしまう。

F:\>camlp4o ./pa_rpn.cmo pr_o.cmo rpn.ml
let _ = print_int ((1 - 2) * 3)12-3*
F:\>

これはどうやら pr_o.cmo のバグで、 Pcaml.parse_implem を直接書き換えるとおかしくなるみたいだ。Matin Jambon 氏のページ [1] でもそのような現象について記載されている。

Camlp4 を勉強しながらその成果をチュートリアルみたいなものとして残そうとしているのだけど、3.09版でやっているので、下方互換性のない3.10がいずれ正式になることと思うと未来のない作業かもしれない。最終的には文章を書く練習だと考えればいいとも思っているが。

[1] http://martin.jambon.free.fr/extend-ocaml-syntax.html#inserting-bof


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

GroovyC と Lua の間のスタック ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。