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 に答える