问题
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 tokenizing 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.
回答1:
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
回答2:
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
来源:https://stackoverflow.com/questions/5736351/use-ruby-to-parse-a-tcl-dsl