2012-09-20 90 views
2

我最近開始使用解析器和解析器生成器及其在DSL設計中的使用。爲了讓事情開始,並且一箭雙鵰,我寫了一個純粹的Ruby PEG解析器DSL,通過竊取peg.js的一些想法。不同之處在於,peg.js會將語法編譯爲JavaScript,而我的庫使用解釋器模式以及Ruby提供的一些語法糖來完成純Ruby中的所有操作。這增加了我想避免的一些不重要的開銷。Ruby中運行時代碼生成的最佳實踐

爲了減少一些開銷,我開始考慮編譯一些解析表達式,這些解析表達式被生成爲低級表示。我的一個想法是使用eval來評估某個對象的單例類中代碼的字符串表示。下面是一些僞代碼來演示過程:

# 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" 

我想知道是否有其他/更好地完成這樣的代碼生成方法?我對這個東西很陌生,所以我可能錯過了一些明顯的東西。

回答

2

我仍然試圖理解你正在努力完成什麼,但已經有一些你可能有興趣探索的Ruby解析器/解析器生成器。

樹頂:我最熟悉的語法分析器,它的PEG解析器可以動態運行或編譯語法爲純Ruby語法分析器Treetop

Parslet:這是另一種peg解析器,它比Treetop和「更好」的錯誤報告更簡單。 Parslet

柑橘:另一個解析器,我不熟悉;儘管如此,我不認爲這是一個pure peg解析器。 Citrus

+0

我知道所有這些圖書館。我只是重新開始學習更深層次的東西。我試圖找出在Ruby中運行時生成代碼的最佳方法。我想知道是否有更好/更簡單的方法來生成代碼,而不是使用實際代碼評估字符串。 – davidk01