使用Ruby来解析Tcl DSL
我希望能够解析一些Tcl代码,其中参数不被字符串包围。
考虑一下这个tcl代码:
proc foo {name} { puts "Foo --> $name" } foo bar
对于那些不熟悉Tcl的人来说, foo
是方法名称, bar
是参数(引号在Tcl中是可选的)。
以前的代码将输出:
Foo --> bar
是否有可能使用ruby解析完全相同的输入( bar
仍未加引号)?
等效的ruby代码是:
def foo(name) puts "Foo --> #{name}" end tcl = <<-TCL.gsub(/^\s+/, "").chop foo bar TCL instance_eval(tcl)
当然,当它到达bar
时会失败,因为它预计会被引用。
我尝试过修改method_missing
def method_missing(meth, *args) puts meth.to_s + " --> args.to_s end
但它以相反的顺序解析:
to_hash --> [] bar --> [] foo --> [nil]
有没有人对这类问题有一个干净的解决方案。 我想避免对字符串进行标记,因为通过调用方法读取数据需要与词法分析相比最少的工作。 但如果我想做一些不可能的事情,我想知道。 谢谢。
这对你不起作用,因为.puts
方法返回nil
而不是string:
irb(main):003:0> puts "42" 42 => nil
我真的不知道为什么to_hash
出现在这个method_missing
但它有效:
def foo(name) puts "Foo --> #{name}" end def method_missing(meth, *args) meth.to_s unless meth.to_s == "to_hash" end tcl = <<-TCL.gsub(/^\s+/, "").chop foo bar TCL instance_eval(tcl) => Foo --> bar
这是一种尝试使语法接近TCL语法的实现。
class TCL class << self alias run instance_eval def proc(n, &b) self.class.__send__(:define_method, n, &b) end def method_missing(n, *a, &b) n.to_s end end end TCL.run do proc(:foo) { |name| puts "Foo --> #{name}" } foo bar end # prints Foo --> bar