diff --git a/infixe.py b/infixe.py deleted file mode 100644 index 83005cf..0000000 --- a/infixe.py +++ /dev/null @@ -1,113 +0,0 @@ -import re - -class Expression: - - def __init__(self, val=None, gauche=None, droite=None): - if Token.isNumber(val) and (gauche != None or droite != None): - raise AttributeError("gauche et droite ne peuvent pas exister si val est un nombre") - self.val = val - self.gauche = gauche - self.droite = droite - - def evalue(self): - if self.val == Token.OPERAND_ADDITION: - return self.gauche.evalue() + self.droite.evalue() - elif self.val == Token.OPERAND_MULTIPLICATION: - return self.gauche.evalue() * self.droite.evalue() - else: - return int(self.val) - - def __str__(self): - if Token.isNumber(self.val): - return str(self.val) - return "(" + str(self.gauche.__str__()) + str(self.val) + str(self.droite.__str__()) + ")" - - -class Token: - ADDITION = "+" - MULTIPLICATION = "*" - PARENTHESE_OUVERTE = "(" - PARENTHESE_FERME = ")" - - NUMBER = re.compile(r'(?:\d+)?.\d+') - - @staticmethod - def isNumber(n): - return Token.NUMBER.match(str(n)) is not None - -def tokenize(text): - buffer = "" - tokens = [] - for char in text: - if Token.isNumber(char): - buffer += char - continue - elif char == " ": - continue - - if buffer != "": - tokens.append(buffer) - buffer = "" - tokens.append(char) - if buffer != "": - tokens.append(buffer) - return tokens - -def arbre(tokens): #-> Expression - print(tokens) - current = None - waiting_before_exp = None - waiting_for_after_exp = None - - i = 0 - while i < len(tokens): - if tokens[i] == "(": - j = i + 1 - innerBrackets = 1 - innerTokens = [] - while tokens[j] != ")" and innerBrackets != 0: - if tokens[j] == "(": - innerBrackets += 1 - elif tokens[j] == ")": - innerBrackets -= 1 - innerTokens.append(tokens[j]) - j += 1 - exp = arbre(innerTokens) - tokens = tokens[:i] + [" "] + tokens[j+1:] - #i -= j+1 - if waiting_for_after_exp != None: - waiting_for_after_exp.droite = exp - waiting_before_exp = waiting_for_after_exp - waiting_for_after_exp = None - else: - waiting_before_exp = exp - - elif tokens[i] == "*" or tokens[i] == "+": - exp = Expression("*") - if Token.isNumber(tokens[i-1]): - exp.gauche = tokens[i-1] - if Token.isNumber(tokens[i+1]): - exp.droite = tokens[i+1] - if Token.isNumber(tokens[i-1]) and Token.isNumber(tokens[i+1]): - return exp - - if tokens[i-1] == ")": - exp.gauche = waiting_before_exp - waiting_before_exp = None - elif tokens[i+1] == "(": - waiting_for_after_exp = exp - print(exp) - elif tokens[i-1] == " ": - exp.gauche = waiting_before_exp - waiting_for_after_exp = exp - else: - raise Exception() - - i += 1 - - return waiting_for_after_exp - - - -if __name__ == "__main__": - print(arbre(tokenize("(2*8)+(4+7)"))) diff --git a/main.py b/main.py index ffc3123..0d3b2c7 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,9 @@ -from reader import * +from misc.parser import * +from misc.tokenizer import * -cal = str(input("Entrez votre calcul en NPI : ")) -print(npi2tree(shutting_yard(tokenize(cal))).evalue()) \ No newline at end of file +while True: + calcul = str(input("Entrez votre calcul en NPI : ")) + tokens = tokenize(calcul) + npi = shutting_yard(tokens) + expression = npi2tree(npi) + print(expression.evalue()) \ No newline at end of file diff --git a/expression.py b/misc/expression.py similarity index 67% rename from expression.py rename to misc/expression.py index d949223..9ce2e8f 100644 --- a/expression.py +++ b/misc/expression.py @@ -1,28 +1,5 @@ import re - -class Token: - NUMBER = 0 - OPERATOR = 1 - PARENTHESE = 2 - FUNCTION = 3 - - @staticmethod - def isNumber(n): - return re.match(r'\d+', str(n)) is not None - - @staticmethod - def getPrecedence(tok): - if tok == "(" or tok == "": - return 4 - elif tok == "*" or tok == "/": - return 3 - elif tok == "+" or tok == "-": - return 2 - - - def __init__(self, type, val): - self.type = type - self.val = val +from math import cos, sin, exp, sqrt class Expression: @@ -42,10 +19,52 @@ class Expression: return self.gauche.evalue() * self.droite.evalue() elif self.val == "/": return self.gauche.evalue() / self.droite.evalue() + elif self.val == "^": + return self.gauche.evalue() ** self.droite.evalue() + + elif self.val == "cos": + return cos(self.gauche.evalue()) + elif self.val == "sin": + return sin(self.gauche.evalue()) + elif self.val == "exp": + return exp(self.gauche.evalue()) + elif self.val == "sqrt": + return sqrt(self.gauche.evalue()) else: return float(self.val) def __str__(self): if Token.isNumber(self.val): return str(self.val) - return "(" + str(self.gauche.__str__()) + str(self.val) + str(self.droite.__str__()) + ")" \ No newline at end of file + return "(" + str(self.gauche.__str__()) + str(self.val) + str(self.droite.__str__()) + ")" + + +class Token: + NUMBER = 0 + OPERATOR = 1 + PARENTHESE = 2 + FUNCTION = 3 + + @staticmethod + def isChar(n): + return re.match(r'[a-z]', str(n)) is not None + + @staticmethod + def isNumber(n): + return re.match(r'\d+', str(n)) is not None + + @staticmethod + def getPrecedence(tok): + if tok == "(" or tok == "" or tok == "^": + return 4 + elif tok == "*" or tok == "/": + return 3 + elif tok == "+" or tok == "-": + return 2 + + def __init__(self, type, val): + self.type = type + self.val = val + + def __str__(self): + return self.val \ No newline at end of file diff --git a/reader.py b/misc/parser.py similarity index 62% rename from reader.py rename to misc/parser.py index fe95253..4365274 100644 --- a/reader.py +++ b/misc/parser.py @@ -1,29 +1,7 @@ -from expression import Token, Expression +from misc.expression import Token, Expression from lib.Pile import Pile_chaine as Pile from lib.File import File_chaine as File -def tokenize(text: str) -> list: - buffer = "" - tokens = [] - for char in text: - #NUMBER - if Token.isNumber(char) or char == ".": - buffer += char - else: - #PUSH - if buffer != "": - tokens.append(Token(Token.NUMBER, buffer)) - buffer = "" - #SINGLE CHAR - if char != " ": - if char == "(" or char == ")": - tokens.append(Token(Token.PARENTHESE, char)) - else: - tokens.append(Token(Token.OPERATOR, char)) - if buffer != "": - tokens.append(Token(Token.NUMBER, buffer)) - return tokens - def shutting_yard(tokens: list) -> File: output = File() opertator = Pile() @@ -53,19 +31,18 @@ def shutting_yard(tokens: list) -> File: return output - def npi2tree(tokens: File) -> Expression: pile = Pile() while not tokens.est_vide(): token = tokens.defiler() - if token.val in ["+", "-", "*", "/"]: - exp = Expression(token.val, pile.depiler(), pile.depiler()) + if token.type == Token.OPERATOR: + a, b = pile.depiler(), pile.depiler() + t = ((a, b) if token.val != "^" else (b, a)) + exp = Expression(token.val, *t) + pile.empiler(exp) + elif token.type == Token.FUNCTION: + exp = Expression(token.val, pile.depiler(), None) pile.empiler(exp) else: pile.empiler(Expression(token.val)) return pile.depiler() - -if __name__ == "__main__": - a = npi2tree(shutting_yard(tokenize("2+44*(4+21)"))).evalue() - print(a) - #print(npi2tree(tokenize("6 4 3 + *"))) \ No newline at end of file diff --git a/misc/tokenizer.py b/misc/tokenizer.py new file mode 100644 index 0000000..818dc48 --- /dev/null +++ b/misc/tokenizer.py @@ -0,0 +1,27 @@ +from misc.expression import Token + +def tokenize(text: str) -> list: + buffer_num = "" + buffer_func = "" + tokens = [] + for char in text: + if Token.isChar(char): + buffer_func += char + elif Token.isNumber(char) or char == ".": + buffer_num += char + else: + if buffer_num != "": + tokens.append(Token(Token.NUMBER, buffer_num)) + buffer_num = "" + if buffer_func != "": + tokens.append(Token(Token.FUNCTION, buffer_func)) + buffer_func = "" + if char == "(" or char == ")": + tokens.append(Token(Token.PARENTHESE, char)) + elif char != " ": + tokens.append(Token(Token.OPERATOR, char)) + if buffer_num != "": + tokens.append(Token(Token.NUMBER, buffer_num)) + if buffer_func != "": + tokens.append(Token(Token.FUNCTION, buffer_func)) + return tokens \ No newline at end of file