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