如何使用treetop编写动作触发器?

时间:2013-08-08 08:31:14

标签: ruby treetop

每次解析器识别一个令牌时,我都会尝试运行一些代码。

让我们说

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

这里的想法是每次找到puts令牌时执行此foo操作。按原样编码,它不起作用,因为它只被触发一次(在类加载时),当然stuff_i_want.text_value不存在。

有什么想法吗?它甚至可能吗?缺乏关于图书馆的文档并不容易说出来。

2 个答案:

答案 0 :(得分:0)

好吧,我不确定我做了什么值得投票。

无论如何,这是我使用的解决方案:

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

然后剩下的就是在每个要触发效果的节点上定义一个action(*args)方法,并且必须在顶层解析器节点上开始抓取(解析调用返回的那个

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

可选参数传递给每个action方法。您还可以返回虚假值(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

答案 1 :(得分:0)

这可能比您可以使用的解决方案更简单。我不明白为什么你需要打开SyntaxNode类才能获得你想要的功能。您需要做的就是稍微遍历节点(除非我不理解您要完成的任务)。

以下是一个例子:

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