Calling a function is written name(args). Today you parse call expressions by treating the opening parenthesis as an infix operator with the tightest precedence of all.
Parse a call expression into a node holding the callee and its argument expressions.
A call like add(1, 2) is really an infix use of (: the thing on its left
is the function being called, and inside the parentheses is a comma-separated list
of argument expressions. Registering ( as an infix parse function at the
highest precedence, CALL, is what makes this work inside the Pratt loop you
already have.
That top precedence is why a + b(c) parses as (a + b(c)) - the call to b
binds tighter than the +, so b(c) forms first and only then is added to a.
The callee is any expression, not just a name, which will matter once functions
return other functions. Arguments are parsed with full precedence, so
add(1, 2 * 3) correctly groups its second argument as (2 * 3).
type CallExpression struct { Function Expression; Arguments []Expression }const ( /* ...existing levels... */ CALL ) // highest precedence// register '(' as an INFIX parse function at CALL precedence:// the left expression is the callee; parse the comma-separated argsprecedences["("] = CALL