Common Lisp風のインタプリタをRubyで作ってみる。 Rubiesp(RubiestのためのLisp) の略 + Lispっぽく括弧で (rubi)
ruby irubi.rb
でREPLが立ち上がります。
ruby irubi.rb
lisp:001> (+ 1 2)
3
exit
でインタプリタを終了します。
(+ 1 2)
の処理の流れ
Lispのコードを記号ごとに分割します。
Rubi::Tokenizer.new.split_tokens("(+ 1 2)")
=> [:"(", :+, 1, 2, :")"]
記号の集まりから、()を認識して、配列に変換します。 この状態のことを抽象構文木(AST)って言うらしいです。
Rubi::Parser.new.parse([:"(", :+, 1, 2, :")"])
=> [[:+, 1, 2]]
抽象構文木を評価(実行)します。 ※パーサーは複数行のコードを入力する前提になっているので、1行ごとに分けてevalで評価していきます。
Rubi::Evaluator.new.eval([:+, 1, 2], {}, 0)
=> 3
lisp_code = "(+ 1 2)"
tokens = Rubi::Tokenizer.new.split_tokens(lisp_code) # => [:"(", :+, 1, 2, :")"]
ast = Rubi::Parser.new.parse(tokens) # => [[:+, 1, 2]]
ast.map { |code| Rubi::Evaluator.new.eval(code, {}, 0) } # => [3]