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.
167 lines
7.0 KiB
167 lines
7.0 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 == "opp": return - self.gauche.evalue()
|
|
if self.racine == "sqrt": return sqrt(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()
|
|
|
|
|
|
if "." in self.racine:
|
|
return float(self.racine)
|
|
return int(self.racine)
|
|
|
|
def __str__(self):
|
|
"""affiche l'expression"""
|
|
priorite = {"opp":1,
|
|
"!":1,
|
|
"^":2,
|
|
"sin":3,
|
|
"cos":3,
|
|
"tan":3,
|
|
"sqrt":3,
|
|
"*":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] == "-":
|
|
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 ["sin","cos","tan","sqrt"]:
|
|
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):
|
|
"""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 element in 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 ["sin","cos","tan", "opp", "sqrt"]:
|
|
pile_expr.empiler(Expression(element, pile_expr.depiler(), None))
|
|
elif estUnNombre(element):
|
|
pile_expr.empiler(Expression(element, None, None))
|
|
else:
|
|
#à compléter
|
|
raise ValueError("Fonction inconnue","n'est pas une fonction connue, ou il manque des espaces.", element)
|
|
print("Taille de pile_expr à la fin de la boucle : " , pile_expr.taille())
|
|
if pile_expr.taille() == 2:
|
|
raise SyntaxError(("Il manque un opérateur. L'étoile ( « ★ » ) indique la position de l'opérateur manquant dans l'expression.", pile_expr))
|
|
if pile_expr.taille() > 2:
|
|
raise SyntaxError(("Il manque " + str(pile_expr.taille() - 1) + " opérateurs. L'étoile ( « ★ » ) indique la position des opérateurs manquants dans l'expression.", pile_expr))
|
|
return pile_expr.sommet()
|
|
|
|
def fonctionsAvecArgument(lst_expr):
|
|
#la clarifier un peu, peut-être ?
|
|
"""vérifie que les fonctions aient des arguments, mêmes incorrects
|
|
ex : `sin ) 2 +` est OK.Plus tard l'expression sera vérifiée
|
|
par d'autres fonctions qui verront les erreurs (parenthèses..)
|
|
Le but est d'éviter que les expression comme `2 sin` soit vues justes
|
|
par shunting-yard"""
|
|
fonctions = ["sin","cos","tan", "sqrt"]
|
|
lst_expr_stripped = list(filter(lambda x: x != "+" and x != "-", lst_expr))
|
|
if lst_expr_stripped[-1] in fonctions: return False
|
|
#si à droite, pas un nombre ou une parenthèse fermante
|
|
fx_a_gauche = False
|
|
for terme in lst_expr_stripped:
|
|
if fx_a_gauche == True:
|
|
if terme in [")", "*", "/"]: return False
|
|
|
|
if terme in fonctions:
|
|
fx_a_gauche = True
|
|
|
|
#return not in fonctions
|
|
|
|
def inserer_dans_liste(element, lst, indice):
|
|
"""insère l'item `element` dans la liste `lst` à l'indice `indice`"""
|
|
return
|
|
|