0

基本上,我想象一些看起来像这样的伪代码

build_command_list {
   add_command("cmd 1")
   add_command("cmd 2")
   conditional_branch( some_cond ) {
      add_command("cmd3")
      add_command("cmd4")
   }
   conditional_branch( some_other_cond ) {
      add_command("cmd 5")
   }
}

该方法build_command_list将获取一段代码,然后递归地构建一个树结构,其中每个节点都是一个命令,一些解释器将获取该树并从根执行它,这是该代码块中的第一个命令(在这种情况下, "cmd 1")

add_command并且conditional_branch是确定如何创建节点的其他方法。

有些命令conditional branch告诉解释器评估条件,如果为真,它将处理其命令列表。

我想知道 ruby​​ 是否有一些东西可以让我像上面的例子一样编写一段代码并获取代码并解析它?

如果没有,也许有人可以为我建议一种方法来编写输入,以便我可以从一组命令构建正确的命令树?

4

2 回答 2

2

您可以编写一个 DSL 来实现这一点:

班级

class CommandList
  def add_command(str)
    puts "Adding command #{str}"
  end

  def conditional_branch(condition, &block)
    b = ConditionalBranch.new(condition)

    puts "With condition: #{condition} {"
    b.instance_eval(&block)
    puts "}"
  end
end

class ConditionalBranch < CommandList
  def initialize condition
    @condition = condition
  end
end

def build_command_list &block
  c = CommandList.new
  c.instance_eval(&block)
end

DSL 使用

build_command_list {
   add_command("cmd 1")
   add_command("cmd 2")
   conditional_branch( "some_cond" ) {
      add_command("cmd3")
      add_command("cmd4")
   }
   conditional_branch( "some_other_cond" ) {
      add_command("cmd 5")
   }
}

输出

Adding command cmd 1
Adding command cmd 2
With condition: some_cond {
Adding command cmd3
Adding command cmd4
}
With condition: some_other_cond {
Adding command cmd 5
}

请注意,这可能不会按照您希望的方式处理条件,这只是您如何使用 instance_eval 在给定对象的上下文中评估块的示例

于 2012-07-10T22:08:56.653 回答
0

您在这里谈论的内容称为 DSL(领域特定语言)。

您可以在 ruby​​ 中实现内部和外部 DSL。

对于外部 DSL,您需要创建一个解析器。这就是为什么使用 ruby​​ 创建内部 DSL 通常更好的原因。

我写了一篇关于可用于实现此目的的基本技术的博客文章:http: //blog.nofail.de/2010/02/writing-your-own-dsl-with-ruby/

于 2012-07-10T21:54:35.207 回答