If I understand correctly, your problem is not left behind by recursion, this is the structure of the parsing tree.
You correctly eliminated left recursion, but unfortunately the only way to get rid of left recursion is to exclude left recursion in the raw parsing tree. Most of the theory for this material comes down to the correct set of lines. You are still consistent with the same set of rows, so the theory is happy, but you need a left recursive parse tree. Read more about this issue on wikipedia .
AFAIK, you cannot get the original output of the PEG parser so that it remains recursive. However, you can do whatever you want with the exit. So, parse it as an array and then postprocess to give it a nice left structure.
Doing this with a simplified (no spaces, no multi-valued identifiers) grammar:
start = call id = [az] call = arr:id+ { var acc = arr[0] for (i = 1; i < arr.length; i++) { acc = [acc, arr[i]] } return acc; }
This parses abcd to [ [ [ 'a', 'b' ], 'c' ], 'd' ] . I just used + instead of recursion, and then ran through the resulting array, building the structure we needed. Wikipedia has a few notes on how to leave recursion using PEG .
Suppose you need a data structure. If you just want to use parens, replace the action with the following:
var acc = arr[0] for (i = 1; i < arr.length; i++) { acc = acc + '(' + arr[i] + ')' } return acc;
Which gives a(b)(c)(d) .
To return spaces and a multi-line identifier, you can do this:
start = call id = [az]+ _ = [ ]+ 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}