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.

151 lines
6.1 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 = ["sin","cos","tan","sqrt"]
operateurs = ["+", "-", "*", "/", "^","opp"]
priorite = {"sin":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)
#nombre
if estUnNombre(token):
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() or pile_op.sommet() == "opp":
#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)
sortie.append(token)
sortie.append("*")
else:
sortie.append(token)
print("c'est un nombre et il est dans le cas sortie == []")
#fonction
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() or pile_op.sommet() == "opp":
#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)
pile_op.empiler("*")
pile_op.empiler(token)
else:
pile_op.empiler(token)
#operateur
elif token in operateurs:
if not (estUnNombre(last_token) or last_token == ")"):
#opérations unaires
if token == "-" :
#opposé
pile_op.empiler("opp")
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)
# "("
elif token == "(":
if sortie != []:
if pile_op.est_vide():
#mul. implicite
pile_op.empiler("*")
pile_op.empiler(token)
else:
if last_token == pile_op.sommet() or pile_op.sommet() == "opp":
#parenthèse qui suit une fonction ou parenthèse normale
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)
pile_op.empiler("*")
pile_op.empiler(token)
else:
pile_op.empiler(token)
# ")"
elif token == ")":
try:
while pile_op.sommet() != "(":
if pile_op.est_vide():
raise SyntaxError(("Mauvais () detail", index_token))
else:
sortie.append(pile_op.depiler())
except IndexError:
raise SyntaxError(("Mauvais parenthésage.", index_token))
if pile_op.sommet() == "(":
pile_op.depiler()
if not pile_op.est_vide():
if pile_op.sommet() in fonctions:
sortie.append(pile_op.depiler())
else:
raise ValueError("Fonction inconnue","n'est pas une fonction connue, ou il manque des espaces.", index_token)
last_token = token
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):
#doc bof
"""sort toutes les fonctions et opérateurs de la pile"""
while not pile.est_vide():
sortie.append(pile.depiler())
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()