Grouping and calls both consumed a closing parenthesis on faith, which crashes on unbalanced input. Today you check for the closing parenthesis and report a clear error when it is missing.
Report an error when a grouped subexpression or call is not closed by a matching parenthesis.
Back when you wrote grouping and calls, both simply called next to consume the
closing ), trusting it was there. On input like (1 + 2, that trust is misplaced:
after parsing the inner 1 + 2, the next token is EOF, not ). So before consuming
the ), check for it, and if it is missing, report expected ')' at the position
where the parser is now looking, which for (1 + 2 is the end of input at position
6. Apply the identical guard in the call’s argument list, so sqrt(16 fails the
same clear way.
The opposite case, an extra closing parenthesis like 1 + 2), needs no new code:
the parser finishes the 1 + 2, and the leftover ) is caught by the trailing-token
check from the previous lesson. Between the unexpected-token, end-of-input,
trailing-token, and unclosed-parenthesis checks, the parser now rejects every
malformed shape with a message that names what went wrong and where.
// in the grouping nud, replace the blind p.next() that consumed ")":inner, err := p.parseExpr(0)if err != nil { return nil, err }if p.peek().Kind != RParen {return nil, fmt.Errorf("expected ')' at position %d", p.peek().Pos)}p.next()// apply the same guard before consuming ")" in the call argument list