tl;dr What would be a simple way of incorporating functions into a Shunting-Yard algorithm implementation?
If only expressions like function(arg1, arg2, arg3)
were allowed (where function
is some builtin function), then it would be really easy, since I could just treat function
like an operator. But consider a case where the user defines their own function like f = function
, then calls f(arg1, arg2, arg3)
. In this case I would need a strongly-typed AST to detect at compile time what f
's type is in order to see that the proceeding tokens ((arg1, arg2, arg3)
) are actually a function call, and not just a construction of a tuple.
Even worse, consider (f)()
where f
is a user-defined nullary function. Then when I get to f
, even if I know that it's a function, the next token will be )
, which is not the start of a valid function call. What about (l[i])()
, where l
is a list of functions?
At the most general level, I understand grammatically that when we have a statement like [expression], "(", [expression], ")"
, then we know that we're calling a function. However, I'm not quite sure how to check this without implementation an AST (which, for simplicity's sake, I would rather not do).
I could store a list of all operator and "bracket" tokens, and then when I reach the "(" in a supposed function call I just check whether the last non-bracket token was an operator. If it was an operator then the "(" represents a subexpression, like in 5 * (3 - 8)
. If it wasn't an operator, then the "(" represents a function call. However, this method feels easily broken. For example, what if there where some operator $
that was "unary left-associative", so that (expression $)(args)
was valid? Then the algorithm would fail unless I had special checking for $
. What if there was a comment between the function and the function call, like function \* comment *\ (args)
? Or even worse, something like
function \\ lol the last token in this comment is an operator +
(args)
These would require implementing handlers a lot of special cases, and I'm wondering if there's a better way of doing it.