Actualmente estoy implementando un evaluador de expresiones (expresiones de línea única, como fórmulas) basado en lo siguiente:
- la expresión ingresada se tokeniza para separar booleanos literales, enteros, decimales, cadenas, funciones, identificadores (variables)
- Implementé el algoritmo Shunting-yard (ligeramente modificado para manejar funciones con un número variable de argumentos) para deshacer el paréntesis y ordenar a los operadores con una precedencia decente en un orden pospuesto
- mi patio de maniobras simplemente produce una cola (simulada) de tokens (por medio de una matriz, mi lenguaje Powerbuilder Classic puede definir objetos, pero solo tiene matrices dinámicas como almacenamiento nativo, no una lista verdadera, ningún diccionario) que evalúo secuencialmente con un máquina de pila simple
Mi evaluador está funcionando bien, pero todavía me falta un if()
y me pregunto cómo proceder.
Con mi evaluación de desviación fijada y basada en la pila, si agrego if()
como otra función con partes verdaderas y falsas, un solo if(true, msgbox("ok"), msgbox("not ok"))
mostrará ambos mensajes, mientras que me gustaría mostrar solo uno. Esto se debe a que cuando necesito evaluar una función, todos sus argumentos ya han sido evaluados y colocados en la pila.
¿Podría darme alguna forma de implementar if()
de manera perezosa?
Pensé en procesarlos como una especie de macro, pero al principio aún no tengo la evaluación de la condición. ¿Quizás necesito usar otro tipo de estructura que no sea una cola para mantener por separado la condición y las expresiones verdadero / falso? Por ahora, la expresión se analiza antes de la evaluación, pero también planeo almacenar la representación intermedia como una especie de expresión precompilada para una evaluación futura.
Editar : después de un poco sobre el problema, creo que podría construir una representación en árbol de mi expresión (un AST en lugar de una secuencia de token lineal), desde la cual podría ignorar fácilmente una u otra rama de mi if()
.
En lugar de la función que tiene la firma:
Dale la firma:
Luego, su
if
función llamará a la función apropiada en función de la condición, solo evaluando una de ellas.fuente
Es bastante fácil, si compila todo perezosamente. Debe tener algunos medios para ver si un valor ya está evaluado o si necesita más evaluación.
Luego puede hacer lo siguiente: Si es un literal o una variable (¿los tiene ?, es decir, nombres de funciones?), Empújelo en la pila. Si es una aplicación de una función, compílela por separado y presione el punto de entrada en la pila.
La ejecución de un programa es, simplemente, un bucle hasta que se evalúa la parte superior de la pila y no una función. Si no se evalúa o es una función, llame al código al que apunta la parte superior de la pila.
fuente