2013年5月9日木曜日

[Ruby][Scheme] Micro Schemeの実装(4) S式パーサの実装

Rubyのリスト形式でSchemeプログラムを書くのは大変なので、S式のパーサを作成した。
https://github.com/takeisa/uschemer/tree/v0.04

パーサの実装

作成中のMicro Schemeは、Rubyの配列でS式を表現している。
S式をRubyの配列形式になるように文字列置換し、Kernel.evalすればS式の配列表現を得ることができる。

    def parse(sexp)
      sexp.gsub!(/[_a-zA-Z\+\*\-\/][_a-zA-Z0-9\+\*\-\/]*/, ':\\0')
      sexp.gsub!(/\s+/, ',')
      sexp.gsub!(/\(/, '[')
      sexp.gsub!(/\)/, ']')
      Kernel.eval(sexp)
    end

まだ文字列は扱わないので、すごく単純だ。


実行例

eval_print("(let ((a 1) (b 1)) (+ a b))", env)
(let ((a 1) (b 1)) (+ a b)) #=> 2

eval_print("(let ((a 1)) (lambda (x) (+ a x)))", env)
(let ((a 1)) (lambda (x) (+ a x))) #=> [:closure,
 [:x],
 [:+, :a, :x],
 [{:a=>1},
  {:+=>[:built_in, #<Proc:0x9e7fec4@uschemer.rb:6 (lambda)>],
   :-=>[:built_in, #<Proc:0x9e7fe9c@uschemer.rb:7 (lambda)>],
   :*=>[:built_in, #<Proc:0x9e7fe4c@uschemer.rb:8 (lambda)>],
   :/=>[:built_in, #<Proc:0x9e7fe10@uschemer.rb:9 (lambda)>]}]]

eval_print("((let ((a 1)) (lambda (x) (+ a x))) 2)", env)
((let ((a 1)) (lambda (x) (+ a x))) 2) #=> 3

やっとLispらしくなってきた。