如果我理解正确,您的问题不是左递归,而是解析树的结构。
您已经正确地消除了左递归,但不幸的是,摆脱左递归的唯一方法是在原始分析树中消除左递归。这些东西的大部分理论只是匹配正确的字符串集。您仍然匹配同一组字符串,因此理论上很满意,但您需要一个左递归解析树。更多关于 wikipedia上的问题。
AFAIK,你不能让 PEG 解析器的原始输出是左递归的。但是,您可以对输出做任何您想做的事情。因此,将其解析为一个数组,然后进行后处理以使其具有良好的左结构。
使用简化的(无空格,无多字符标识符)语法:
start = call
id = [a-z]
call
= arr:id+ {
var acc = arr[0]
for (i = 1; i < arr.length; i++) {
acc = [acc, arr[i]]
}
return acc;
}
解析abcd
为[ [ [ 'a', 'b' ], 'c' ], 'd' ]
. 我只是使用+
而不是递归,然后遍历生成的数组来构建我们想要的结构。维基百科有一些关于使用 PEG 进行左递归的注释。
那是假设您想要数据结构。如果您只想要括号,请将操作替换为:
var acc = arr[0]
for (i = 1; i < arr.length; i++) {
acc = acc + '(' + arr[i] + ')'
}
return acc;
这给了a(b)(c)(d)
.
要放回空格和多字符 id,您可以这样做:
start = call
id = [a-z]+
_ = [ ]+
call
= a:id as:arg* {
arr = [a].concat(as)
var acc = arr[0]
for (i = 1; i < arr.length; i++) {
acc = acc + '(' + arr[i] + ')'
}
return acc;
}
arg = _ a:id {return a}