Precedence has a manual override - parentheses. Today you let the parser treat a parenthesized expression as a single primary value, so a user can force any grouping they want.
Parse a parenthesized sub-expression as a primary, overriding the default precedence.
Precedence gives a sensible default, but a user needs to override it, and that is
what parentheses are for. The parser handles them in the primary position:
when the primary parser sees an open paren, it starts a fresh expr(0) - parsing a
full expression from the lowest binding power - and then consumes the matching
close paren. The parenthesized expression comes back as a single node, so the
surrounding operators treat it as one atomic value.
That is all it takes. Because the inner expr(0) runs with no precedence floor, the
grouping inside the parens is computed on its own terms, and the result plugs into
the outer expression as a unit. So (1+2)*3 parses with the sum as a subtree of the
multiply, printing ((1 + 2) * 3) - the reverse of what precedence alone would
give. The fully-parenthesized String() from last lesson makes the effect easy to
see.
// in the primary parser: an open paren starts a fresh expr(0),// then the matching close paren is consumed.func (p *Parser) primary() Expr {t := p.next()if t.Kind == TLParen {e := p.expr(0)p.next() // consume ')'return e}// ... Number, and later Cell / Ident}