Use Ruby to parse a Tcl DSL
I would like to be able to parse some Tcl code where arguments are not surrounded by strings.
Consider this tcl code:
proc foo {name} {
puts "Foo --> $name"
}
foo bar
For those unfamiliar with Tcl, foo
is the method name and bar
is the argument (quotes are optional in Tcl).
The previous code will output:
Foo --> bar
Is it possible to parse exactly the same input using ruby (bar
remains unquoted)?
The equivalent ruby code is:
def foo(name)
puts "Foo --> #{name}"
end
tcl = <<-TCL.gsub(/^\s+/, "").chop
foo bar
TCL
instance_eval(tcl)
Of course that fails when it reaches bar
since it's expected it to be quoted.
I've tried tinkering with method_missing
def method_missing(meth, *args)
puts meth.to_s + " --> args.to_s
end
but it parses in reverse order:
to_hash --> []
bar --> []
foo --> [nil]
Does anyone have a clean solution to this type of problem. I'd like to avoid tokeniz开发者_如何学Cing the strings since reading the data in by calling a method requires minimal work compared to lexical analysis. But if I'm trying to do something that's not possible, I'd like to know. Thanks.
It's doesn't work for you because .puts
method returns nil
instead of string:
irb(main):003:0> puts "42"
42
=> nil
I really don't know why to_hash
appears in this method_missing
but it works:
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
This is an implementation that try to make the syntax near to the TCL syntax.
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
精彩评论