diff --git a/python_symb/Expressions/tree.py b/python_symb/Expressions/tree.py index c68f9a4..0d4af3a 100644 --- a/python_symb/Expressions/tree.py +++ b/python_symb/Expressions/tree.py @@ -24,6 +24,10 @@ class Tree(ABC): self.depth_first_order = depth_first_order self.children = children if children else [] + @property + def is_leaf(self) -> bool: + return not self.children + def __repr__(self) -> str: return f'Tree({self.value}, {self.children})' if self.children else f'Tree({self.value})' diff --git a/python_symb/MathTypes/operator_file.py b/python_symb/MathTypes/operator_file.py index 86c779c..0345f83 100644 --- a/python_symb/MathTypes/operator_file.py +++ b/python_symb/MathTypes/operator_file.py @@ -7,18 +7,22 @@ class Operator(Symbols): """ Represent an operator, like +, *, sin, anything that can be applied to an expression """ - instances = [] + instances = {} - def __init__(self, name: str, precedence: int, call: Callable): + def __init__(self, name: str, precedence: int, call: Callable, repeated_op: Operator = None): """ :param name of the operator :param precedence: precedence of the operator, higher is better :param call: function to apply the operator + :param repeated_op: if you repeat the operator what do you get ? + for exemple a+a+a+a -> 4*a, the repeated_op of Add is Mul """ + super().__init__(name) self.precedence = precedence self.call = call - Operator.instances.append(self) + self.repeated_op = repeated_op + Operator.instances[name] = self def __repr__(self): return f'{self.name}' @@ -29,11 +33,11 @@ class UnaryOperator(Operator): Represent a unary operator, like sin, cos, - etc... all operators that take only one argument """ - instances = [] + instances = {} - def __init__(self, name: str, precedence: int, call: Callable): - UnaryOperator.instances.append(self) - super().__init__(name, precedence, call) + def __init__(self, name: str, precedence: int, call: Callable, repeated_op: Operator = None): + UnaryOperator.instances[name] = self + super().__init__(name, precedence, call, repeated_op) def apply(self, expr): return self.call(expr) @@ -77,11 +81,11 @@ class BinOperator(Operator): """ # Used to store all the instances of BinOperator, used in the parser - instances = [] + instances = {} - def __init__(self, name: str, precedence: int, properties: BinProperties, call: Callable): - BinOperator.instances.append(self) - super().__init__(name, precedence, call) + def __init__(self, name: str, precedence: int, properties: BinProperties, call: Callable, repeated_op: Operator = None ): + BinOperator.instances[name] = self + super().__init__(name, precedence, call, repeated_op) self.properties = properties def apply(self, left, right): diff --git a/python_symb/MathTypes/symbols.py b/python_symb/MathTypes/symbols.py index 00c620a..1fe07ec 100644 --- a/python_symb/MathTypes/symbols.py +++ b/python_symb/MathTypes/symbols.py @@ -1,16 +1,16 @@ from __future__ import annotations - class Symbols: """ - All maths things (other than number) that will be parsed need to be of "Symbols" class + All maths things (other than integers) that will be parsed need to be of "Symbols" class """ - instances = [] + instances = {} def __init__(self, name): + assert name not in Symbols.instances, f'Symbol with name {name} already exists' self.name = name - Symbols.instances.append(self) + Symbols.instances[name] = self def __repr__(self): return self.name @@ -39,10 +39,10 @@ class Var(Symbols): """ variable, like 'x' in x+2 """ - instances = [] + instances = {} def __init__(self, name): super().__init__(name) - self.__class__.instances.append(self) + self.__class__.instances[name] = self diff --git a/python_symb/Parsing/parse.py b/python_symb/Parsing/parse.py index 5d374dd..754069e 100644 --- a/python_symb/Parsing/parse.py +++ b/python_symb/Parsing/parse.py @@ -11,16 +11,11 @@ ParenthesisRight = Symbols(')') Number = Union[int, float, Fraction] -name_to_symbol = {sy.name:sy for sy in Symbols.instances} +name_to_symbol = Symbols.instances -def update_symbols_dict(): - global name_to_symbol - name_to_symbol = {sy.name:sy for sy in Symbols.instances} - - """ example1 = "a + b * c + d" - @@ -37,7 +32,7 @@ def preprocess(expr: str) -> List: :param expr: string expression :return: list of symbols and numbers """ - update_symbols_dict() + return_list = [] expr = expr.strip() expr = expr.replace(' ', '') diff --git a/python_symb/TreeModification/expand.py b/python_symb/TreeModification/expand.py new file mode 100644 index 0000000..9422868 --- /dev/null +++ b/python_symb/TreeModification/expand.py @@ -0,0 +1,14 @@ +from python_symb.Expressions.expr import Expr +from python_symb.MathTypes.symbols import Var +from python_symb.MathTypes.operator_file import Operator, BinOperator, Add, Mul + +def expand(expr: Expr) -> Expr: + """ + Expand an expression + :param expr: expression to expand + :return: expanded expression + """ + + if expr.is_leaf: + return expr + diff --git a/python_symb/tree_visual.py b/python_symb/tree_visual.py index 859ed45..1f52f27 100644 --- a/python_symb/tree_visual.py +++ b/python_symb/tree_visual.py @@ -1,7 +1,6 @@ import tkinter as tk from python_symb.Expressions.expr import Expr from python_symb.MathTypes.symbols import Var -from python_symb.Parsing.parse import update_symbols_dict class Visual: @@ -72,8 +71,6 @@ class Visual: if v not in Var.instances: Var(v) - # Update the symbols dict - update_symbols_dict() def show_tree(self):