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.

178 lines
7.5 KiB

from Pile import Pile_chaine as Pile
from math import *
def infixe2npi(liste_en_infixe):
"""conversion d'une liste en notation infixe à une liste en npi"""
pile_op = Pile()
sortie = []
fonctions = ["asin","acos","atan","sin","cos","tan","sqrt","factorielle"]
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
print(40*"=")
for index_token, token in enumerate(liste_en_infixe):
print(20*"-")
print("token", token)
if estUnNombre(token) or token in ["pi","e"]:
if sortie != []:
if pile_op.est_vide():
#mul. implicite
sortie.append(token)
sortie.append("*")
print("c'est un nombre et il est dans le cas pile_op.est_vide()")
else:
print(last_token, pile_op.sommet())
if last_token == pile_op.sommet():
#opération binaire normale ou fonction (avec avant elle ultimement une opération binaire)
sortie.append(token)
print("c'est un nombre et il est dans le cas last_token == pile_op.sommet()")
if last_token == sortie[-1]:
print("c'est un nombre et il est dans le cas last_token == sortie[-1]")
#on a affaire à une expression (chiffre (... 2), opération (... +), fonction (... fx)) qui est in fine un nombre
cleanFx(pile_op, sortie, token)
sortie.append(token)
sortie.append("*")
if last_token == ")":
sortie.append(token)
sortie.append("*")
else:
sortie.append(token)
print("c'est un nombre et il est dans le cas sortie == []")
elif token in fonctions:
if sortie != []:
if pile_op.est_vide():
#mul. implicite
pile_op.empiler("*")
pile_op.empiler(token)
else:
if last_token == pile_op.sommet():
#composition de fonctions, ou fonction qui suit un opérateur
pile_op.empiler(token) #normal
if last_token == sortie[-1]:
#le dernier element est l'argument de la fonction (ou
#des fonctions, composées) sur la pile - s'il y a des fonctions
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)
elif token in operateurs:
if not (estUnNombre(last_token) or last_token == ")"):
#opérations unaires
if token == "-" :
#opposé
pile_op.empiler("opp")
print("'-' qui devient 'opp'")
elif token == "+":
#identité
if last_token in fonctions:
print("'+' identité juste après une fonction")
#raise ValueError("Opérateur mal utilisé","est ici ambigu ; addition ou identité ?",index_token)
print("le plus est 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)
elif token == "(":
if sortie != []:
if pile_op.est_vide():
#mul. implicite
pile_op.empiler("*")
pile_op.empiler(token)
print("parenthèse insérée dans la pile AVEC une multiplication -- pile_op.est_vide()")
else:
if last_token == pile_op.sommet():
#parenthèse qui suit une fonction ou parenthèse normale
pile_op.empiler(token) #normal
print("parenthèse insérée dans la pile SANS une multiplication -- last_token == pile_op.sommet()")
if last_token == sortie[-1]:
#le dernier element est l'argument de la fonction (ou
#des fonctions, composées) sur la pile - s'il y a des fonctions
cleanFx(pile_op, sortie, token)
pile_op.empiler("*")
pile_op.empiler(token)
print("parenthèse insérée dans la pile AVEC une multiplication -- last_token == sortie[-1]")
else:
pile_op.empiler(token)
print("parenthèse insérée dans la pile SANS une multiplication -- il n'y a rien en sortie")
elif token == ")":
cleanFx(pile_op, sortie, ")")
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
print("état de la sortie après le token : ", sortie)
while not pile_op.est_vide():
if pile_op.sommet() != "(":
sortie.append(pile_op.depiler())
else:
raise SyntaxError(("Mauvais parenthésage", 0))
print("infixe2npi : ",sortie)
return sortie
def cleanFx(pile, sortie, token):
"""dépile tous les tokens dans la sortie
- pas d'erreur de parenthésage si token != ")"
car on veut garder la multipication implicite"""
while not pile.est_vide() and pile.sommet() != "(":
sortie.append(pile.depiler())
if not pile.est_vide() and pile.sommet() == "(":
pile.depiler()
else:
if token == ")":
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())
# ↓ sert à quelque chose ??
#return sortie
def estUnNombre(txt):
"""indique si la chaine de caractères txt est un nombre (entier (négatif) ou flottant)"""
if txt == None : return False
if txt[0] == "-" : txt = txt.replace('-','',1)
return txt.replace('.','',1).isdigit()