简体   繁体   English

树梢语法节点的自定义方法

[英]Custom Methods for Treetop Syntax Nodes

I have a Treetop PEG grammar that matches some keys. 我有一个与某些键匹配的Treetop PEG语法。 I want to look up the values associated with those keys in a hash I give the parser. 我想在给解析器的哈希中查找与这些键相关联的值。 How can I make it so that the syntax nodes have access to methods or variables from the parser? 如何使语法节点可以访问解析器中的方法或变量?

For example, here's a simple grammar that finds a single word and tries to look up its value: 例如,下面是一个简单的语法,该语法找到一个单词并尝试查找其值:

# 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

Here's a test file using it: 这是使用它的测试文件:

# 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

Running this test, I get the output: 运行此测试,我得到输出:

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

How can I make find_variable accessible inside the value method? 如何在value方法中使find_variable可访问? (In the real parser, these rules are deeply nested, and need to resolve the value without returning the actual name to the top of the parse tree. I cannot just return the text_value and look it up outside.) (在真正的解析器中,这些规则是深层嵌套的,需要解析值而不将实际名称返回到解析树的顶部。我不能只返回text_value并在外部查找它。)

This is a significant weakness in the design of Treetop. 这是Treetop设计中的一个重大弱点。

I (as maintainer) didn't want to slow it down further by passing yet another argument to every SyntaxNode, and break any custom SyntaxNode classes folk have written. 我(作为维护人员)不想通过向每个SyntaxNode传递另一个参数来进一步降低它的速度,并破坏人们编写的任何自定义SyntaxNode类。 These constructors get the "input" object, a Range that selects part of that input, and optionally an array of child SyntaxNodes. 这些构造函数获得“输入”对象,一个选择该输入一部分的Range以及一个可选的子SyntaxNodes数组。 They should have received the Parser itself instead of the input as a member. 他们应该已经收到解析器本身,而不是作为成员输入。

So instead, for my own use (some years back), I made a custom proxy for the "input" and attached my Context to it. 因此,取而代之的是,为我自己使用(几年前),我为“输入”创建了一个自定义代理,并将上下文附加到该输入。 You might get away with doing something similar: 您可能会做类似的事情:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM