Используйте Ruby для разбора Tcl DSL
Я хотел бы иметь возможность анализировать некоторый код Tcl, где аргументы не окружены строками.
Рассмотрим этот код tcl:
proc foo {name} {
puts "Foo --> $name"
}
foo bar
Для тех, кто не знаком с Tcl, foo
это имя метода и bar
является аргументом (кавычки необязательны в Tcl).
Предыдущий код выведет:
Foo --> bar
Можно ли проанализировать точно такой же ввод, используя ruby (bar
остается без кавычек)?
Эквивалентный рубиновый код:
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]
У кого-нибудь есть чистое решение этой проблемы. Я бы хотел избежать токенизации строк, поскольку чтение данных с помощью вызова метода требует минимальной работы по сравнению с лексическим анализом. Но если я пытаюсь сделать что-то, что невозможно, я бы хотел знать. Благодарю.
2 ответа
Это не работает для вас, потому что .puts
метод возвращает nil
вместо строки:
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