Let's start Scheme

2011-05-24

sxmlを使えるようにしたい

仕事柄、自分用の何かしらを書くのにXMLパーサーくらいは絶対的に必要になる。ということでSchemeでつかえるXMLパーサーということでSSAXをporting中。
必要そうなSRFI(13、14とか)を実装して、いざSSAXを流してみたらsyntax-rulesでおかしなエラーを出してくる。
エラーはパターン変数が重複しているというもの。
Ypsilonで試したらきっちり動く。でも、Gaucheでは同じエラー。
ちなみに、こんなsyntax-rules
(define-syntax ssax:define-labeled-arg-macro
  (syntax-rules ()
    ((ssax:define-labeled-arg-macro
       labeled-arg-macro-name
       (positional-macro-name
  (arg-name . arg-def) ...))
      (define-syntax labeled-arg-macro-name
 (syntax-rules ()
   ((labeled-arg-macro-name . kw-val-pairs)
     (letrec-syntax
       ((find 
   (syntax-rules (arg-name ...)
                   ;; ここが問題
     ((find k-args (arg-name . default) arg-name
        val . others)    ; found arg-name among kw-val-pairs
      (next val . k-args)) ...
     ((find k-args key arg-no-match-name val . others)
       (find k-args key . others))
     ((find k-args (arg-name default)) ; default must be here
       (next default . k-args)) ...
     ))
  (next   ; pack the continuation to find
    (syntax-rules ()
      ((next val vals key . keys)
        (find ((val . vals) . keys) key . kw-val-pairs))
      ((next val vals) ; processed all arg-descriptors
        (rev-apply (val) vals))))
  (rev-apply
    (syntax-rules ()
      ((rev-apply form (x . xs))
        (rev-apply (x . form) xs))
      ((rev-apply form ()) form))))
       (next positional-macro-name () 
  (arg-name . arg-def) ...))))))))
問題なのはarg-nameが2回出現していること。仮に展開されるとしてもarg-nameは同じものを指すので、展開後もパターン変数が重複する。仕様書を完全に理解してないけど、これはsyntax-rulesの動作として正しい。個人的に気になるのは、Ypsilonではなぜ動いたのかということと、他のR6RSの実装でもこれは動くのかということ。(もし他のR6RSの実装でも動くのなら、ちと考えないといけないかもしれない)
っで、sxmlをライブラリとして持っているGaucheはなぜ動いたのかというところを探ってみたところ、単純にバージョンが古かった。最新版といっても2004年ととても古いのだが、Gaucheのはさらに1年古い2003年のもので、make-parserはdefine-macroで書かれていた。
一応最新版と思われるbiglooで動く実装を覗いたら、そちらもdefine-mecroで実装してある。う~ん、define-macro自体はあるし、er-macro-transformerでの書き換えも非常に楽なんだけど、どうしたものだろう?
とりあえず他のも見てみるか。

No comments:

Post a Comment