2

私は最近、パーサーとパーサー ジェネレーター、および DSL 設計におけるそれらの使用法をいじり始めました。物事を開始し、一石二鳥にするために、peg.js からいくつかのアイデアを盗んで純粋な Ruby PEG パーサー DSL を作成しました。違いは、peg.js は文法を JavaScript にコンパイルするのに対し、私のライブラリは Ruby が提供する構文シュガーと組み合わせたインタープリター パターンを使用して、すべてを純粋な Ruby で行うことです。これにより、回避したい重要なオーバーヘッドが追加されます。

オーバーヘッドの一部を削減するために、生成された構文解析式の一部を低レベルの表現にコンパイルすることを考え始めました。eval私が思いついたアイデアの 1 つは、あるオブジェクトのシングルトン クラス内のコードの文字列表現を評価するために使用することでした。プロセスを示すための疑似コードを次に示します。

# will be used to pass CompiledExpression instance to `eval`
def get_binding(instance)
  instance.instance_eval { binding }
end

# an instance of this class will be used with `eval` 
# to define an `execute` method
class CompiledExpression
  attr_reader :code_repr
  # need to instantiate with a string representation of 
  # the code we are going to use to define the `execute` method
  def initialize(code)
    @code_repr = code
  end
end

# create the instance and define `execute` for that instance
# by evaluating the code representation
compiled_expr = CompiledExpression.new

# first way
eval "class << self; def execute; " +
    "#{compiled_expr.code_repr}; end; end", get_binding(compiled_expr)

# second way
compiled_expr.instance_eval "class << self; " +
    "def execute; #{compiled_expr.code_repr}: end; end"

# third way
compiled_expr.singleton_class.class_eval "def execute; " + 
    "#{compiled_expr.code_repr}; end"

# fourth way
compiled_expr.instance_eval "def execute; " + 
    "#{compiled_expr.code_repr}; end"

そのようなコード生成を達成するための他の/より良いアプローチがあるかどうか知りたいですか? 私はこのようなことに慣れていないので、おそらく明らかな何かを見逃しています。

4

1 に答える 1

2

私はまだあなたが達成しようとしていることを理解しようとしていますが、あなたが探求することに興味があるかもしれないいくつかのRubyパーサー/パーサージェネレーターがすでにあります。

Treetop:私が最もよく知っているパーサーです。これは、文法を動的に実行したり、純粋なRubyパーサーにコンパイルしたりできるペグパーサーです。ツリートップ

Parslet:これは、Treetopよりもシンプルなデザインで、「より優れた」エラーレポートを備えたもう1つのペグパーサーです。パースレット

Citrus:もう1つのパーサー、私はあまり馴染みがありません。ただし、これは純粋なペグパーサーではないと思います。柑橘類

于 2012-09-23T03:37:57.510 に答える