В настоящее время я реализую оценщик выражений (однострочные выражения, например формулы), основанный на следующем:
- введенное выражение токенизируется для разделения буквенных логических значений, целых чисел, десятичных дробей, строк, функций, идентификаторов (переменных)
- Я реализовал алгоритм Shunting-yard (слегка измененный для обработки функций с переменным числом аргументов), чтобы избавиться от скобок и упорядочить операторы с приличным приоритетом в постфиксном порядке.
- мой маневровый двор просто создает (смоделированную) очередь токенов (с помощью массива мой язык Powerbuilder Classic может определять объекты, но иметь только динамические массивы как собственное хранилище - не истинный список, не словарь), которые я оцениваю последовательно с помощью простая стековая машина
Мой оценщик работает хорошо, но мне все еще не хватает if()
и мне интересно, как поступить.
С моей оценкой постфикса и стекового шунтирующего двора, если я добавлю if()
как другую функцию с истинными и ложными частями, одно if(true, msgbox("ok"), msgbox("not ok"))
сообщение покажет оба сообщения, в то время как я хотел бы показать только одно. Это потому, что когда мне нужно оценить функцию, все ее аргументы уже были оценены и помещены в стек.
Не могли бы вы дать мне способ реализовать if()
это ленивым образом?
Я хотя и рассматривал их как своего рода макрос, но на ранних этапах еще не оценил состояние. Возможно, мне нужно использовать другой вид структуры, кроме очереди, чтобы отдельно хранить условие и выражения «истина / ложь»? На данный момент выражение анализируется перед оценкой, но я также планирую сохранить промежуточное представление как вид предварительно скомпилированного выражения для будущей оценки.
Изменить : после некоторого, хотя по проблеме, я думаю, что я мог бы построить представление моего выражения в виде дерева (AST вместо линейного потока токенов), из которого я мог бы легко игнорировать ту или иную ветвь своего if()
.
Вместо функции, имеющей подпись:
Дайте ему подпись:
Тогда ваша
if
функция будет вызывать соответствующую функцию на основе условия, оценивая только одну из них.источник
Это довольно легко, если вы все компилируете лениво. У вас должны быть какие-то средства, чтобы увидеть, оценивается ли уже значение или требуется дополнительная оценка.
Затем вы можете сделать следующее: Если это литерал или переменная (у вас есть такие ?, т.е. имена функций?), Поместите ее в стек. Если это приложение функции, скомпилируйте ее отдельно и поместите точку входа в стек.
Таким образом, выполнение программы просто зацикливается до тех пор, пока не будет вычислена вершина стека, а не функция. Если он не оценен или не является функцией, вызовите код, на который указывает вершина стека.
источник