Treetop语法节点的自定义方法

时间:2018-04-05 05:11:10

标签: ruby peg treetop

我有一个匹配某些键的Treetop PEG语法。我想在我给解析器的哈希中查找与这些键相关的值。我怎样才能使语法节点可以访问解析器中的方法或变量?

例如,这是一个简单的语法,它找到一个单词并试图查找其值:

# var.treetop
grammar VarResolver
  include VarLookup

  rule variable
    [a-zA-Z] [a-zA-Z0-9_]*
    {
      def value
        p found:text_value
        find_variable(text_value)
      end
    }
  end
end

这是一个使用它的测试文件:

# test.rb
require 'treetop'

module VarLookup
  def set_variables(variable_hash)
    @vars = variable_hash
  end
  def find_variable(str)
    @vars[str.to_sym]
  end
end

Treetop.load('var.treetop')

@p = VarResolverParser.new
@p.set_variables name:'Phrogz'
p @p.parse('name').value

运行此测试,我得到输出:

{:found=>"name"}
(eval):16:in `value': undefined method `find_variable'
     for #<Treetop::Runtime::SyntaxNode:0x00007f88e091b340> (NoMethodError)

如何在find_variable方法中访问value? (在真正的解析器中,这些规则是深度嵌套的,需要解析值而不将实际名称返回到解析树的顶部。我不能只返回text_value并在外面查找。)

1 个答案:

答案 0 :(得分:1)

这是Treetop设计的一个重大缺陷。

我(作为维护者)并不想进一步放慢速度 将另一个参数传递给每个SyntaxNode, 并打破民间拥有的任何自定义SyntaxNode类 书面。这些构造函数得到了&#34;输入&#34;对象,范围 选择该输入的一部分,以及可选的数组 子语法SyntaxNodes。他们应该收到了 解析器本身而不是作为成员的输入。

相反,为了我自己的使用(几年前),我做了 &#34;输入&#34;的自定义代理并附上我的背景 它。你可能会做类似的事情:

https://github.com/cjheath/activefacts-cql/blob/master/lib/activefacts/cql/parser.rb#L203-L249