Abhängig von Ihrer Sprachsyntax sind zwei verschiedene Fälle zu berücksichtigen. Wenn Ihre Sprache Klammern verwendet, um die Funktionsanwendung anzuzeigen (z. B. f(2+1)
), ist der Vorrang irrelevant. Die Funktion sollte auf den Stapel geschoben und danach herausgesprungen werden (für das obige Beispiel ist das Ergebnis 2 1 + f
). Alternativ können Sie die Funktion als Wert behandeln und sofort ausgeben und eine Funktionsaufrufoperation nach der geschlossenen Klammer ausgeben (die ansonsten wie jede andere Klammer behandelt werden sollte), z. B. f 2 1 + $
wo $
sich die Funktionsaufrufoperation befindet.
Wenn Ihre Sprache jedoch keine Klammern verwendet, um den Funktionsaufruf anzuzeigen, sondern das Argument direkt nach der Funktion ohne spezielle Interpunktion (z. B. f 2 + 1
) platziert, wie dies anscheinend im Beispiel von Wikipedia der Fall ist, sind die Dinge etwas komplizierter. Beachten Sie, dass der Ausdruck, den ich gerade als Beispiel gegeben habe, nicht eindeutig ist: Wird f auf 2 und 1 angewendet, die zum Ergebnis hinzugefügt werden, oder addieren wir 2 und 1 zusammen und rufen dann f mit dem Ergebnis auf?
Auch hier gibt es zwei Ansätze. Sie können die Funktion einfach auf den Operator-Stack übertragen, wenn Sie darauf stoßen, und ihr die gewünschte Priorität zuweisen. Dies ist der einfachste Ansatz und anscheinend das, was das zitierte Beispiel getan hat. Es gibt jedoch praktische Probleme. Wie identifizieren Sie zunächst eine Funktion? Wenn Sie eine endliche Menge haben, ist es einfach, aber wenn Sie benutzerdefinierte Funktionen haben, bedeutet dies, dass Ihr Parser auch Rückmeldungen in Ihre Umgebung benötigt, was schnell chaotisch werden kann. Und wie gehen Sie mit Funktionen mit mehreren Argumenten um?
Meiner Meinung nach ist es für diesen Syntaxstil viel sinnvoller, Funktionen als Werte zu verwenden, die von einem Funktionsanwendungsoperator handlicher sind. Dann können Sie den Anwendungsoperator einfach einfügen, wenn Sie einen Wert lesen, und das letzte, was Sie gelesen haben, war auch ein Wert, sodass Sie keine spezielle Methode benötigen, um festzustellen, welche Bezeichner Funktionen sind. Sie können auch mit Ausdrücken arbeiten, die Funktionen zurückgeben (was mit dem Funktionsstil schwierig oder unmöglich ist). Dies bedeutet, dass Sie Currying verwenden können, um mehrere Argumentfunktionen zu verarbeiten. Dies ist eine massive Vereinfachung gegenüber dem Versuch, sie direkt zu verarbeiten.
Das einzige, was Sie dann entscheiden müssen, ist, welche Priorität die Funktionsanwendung hat. Die Wahl liegt bei Ihnen, aber in jeder Sprache, die ich verwendet habe und die so funktioniert, war es der am stärksten bindende Operator in der Sprache und war richtig assoziativ. (Die einzige interessante Variante ist Haskell, das neben der beschriebenen stark bindenden Version auch ein Synonym für das Symbol hat, $
das der am schwächsten bindende Operator in der Sprache ist und Ausdrücke wie f 2 + 1
f bis 2 f $ 2 + 1
anwenden und anwenden lässt es auf den gesamten Rest des Ausdrucks)
sin( max( 2 3) / 3 * 3.1415)