S式計算式
30分プログラム、その62。S式計算機。
ちょっとさきの勉強会のネタ。本番は、OCamlで作ったのを持っていくつもりだけれども、とりあえずRubyでも作ってみる。
> 1 1 > (+ 1 2) 3 > (* (+ 2 3) 1 3) 15
require 'strscan' require 'readline' def call(name) lambda{|x,*args| x.send name,*args } end module SExpression class Call def initialize(op,*args) @op = op @args = args end def eval @args.map(&call(:eval)).inject(&call(@op)) end end class Number attr_reader :num alias_method :eval,:num def initialize(num) @num = num end end def self.parse(str) str = StringScanner.new(str) if str.class == String str.skip /\s+/ if str.skip /\(/ then op = str.scan %r![-+*/]! args = [] args << parse(str) until str.skip /\)/ Call.new op.to_sym,*args elsif str.scan /\d+/ then Number.new str.matched.to_i else raise 'error' end end end while buf = Readline.readline('> ',true) puts SExpression.parse(buf).eval end
- callは、ちょっと自慢
- ちゃんとASTも作ってみた
- 3秒あまった。あまったとは言わんけど