Lexus 发表于 2015-06-30 10:12

用 Ruby 进行简单的 lisp 表达式的解析

就是lisp用的s表达式,可以向json一样用来读取保存的数据,也可以用来做DSL什么的。
代码的各种情况还考虑得不是很完全,等用到一种测试用例再来补充对应的实现吧。
这个实现对S表达式的格式以及这个解析函数在各方面都暂且以简单能用首要目的来着。

代码def parse(line)
s = line.scan(/\(|\)|"(?:\\.|[^"])*"|[^()" \n]+/)
f = ->(t=nil){
    case x = t || s.shift
    when ?(
      y = []
      while x = s.shift
      return y if x==?)
      y << f
      end
      fail ")?"
    when nil
      nil
    when /^#(.*)$/
      {?t=>true,?f=>false}[$~]
    when /\d+/
      x.to_i
    when /^\"(.*)\"$/m
      $~.gsub(/\\./,'\n'=>"\n","\\\\"=>"\\","\\\""=>'"')
    else
      x.to_sym
    end
}
f[]
end

$tests = {
"" => nil,
"1" => 1,
"(a b)" => [:a,:b],
"(1 2(2 3))" => ],
'(a"b"c"d"(ef))' => [:a,"b",:c,"d",[:ef]],
'("a b" (c d-e))' => ["a b",[:c,:"d-e"]],
"(\"a\nb\"\nb\nc (d))" => ["a\nb",:b,:c,[:d]],
' "a\nb"' => "a\nb",
'"a\\"b"'=>'a"b',
"\"\\\\\""=> "\\",
"(#t #f)" => ,
"(define (f x) (if (zero? x) 0 (+ x (f (- x 1)))))" =>
    [:define,[:f,:x],[:if,[:zero?,:x],0,[:+,:x,[:f,[:-,:x,1]]]]],
}

p $tests.all?{|x,y|parse(x)==y}
页: [1]
查看完整版本: 用 Ruby 进行简单的 lisp 表达式的解析