If I understand correctly, your problem isn't left recursion, it's the structure of the parse tree.
You've eliminated the left recursion properly, but unfortunately, the only way to get rid of left recursion is by eliminating left recursion in the raw parse tree. Most of the theory for this stuff is just about matching the right set of strings. You are still matching the same set of strings, so the theory is happy, but you wanted a left recursive parse tree. More on that problem on wikipedia.
AFAIK, You can't get the raw output of the PEG parser to be left-recursive. You can, however, do whatever you want with the output. So parse it as an array and then postprocess to give it that nice left-structure.
Doing it with a simplified (no spaces, no multicharacter identifiers) grammar:
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;
}
That parses abcd
to [ [ [ 'a', 'b' ], 'c' ], 'd' ]
. I just used +
instead of recursion, and then ran through the resulting array building the structure we wanted. Wikipedia has some notes on doing left recursion with a PEG.
That's assuming you wanted the data structure. If you just want the parens, replace the action with this:
var acc = arr[0]
for (i = 1; i < arr.length; i++) {
acc = acc + '(' + arr[i] + ')'
}
return acc;
Which gives a(b)(c)(d)
.
To put spaces and multicharacter id's back, you can do this:
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}