You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
6.2 KiB

from Pile import Pile_chaine as Pile
from math import *
from infixe import estUnNombre
class Expression:
def __init__(self, racine, gauche, droit):
"""initialisation d'un objet 'Expression'"""
self.racine = racine
self.gauche = gauche
self.droit = droit
def evalue(self):
"""renvoie la valeur de l'expression
si 1 seul argument alors on prend le fils gauche"""
#fonctions
if self.racine == "sin": return sin(self.gauche.evalue())
if self.racine == "cos": return cos(self.gauche.evalue())
if self.racine == "tan": return tan(self.gauche.evalue())
if self.racine == "asin": return asin(self.gauche.evalue())
if self.racine == "acos": return acos(self.gauche.evalue())
if self.racine == "atan": return atan(self.gauche.evalue())
if self.racine == "opp": return - self.gauche.evalue()
if self.racine == "sqrt": return sqrt(self.gauche.evalue())
if self.racine == "factorielle": return factorial(self.gauche.evalue())
#operateurs
if self.racine == "+": return self.gauche.evalue() + self.droit.evalue()
if self.racine == "-": return self.gauche.evalue() - self.droit.evalue()
if self.racine == "*": return self.gauche.evalue() * self.droit.evalue()
if self.racine == "/": return self.gauche.evalue() / self.droit.evalue()
if self.racine == "^": return self.gauche.evalue() ** self.droit.evalue()
#constantes
if self.racine == "pi": return pi
if self.racine == "e": return exp(1)
if "." in self.racine:
return float(self.racine)
return int(self.racine)
def __str__(self):
"""affiche l'expression"""
priorite = {"sin":1,
"cos":1,
"tan":1,
"sqrt":1,
"asin":1,
"acos":1,
"atan":1,
"factorielle":1,
"opp":1,
"^":2,
"*":4,
"/":4,
"+":5,
"-":5}
associativite = {"opp":"droit",
"^":"droit",
"*":"gauche",
"/":"gauche",
"+":"gauche",
"-":"gauche"}
pas_commutatif = ["^","/","-"]
if self.racine in ["opp","!", "^", "*", "/", "+", "-"]:
gauche = str(self.gauche)
#definitivement à améliorer
if self.droit == None:
# racine est "-" (unaire) ou "opp"
priorite_racine = priorite[self.racine]
priorite_gauche = priorite.get(self.gauche.racine, -1)
#test
print(self.gauche.racine)
#test
if self.gauche.racine[0] == "-" or priorite_racine <= priorite_gauche:
gauche = parentheses(gauche)
return "-" + gauche
droit = str(self.droit)
priorite_racine = priorite[self.racine]
priorite_gauche = priorite.get(self.gauche.racine, -1)
priorite_droit = priorite.get(self.droit.racine, -1)
if (self.gauche.racine == "opp" or (self.gauche.racine != "-" and self.gauche.racine[0] == "-")) and self.racine not in ["+","-"]:
gauche = parentheses(gauche)
if self.droit.racine == "opp" or (self.droit.racine != "-" and self.droit.racine[0] == "-"):
droit = parentheses(droit)
if priorite_racine < priorite_gauche:
gauche = parentheses(gauche)
if priorite_racine < priorite_droit:
droit = parentheses(droit)
if self.racine in pas_commutatif:
if priorite_racine == priorite_droit and associativite[self.racine] == "gauche":
droit = parentheses(droit)
if priorite_racine == priorite_gauche and associativite[self.racine] == "droit":
gauche = parentheses(gauche)
return gauche + self.racine + droit
if self.racine in ["asin","acos","atan","sin","cos","tan","sqrt","factorielle"]:
return self.racine + "(" + str(self.gauche) + ")"
return str(self.racine)
def parentheses(txt):
"""ajoute des parentheses à txt"""
return "(" + txt + ")"
def npi2tree_original(liste_en_npi):
#obsolète (il faudrait mettre à jour la liste de fonctions)
"""conversion d'une liste en NPI en un arbre"""
pile_expr = Pile()
for element in liste_en_npi:
if element in ["+", "*","-","/", "^"]:
fils_droit = pile_expr.depiler()
fils_gauche = pile_expr.depiler()
pile_expr.empiler(Expression(element, fils_gauche, fils_droit))
elif element in ["sin","cos","tan", "opp"]:
pile_expr.empiler(Expression(element, pile_expr.depiler(),None))
else:
pile_expr.empiler(Expression(element, None, None))
return pile_expr.sommet()
#renommer la fonction !...
def npi2tree(liste, etat_affichage):
"""conversion d'une liste en NPI ou NP en un arbre"""
pile_expr = Pile()
for i,element in enumerate(liste):
if element in ["+","-", "*","/", "^"]:
fils_gauche = pile_expr.depiler()
fils_droit = pile_expr.depiler()
if etat_affichage == "post-expr" or etat_affichage == "inf":
fils_gauche, fils_droit = fils_droit, fils_gauche
pile_expr.empiler(Expression(element, fils_gauche, fils_droit))
elif element in ["asin","acos","atan","sin","cos","tan", "opp", "sqrt","factorielle"]:
pile_expr.empiler(Expression(element, pile_expr.depiler(), None))
elif estUnNombre(element) or element in ["pi","e"]:
pile_expr.empiler(Expression(element, None, None))
else:
raise ValueError("Fonction inconnue","n'est pas une fonction connue, ou il manque des espaces.", i)
if pile_expr.taille() == 2:
raise SyntaxError("Il manque un opérateur.")
if pile_expr.taille() > 2:
raise SyntaxError("Il manque " + str(pile_expr.taille() - 1) + " opérateurs.")
return pile_expr.sommet()