|
|
|
from math import *
|
|
|
|
from Pile import Pile_chaine as Pile
|
|
|
|
|
|
|
|
def infixe2npi(liste_en_infixe):
|
|
|
|
"""conversion d'une liste en notation infixe en une liste en NPI"""
|
|
|
|
|
|
|
|
pile_op = Pile()
|
|
|
|
sortie = []
|
|
|
|
|
|
|
|
fonctions = {"sin","cos","tan","sqrt","factorielle","asin","acos","atan"}
|
|
|
|
operateurs = {"+", "-", "*", "/", "^","opp"}
|
|
|
|
priorite = {"sin":1,
|
|
|
|
"cos":1,
|
|
|
|
"tan":1,
|
|
|
|
"asin":1,
|
|
|
|
"acos":1,
|
|
|
|
"atan":1,
|
|
|
|
"sqrt":1,
|
|
|
|
"factorielle":1,
|
|
|
|
"opp":1,
|
|
|
|
"^":1,
|
|
|
|
"*":2,
|
|
|
|
"/":2,
|
|
|
|
"+":3,
|
|
|
|
"-":3}
|
|
|
|
associativite = {"opp": "droit",
|
|
|
|
"^":"droit",
|
|
|
|
"*":"gauche",
|
|
|
|
"/":"gauche",
|
|
|
|
"+":"gauche",
|
|
|
|
"-":"gauche"}
|
|
|
|
|
|
|
|
last_token = None
|
|
|
|
position_dernier_token = "nulle part"
|
|
|
|
for index_token, token in enumerate(liste_en_infixe):
|
|
|
|
|
|
|
|
if estUnNombre(token) or token in {"pi","e"}:
|
|
|
|
if sortie != []:
|
|
|
|
if pile_op.est_vide():
|
|
|
|
sortie.append(token)
|
|
|
|
sortie.append("*")
|
|
|
|
else:
|
|
|
|
if position_dernier_token == "pile_op":
|
|
|
|
sortie.append(token)
|
|
|
|
if position_dernier_token == "sortie":
|
|
|
|
cleanFx(pile_op, sortie, token)
|
|
|
|
sortie.append(token)
|
|
|
|
sortie.append("*")
|
|
|
|
if last_token == ")":
|
|
|
|
sortie.append(token)
|
|
|
|
sortie.append("*")
|
|
|
|
else:
|
|
|
|
sortie.append(token)
|
|
|
|
position_dernier_token = "sortie"
|
|
|
|
|
|
|
|
elif token in fonctions:
|
|
|
|
if sortie != []:
|
|
|
|
if pile_op.est_vide():
|
|
|
|
pile_op.empiler("*")
|
|
|
|
pile_op.empiler(token)
|
|
|
|
else:
|
|
|
|
if position_dernier_token == "pile_op":
|
|
|
|
pile_op.empiler(token)
|
|
|
|
if position_dernier_token == "sortie":
|
|
|
|
cleanFx(pile_op, sortie, token)
|
|
|
|
pile_op.empiler("*")
|
|
|
|
pile_op.empiler(token)
|
|
|
|
if last_token == ")":
|
|
|
|
pile_op.empiler("*")
|
|
|
|
pile_op.empiler(token)
|
|
|
|
else:
|
|
|
|
pile_op.empiler(token)
|
|
|
|
position_dernier_token = "pile_op"
|
|
|
|
elif token in operateurs:
|
|
|
|
if not (estUnNombre(last_token) or last_token == ")"):
|
|
|
|
#opérations unaires
|
|
|
|
if token == "-" :
|
|
|
|
pile_op.empiler("opp")
|
|
|
|
position_dernier_token = "pile_op"
|
|
|
|
elif token == "+":
|
|
|
|
#identité
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
raise ValueError("Opérateur mal utilisé","n'a ici qu'un seul opérande (ou aucun), quand il devrait en avoir deux.",index_token)
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
while pile_op.sommet() != "(" and (priorite[pile_op.sommet()] < priorite[token] or (priorite[pile_op.sommet()] == priorite[token] and associativite[token] == "gauche")):
|
|
|
|
sortie.append(pile_op.depiler())
|
|
|
|
except IndexError:
|
|
|
|
pass
|
|
|
|
pile_op.empiler(token)
|
|
|
|
position_dernier_token = "pile_op"
|
|
|
|
elif token == "(":
|
|
|
|
if sortie != []:
|
|
|
|
if pile_op.est_vide():
|
|
|
|
pile_op.empiler("*")
|
|
|
|
pile_op.empiler(token)
|
|
|
|
else:
|
|
|
|
if position_dernier_token == "pile_op":
|
|
|
|
pile_op.empiler(token)
|
|
|
|
if position_dernier_token == "sortie":
|
|
|
|
cleanFx(pile_op, sortie, token)
|
|
|
|
pile_op.empiler("*")
|
|
|
|
pile_op.empiler(token)
|
|
|
|
if last_token == ")":
|
|
|
|
pile_op.empiler("*")
|
|
|
|
pile_op.empiler(token)
|
|
|
|
else:
|
|
|
|
pile_op.empiler(token)
|
|
|
|
position_dernier_token = "pile_op"
|
|
|
|
|
|
|
|
elif token == ")":
|
|
|
|
cleanFx(pile_op, sortie, ")")
|
|
|
|
position_dernier_token = "nulle part"
|
|
|
|
|
|
|
|
else:
|
|
|
|
raise ValueError("Fonction inconnue","n'est pas une fonction connue, ou il manque des espaces.", index_token)
|
|
|
|
|
|
|
|
if token == "-" and pile_op.sommet() == "opp":
|
|
|
|
last_token = "opp"
|
|
|
|
elif token == "+" and pile_op.sommet() != "+":
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
last_token = token
|
|
|
|
|
|
|
|
while not pile_op.est_vide():
|
|
|
|
if pile_op.sommet() != "(":
|
|
|
|
sortie.append(pile_op.depiler())
|
|
|
|
else:
|
|
|
|
raise SyntaxError("Mauvais parenthésage. Il manque une parenthèse droite.")
|
|
|
|
return sortie
|
|
|
|
|
|
|
|
def cleanFx(pile, sortie, token):
|
|
|
|
"""dépile toutes les opérations/fx dans la sortie
|
|
|
|
jusqu'à pile vide ou "(".
|
|
|
|
- pas d'erreur de parenthésage si token qui appelle cleanFx
|
|
|
|
n'est pas ")", car ça permet la multipication implicite"""
|
|
|
|
while not pile.est_vide() and pile.sommet() != "(":
|
|
|
|
sortie.append(pile.depiler())
|
|
|
|
|
|
|
|
if token == ")":
|
|
|
|
if not pile.est_vide() and pile.sommet() == "(":
|
|
|
|
pile.depiler()
|
|
|
|
else:
|
|
|
|
raise SyntaxError("Mauvais parenthésage. Il manque une parenthèse gauche.")
|
|
|
|
|
|
|
|
if not pile.est_vide():
|
|
|
|
if pile.sommet() in {"asin","acos","atan","sin","cos","tan","sqrt", "opp","factorielle"}:
|
|
|
|
sortie.append(pile.depiler())
|
|
|
|
|
|
|
|
def estUnNombre(txt):
|
|
|
|
"""indique si la chaine de caractères txt est un nombre réel"""
|
|
|
|
if txt == None : return False
|
|
|
|
if txt[0] == "-" : txt = txt.replace('-','',1)
|
|
|
|
return txt.replace('.','',1).isdigit()
|