Skip to content

Instantly share code, notes, and snippets.

@Ethosa
Created August 12, 2021 11:30
Show Gist options
  • Save Ethosa/4ad232cf5f147305484f50f57255228c to your computer and use it in GitHub Desktop.
Save Ethosa/4ad232cf5f147305484f50f57255228c to your computer and use it in GitHub Desktop.
simple calc 👀 lol
# author: Ethosa
from enum import Enum
numbers = '0123456789'
operators = '+-/*'
class Type(Enum):
NUMBER = 0
OPERATOR = 1
UNKNOWN = 2
class Token:
def __init__(self, token=' ', other=None):
token = token
if token in numbers:
ttype = Type.NUMBER
token = int(token)
elif token in operators:
ttype = Type.OPERATOR
else:
ttype = Type.UNKNOWN
if not other:
self.ttype = ttype
self.token = token
else:
self.ttype = other.ttype
self.token = other.token
if self.ttype == ttype and ttype == Type.NUMBER:
self.token = self.token * 10 + token
else:
self.ttype = ttype
self.token = token
def num_token(number: int):
token = Token()
token.ttype = Type.NUMBER
token.token = number
return token
def __str__(self) -> str:
return str(self.token)
class Tree:
def __init__(self):
self.tokens = []
def add(self, token: Token) -> None:
self.tokens.append(token)
def get_at(self, pos: int) -> Token:
return self.tokens[pos]
def has_operators(self) -> bool:
for t in self.tokens:
if t.ttype == Type.OPERATOR:
return True
def has_upper(self, token: Token) -> bool:
for t in self.tokens:
if self.get_weight(t) > self.get_weight(token):
return True
def get_weight(self, token: Token) -> int:
return 0 if token.ttype != Type.OPERATOR else 46 if token.token == '*' else ord(token.token)
def size(self) -> int:
return len(self.tokens)
def __str__(self) -> str:
return ", ".join([str(token) for token in self.tokens])
class Calc:
def _parse_expr(self, expr: str) -> Tree:
expr += " "
tree = Tree()
token = Token()
for i in expr:
_token = Token(i, token)
if (_token.ttype == Type.UNKNOWN or token.ttype != _token.ttype) and token.ttype != Type.UNKNOWN:
tree.add(token)
token = _token
return self._calc_tree(tree)
def _calc_tree(self, tree: Tree) -> int:
while tree.has_operators():
for i in range(1, tree.size()-1):
prev = tree.get_at(i-1)
current = tree.get_at(i)
next = tree.get_at(i+1)
if tree.has_upper(current):
continue
if (self.insert(tree, i, int.__truediv__, "/", prev, current, next) or
self.insert(tree, i, int.__mul__, "*", prev, current, next) or
self.insert(tree, i, int.__sub__, "-", prev, current, next) or
self.insert(tree, i, int.__add__, "+", prev, current, next)):
break
return tree.tokens[0].token if len(tree.tokens) == 1 else 0
def insert(self, tree, pos, val, ifval, prev, current, next) -> bool:
if current.token == ifval and prev.ttype == Type.NUMBER and next.ttype == Type.NUMBER:
tree.tokens.insert(pos-1, Token.num_token(int(val(prev.token, next.token))))
for j in range(3):
tree.tokens.pop(pos)
return True
if __name__ == '__main__':
calc = Calc()
print(calc._parse_expr("100 + 500 / 10 * 2 - 50"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment