Parentheses let a writer override precedence and force a grouping the binding powers would not give. Today you handle them as a prefix form that parses a fresh subexpression and expects a closing parenthesis.
Parse a parenthesized subexpression as a prefix form that resets the binding-power floor.
A parenthesis is a prefix form: when nud sees a (, it parses a complete
subexpression starting from a fresh floor of 0, then consumes the matching ).
Resetting the floor to 0 is what makes the parentheses powerful: inside them, no
outer operator’s binding power reaches in, so (2 + 3) groups as a unit even though
the * outside would otherwise pull the 3 away. The result is that (2 + 3) * 4
renders as ((2 + 3) * 4) and will evaluate to 20.
The parentheses themselves produce no node. They are pure grouping: the tree for
(2 + 3) is just the Bin for 2 + 3, indistinguishable from what you would build
if precedence had grouped it that way on its own. For now assume the ) is really
there and simply consume it; noticing when it is missing, and reporting that
clearly, is a job for the errors chapter.
// in nud, alongside the Number case:if t.Kind == LParen {inner, err := p.parseExpr(0) // fresh floor: parse a whole subexpressionif err != nil { return nil, err }p.next() // consume the ")" (matching it comes later)return inner, nil}