【问题标题】:Use Ruby to parse a Tcl DSL使用 Ruby 解析 Tcl DSL
【发布时间】:2011-04-20 20:40:54
【问题描述】:

我希望能够解析一些参数不被字符串包围的 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]

有没有人对这类问题有一个干净的解决方案。我想避免对字符串进行标记,因为与词法分析相比,通过调用方法读取数据需要最少的工作。但如果我试图做一些不可能的事情,我想知道。谢谢。

【问题讨论】:

    标签: ruby parsing tcl dsl method-missing


    【解决方案1】:

    这对你不起作用,因为 .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
    

    【讨论】:

    • 该死,我差点就搞定了。感谢您的意见。有人能说一下to_hash 的来源吗?
    • Tcl 不使用像nil 这样的东西;该概念分为空字符串(Tcl 的puts 的结果)和不存在的变量。
    【解决方案2】:

    这是一个尝试使语法接近 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
    

    【讨论】:

    • 由于优先级,我不得不更改块中的大括号以执行/结束。然后我仍然遇到define_method 的错误,我无法弄清楚。想要详细说明吗?
    • @elmt,我进行了更改,现在我进行了测试。有很多事情是错的。现在可以了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多