为什么在Treetop语法中有时会发出空字符串而不是自定义节点?

时间:2015-05-07 08:49:34

标签: ruby treetop

我喜欢你的建议,关于我使用Treetop的一个反复出现的问题,我无法解决......时不时。我可能错过了一些东西。

我怀疑你们中的许多人都有正确的习惯或习惯来解决这个问题。

我通常使用Treetop,如下所示:

  1. 我在.tt文件中定义我的语法
  2. 我修改它以发出自定义分析树对象 (继承Treetop :: Runtime :: SyntaxNode)。这些课程是 在" parsetree.rb"中定义文件。
  3. 这些自定义对象有一个 to_ast 方法将它们递归转换为" pure" 树梢独立的类(构成我的最终AST)。我有 两个独立的模块(ParseTree& AST)。
  4. 但是,我遇到了一条经典的错误信息,我通常无法修复:

    parsetree.rb:380:in `to_ast': undefined method `to_ast' for SyntaxNode
    offset=149, "":Treetop::Runtime::SyntaxNode (NoMethodError)
    

    我在这里感到困惑,因为一个空字符串""似乎是发出而不是我的一个自定义节点。

    在这个例子中,在这一行380上我有以下代码(它是关于有限状态机)

    # in parsetree.rb
    class Next < Tree
          def to_ast
            ret=Ldl::Ast::Next.new
            ret.name=ns.to_ast
            if cond
              ret.condition=cond.c.to_ast
            end
            ret.actions=acts.to_ast # <==== line 380
            ret
          end
        end
    
     class NextActions < Tree
          def to_ast
            eqs.elements.collect{|eq| eq.to_ast}
          end
        end
    

    我错误的语法是:

    rule nextstate
        space? 'next' space ns:identifier space? cond:('?' space? c:expression)? space
        acts:next_actions? <Ldl::ParseTree::Next>
    end  
    
    rule next_actions
        space? eqs:equation+ space 'end' space <Ldl::ParseTree::NextActions>
    end
    

1 个答案:

答案 0 :(得分:1)

您的问题在于可选表达式的行为。

行为:next_actions是可选的。如果输入中此可选元素不匹配,则不会获得NextActions节点,而是获取epsilon。你应该通过这样的话来检测:

ret.actions = acts.empty? ? [] : acts.to_ast

可能会出现同样的问题,因为标签cond:命名的序列是可选的。如果输入中不存在此序列,则它没有内容“c”。在这种情况下,仍将定义“cond”并且您的“if”语句将为true,但cond.c.to_ast将失败。

简答:当您使用可选表达式时,您应该标记它并测试标记是否为空?在尝试使用内容之前。