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