Flat operators

What’s a good way to implement “flat” operators, where I want all the operands as direct children of a single parse node, as opposed to left/right-associative operators that force a particular (binary) grouping?

Naïve attempt:

@top[name=top] { expr }

@tokens {
    pl { "+" }
    int { std.digit+ }

expr { PlusExpr | int }

PlusExpr { expr (pl expr)+ }

(which results in a shift/reduce conflict)

I would like it to generate a parse tree of the form

PlusExpr(1, 2, 3, 4, 5)

when parsing


I could use

@precedence { plus @left }

PlusExpr { expr !plus expr }

and then flatten out the parse tree after parsing, but that seems a bit wasteful (?). Is there any better way?

P.S. Thanks for creating this library, it’s awesome!

If you put the !plus marker in your PlusExpr { expr (pl !plus expr)+ } rule, this seems to work.