There are two different cases to consider, depending on your language syntax. If your language uses parenthesis to indicate function application (eg f(2+1)
) then precedence is irrelevant. The function should be pushed onto the stack and popped out after (for the example above, the result is 2 1 + f
). Alternatively you can treat the function as a value and output it immediately, and output a function invocation operation after the close parenthesis (which should otherwise be treated the same as any other parenthesis), eg f 2 1 + $
, where $
is the function invocation operation.
If your language, however, does not use parenthesis to indicate function invocation, but instead places the argument directly after the function without any special punctuation (eg f 2 + 1
), as is apparently the case for Wikipedia's example, then things are a little more complicated. Note that the expression I just gave ás an example is ambiguous: is f applied to 2 and 1 added to the result, or do we add 2 and 1 together and then call f with the result?
Again, there are two approaches. You can simply push the function to the operator stack when you encounter it and assign it whatever precedence you want. This is the simplest approach, and is apparently what the quoted example has done. There are practical issues, however. Firstly, how do you identify a function? If you have a finite set it's easy, but if you have user defined functions, this means your parser needs too feed back into your environment, which can get messy quickly. And how do you handle functions with multiple arguments?
My feeling is that for this style of syntax, using functions as values that are handier by a function application operator makes a lot more sense. Then, you can simply inject the application operator whenever you read a value and the last thing you read was also a value, so you don't need any special way of telling which identifiers are functions. You can also work with expressions that return functions (which is difficult or impossible with the function-as-operation style). And this means you can use currying to handle multiple argument functions, which is a massive simplification over trying to handle them directly.
The only thing you need to decide then is what the precedence of function application is. The choice is up to you, but in every language I've used that works like this, it has been the most strongly binding operator in the language, and has been right associative. (The only interesting variation being Haskell, which as well as having the strongly binding version described, also has a synonym for it with the symbol $
which is the most weakly binding operator in the language, allowing expressions like f 2 + 1
to apply f to 2 and f $ 2 + 1
to apply it to the whole of the rest of the expression)