我喜欢你的建议,关于我使用Treetop的一个反复出现的问题,我无法解决......时不时。我可能错过了一些东西。
我怀疑你们中的许多人都有正确的习惯或习惯来解决这个问题。
我通常使用Treetop,如下所示:
但是,我遇到了一条经典的错误信息,我通常无法修复:
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
答案 0 :(得分:1)
您的问题在于可选表达式的行为。
行为:next_actions是可选的。如果输入中此可选元素不匹配,则不会获得NextActions节点,而是获取epsilon。你应该通过这样的话来检测:
ret.actions = acts.empty? ? [] : acts.to_ast
可能会出现同样的问题,因为标签cond:命名的序列是可选的。如果输入中不存在此序列,则它没有内容“c”。在这种情况下,仍将定义“cond”并且您的“if”语句将为true,但cond.c.to_ast将失败。
简答:当您使用可选表达式时,您应该标记它并测试标记是否为空?在尝试使用内容之前。