Obecnie implementuję ewaluator wyrażeń (wyrażenia jednowierszowe, takie jak formuły) w oparciu o:
- wprowadzone wyrażenie jest tokenizowane w celu oddzielenia literalnych boolanów, liczb całkowitych, dziesiętnych, ciągów, funkcji, identyfikatorów (zmiennych)
- Zaimplementowałem algorytm Shunting-yard (lekko zmodyfikowany do obsługi funkcji o zmiennej liczbie argumentów), aby pozbyć się nawiasów i uporządkować operatorów z przyzwoitym pierwszeństwem w ustalonej kolejności
- moje pole manewrowe po prostu tworzy (symulowaną) kolejkę tokenów (za pomocą tablicy mój język Powerbuilder Classic może definiować obiekty, ale tylko macierze dynamiczne jako pamięć natywną - nie jest to prawdziwa lista, brak słownika), które oceniam sekwencyjnie za pomocą prosta maszyna do układania w stosy
Mój ewaluator działa dobrze, ale wciąż mi brakuje if()
i zastanawiam się, jak postępować.
Z moją postfuntowaną postfunkcją i oceną stosu, jeśli dodam if()
jako inną funkcję z częściami prawdziwą i fałszywą, jeden if(true, msgbox("ok"), msgbox("not ok"))
wyświetli obie wiadomości, podczas gdy chciałbym pokazać tylko jedną. Dzieje się tak, ponieważ gdy muszę ocenić funkcję, wszystkie jej argumenty zostały już ocenione i umieszczone na stosie.
Czy możesz dać mi sposób na wdrożenie if()
w leniwy sposób?
Myślałem o przetwarzaniu ich jako rodzaju makra, ale na początku nie miałem jeszcze oceny stanu. Być może muszę użyć innej struktury niż kolejka, aby oddzielnie zachować warunek i wyrażenia prawda / fałsz? Na razie wyrażenie jest analizowane przed oceną, ale planuję również przechowywać reprezentację pośrednią jako rodzaj wstępnie skompilowanego wyrażenia do przyszłej oceny.
Edycja : po kilku rozważaniach na temat problemu, myślę, że mógłbym zbudować drzewną reprezentację mojego wyrażenia (AST zamiast liniowego strumienia tokena), z którego mógłbym łatwo zignorować jedną lub drugą gałąź mojego if()
.
Zamiast funkcji posiadającej podpis:
Podaj podpis:
Wtedy twoja
if
funkcja wywoła odpowiednią funkcję na podstawie warunku, oceniając tylko jedną z nich.źródło
Jest to dość łatwe, jeśli wszystko leniwie skompilujesz. Musisz mieć jakieś środki, aby sprawdzić, czy wartość jest już oszacowana, czy też wymaga więcej ewaluacji.
Następnie możesz wykonać następujące czynności: Jeśli jest to literał lub zmienna (czy masz je?, Tj. Nazwy funkcji?), Pchnij je na stos. Jeśli jest to zastosowanie funkcji, skompiluj ją osobno i wciśnij punkt wejścia na stosie.
Wykonywanie programu jest więc zapętleniem, dopóki szczyt stosu nie zostanie oceniony, a nie funkcja. Jeśli nie jest to wartościowane lub funkcja, wywołaj kod, na który wskazuje góra stosu.
źródło