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.

155 lines
5.7 KiB

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, 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()