在我正在处理的这个简单的表达式解析器中,我无法避免左递归。本质上,我想将方程'f x y'解析为两个表达式'f x'和'(f x)y'(带隐式括号)。如何在避免左递归和回溯的同时做到这一点?是否必须有中间步骤?
#!/usr/bin/env ruby
require 'rubygems'
require 'treetop'
Treetop.load_from_string DATA.read
parser = ExpressionParser.new
p parser.parse('f x y').value
__END__
grammar Expression
rule equation
expression (w+ expression)*
end
rule expression
expression w+ atom
end
rule atom
var / '(' w* expression w* ')'
end
rule var
[a-z]
end
rule w
[\s\n\t\r]
end
end
答案 0 :(得分:1)
您没有提供有关所需结果的足够信息。特别是,你期望“f(a b)y”解析为“(f(a(b)))y”吗?我假设你做...这意味着一个没有开括号的函数有一个arity。
所以你想说:
rule equation
expression w* var / expression w* parenthesised_list
end
rule parenthesised_list
'(' w* ( expression w* )+ ')'
end
另一方面,如果你有f的arity的外部(语法)知识,并且你想要多次迭代“表达式” - 例如在解析TeX时发生 - 那么你将需要使用语义谓词& {| s | ...}在迭代表达式列表中)。请注意,传递给sempred块的参数不是SyntaxNode(由于此序列子规则尚未成功,因此尚未构造),而是序列中到目前为止累积的节点数组。块返回值的真实性决定了解析结果并可以停止迭代。
您可能考虑使用的另一个工具是先行(!stuff_I_dont_expect_to_follow或& stuff_that_must_follow)。
中提出这些问题