简体   繁体   English

如何用树梢编码动作触发器?

[英]How to code an action trigger with treetop?

I'm trying to have some bit of code running each time the parser recognises a token. 每当解析器识别出令牌时,我都试图运行一些代码。

Let's say 比方说

grammar FooBar

  rule start
    (foo "\n")+
  end

  rule foo
    stuff_i_want:([a-z]+) {
       puts "Hi there I found: #{stuff_i_want.text_value}"
     }
  end

end

The idea here would be to have this puts action execute each time the foo token is found. 这里的想法是每次发现foo令牌时都执行puts操作。 Coded as is, it does not work as it is triggered only once (at the class loading time) and of course stuff_i_want.text_value does not exist then. 照原样编码,它不起作用,因为它仅被触发一次(在类加载时),当然, stuff_i_want.text_value不存在。

Any idea? 任何想法? Is it even possible? 可能吗 The lack of documentation on the library does not make it easy to tell. 库上缺少文档并不容易说明。

Well, I'm not sure what I did to deserve the downvote. 好吧,我不确定我应该做些什么来减少票数。

Anyway, here is the solution I used: 无论如何,这是我使用的解决方案:

node_extension.rb node_extension.rb

module Crawlable

  def crawl *args
    continue = true
    continue = action(*args) if respond_to? :action

    return if !continue || elements.nil?

    elements.each do |elt|
      elt.crawl(*args)
    end
  end

end

# reopen the SyntaxNode class and include the module to add the functionality
class Treetop::Runtime::SyntaxNode

  include Crawlable

end

then all is left is to define a action(*args) method on each node you want to trigger an effect on and have to start the crawling on the top parser node (the one returned by the parse call 然后剩下的就是在每个要在其上触发效果的节点上定义一个action(*args)方法,并且必须开始在顶部解析器节点上进行爬网(由解析调用返回的那个)

parse_tree = FooBarParser.new.parse "mycontent"
parse_tree.crawl # add optional parameters for context/state

The optional parameters are passed to each action method. 可选参数传递给每个action方法。 You can also return a falsey value ( false or nil ) in action in order to stop the subtree crawling. 您还可以返回一个falsey值( falsenil )以停止子树爬网。

grammar FooBar

  rule start
    (foo "\n")+
  end

  rule foo
    stuff_i_want:([a-z]+) {
       def action
         puts "Hi there I found: #{stuff_i_want.text_value}"

         false
       end
     }
  end

end

This might be a simpler solution than the one you can up with. 这可能是比您可以使用的解决方案更简单的解决方案。 I can't see why you would need open up the SyntaxNode class in order to get the functionality that you want. 我看不到为什么您需要打开SyntaxNode类才能获得所需的功能。 All you need to do is traverse the nodes a little bit more (unless I'm not understanding what you're trying to accomplish). 您需要做的是更多地遍历节点(除非我不理解您要完成的工作)。

Here's an example: 这是一个例子:

require 'treetop'

Treetop.load_from_string DATA.read

parser = FooBarParser.new

parser.parse("hello\nok\nmorestuff\n").action

__END__
grammar FooBar
  rule start
     (foo "\n")+
     {
        def action
           elements.each {|e| e.elements[0].action }
        end
     }
  end

  rule foo
    stuff_i_want:([a-z]+)
    {
       def action
          puts "Hi there I found: #{stuff_i_want.text_value}"
       end
    }
  end
end

# => Hi there I found: hello
#    Hi there I found: ok
#    Hi there I found: morestuff

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

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