J'implémente actuellement un évaluateur d'expressions (expressions sur une seule ligne, comme des formules) basé sur les éléments suivants:
- l'expression entrée est symbolisée pour séparer les booléens littéraux, les entiers, les décimales, les chaînes, les fonctions, les identificateurs (variables)
- J'ai implémenté l'algorithme Shunting-yard (légèrement modifié pour gérer les fonctions avec un nombre variable d'arguments) pour se débarrasser des parenthèses et ordonner les opérateurs avec une priorité décente dans un ordre postfixé
- mon shunting-yard produit simplement une file d'attente (simulée) de jetons (au moyen d'un tableau, mon langage Powerbuilder Classic peut définir des objets, mais n'a que des tableaux dynamiques comme stockage natif - pas une vraie liste, pas de dictionnaire) que j'évalue séquentiellement avec un machine à empiler simple
Mon évaluateur fonctionne bien, mais il me manque encore un if()
et je me demande comment procéder.
Avec mon évaluation shunt-yard postfixée et basée sur la pile, si j'ajoute if()
une autre fonction avec des parties vraies et fausses, un seul if(true, msgbox("ok"), msgbox("not ok"))
affichera les deux messages tandis que je voudrais en afficher un seul. En effet, lorsque j'ai besoin d'évaluer une fonction, tous ses arguments ont déjà été évalués et placés sur la pile.
Pourriez-vous me donner un moyen de mettre if()
en œuvre de manière paresseuse?
J'ai pensé à les traiter comme une sorte de macro, mais au début, je n'ai pas encore évalué l'état. Peut-être que j'ai besoin d'utiliser un autre type de structure qu'une file d'attente pour conserver séparément la condition et les expressions vrai / faux? Pour l'instant, l'expression est analysée avant l'évaluation, mais je prévois également de stocker la représentation intermédiaire comme une sorte d'expression précompilée pour une évaluation future.
Edit : après quelques réflexions sur le problème, je pense que je pourrais construire une représentation arborescente de mon expression (un AST au lieu d'un flux de jeton linéaire), à partir de laquelle je pourrais facilement ignorer l'une ou l'autre branche de ma if()
.
Plutôt que la fonction ayant la signature:
Donnez-lui la signature:
Ensuite, votre
if
fonction appellera la fonction appropriée en fonction de la condition, en évaluant uniquement l'une d'entre elles.la source
C'est assez facile, si vous compilez tout paresseusement. Vous devez avoir un moyen de voir si une valeur est déjà évaluée, ou si elle a besoin de plus de précisions.
Ensuite, vous pouvez faire ce qui suit: S'il s'agit d'un littéral ou d'une variable (en avez-vous?, C'est-à-dire les noms de fonctions?), Poussez-le sur la pile. S'il s'agit d'une application d'une fonction, compilez-la séparément et poussez le point d'entrée sur la pile.
L'exécution d'un programme n'est alors qu'une boucle jusqu'à ce que le haut de la pile soit évalué et non une fonction. S'il n'est pas évalué ou s'il s'agit d'une fonction, appelez le code vers lequel pointe la pile.
la source