Ich implementiere derzeit einen Ausdrucksauswerter (einzeilige Ausdrücke wie Formeln), der auf Folgendem basiert:
- Der eingegebene Ausdruck wird tokenisiert, um Literal-Boolesche Werte, Ganzzahlen, Dezimalstellen, Zeichenfolgen, Funktionen und Bezeichner (Variablen) zu trennen.
- Ich habe den Shunting-Yard-Algorithmus implementiert (leicht modifiziert, um Funktionen mit variabler Anzahl von Argumenten zu handhaben), um Klammern zu entfernen und die Operatoren mit einer anständigen Priorität in einer nachfixierten Reihenfolge zu ordnen
- Mein Rangierplatz erzeugt einfach eine (simulierte) Warteschlange von Token (mithilfe eines Arrays kann meine Powerbuilder Classic-Sprache Objekte definieren, verfügt jedoch nur über dynamische Arrays als nativen Speicher - keine echte Liste, kein Wörterbuch), die ich nacheinander mit a auswerte einfache Stapelmaschine
Mein Evaluator arbeitet gut, aber ich vermisse immer noch einen if()
und frage mich, wie ich vorgehen soll.
Wenn ich bei meiner nachträglichen und stapelbasierten Rangierauswertung if()
als weitere Funktion mit einem wahren und einem falschen Teil hinzufüge , zeigt eine einzelne if(true, msgbox("ok"), msgbox("not ok"))
beide Nachrichten an, während ich nur eine anzeigen möchte. Dies liegt daran, dass beim Auswerten einer Funktion bereits alle Argumente ausgewertet und auf den Stapel gelegt wurden.
Könnten Sie mir eine Möglichkeit geben, if()
faul zu implementieren ?
Ich habe überlegt, diese als eine Art Makro zu verarbeiten, aber zu einem frühen Zeitpunkt habe ich noch keine Zustandsbewertung. Vielleicht muss ich eine andere Art von Struktur als eine Warteschlange verwenden, um die Bedingung und die wahren / falschen Ausdrücke getrennt zu halten? Im Moment wird der Ausdruck vor der Auswertung analysiert, aber ich plane auch, die Zwischendarstellung als eine Art vorkompilierten Ausdruck für die zukünftige Auswertung zu speichern.
Bearbeiten : Nach einigem Nachdenken über das Problem denke ich, ich könnte eine Baumdarstellung meines Ausdrucks erstellen (ein AST anstelle eines linearen Token-Streams), aus der ich den einen oder anderen Zweig von mir leicht ignorieren könnte if()
.
Anstelle der Funktion mit der Signatur:
Gib ihm die Unterschrift:
Dann
if
ruft Ihre Funktion die entsprechende Funktion basierend auf der Bedingung auf und wertet nur eine davon aus.quelle
Es ist ganz einfach, wenn Sie alles träge kompilieren. Sie müssen über einige Mittel verfügen, um festzustellen, ob ein Wert bereits ausgewertet wurde oder ob eine weitere Evlauation erforderlich ist.
Dann können Sie Folgendes tun: Wenn es sich um ein Literal oder eine Variable handelt (haben Sie diese?, Dh Namen von Funktionen?), Schieben Sie sie auf den Stapel. Wenn es sich um eine Anwendung einer Funktion handelt, kompilieren Sie sie separat und verschieben Sie den Einstiegspunkt auf den Stapel.
Die Ausführung eines Programms ist dann lediglich eine Schleife, bis die Oberseite des Stapels ausgewertet wird und keine Funktion mehr. Wenn es nicht ausgewertet wird oder eine Funktion ist, rufen Sie den Code auf, auf den der Stapel oben zeigt.
quelle