Skip to content

Instantly share code, notes, and snippets.

@AcrylicShrimp
Created October 17, 2022 09:03
Show Gist options
  • Save AcrylicShrimp/465776131f4969a645c09a52c0954c69 to your computer and use it in GitHub Desktop.
Save AcrylicShrimp/465776131f4969a645c09a52c0954c69 to your computer and use it in GitHub Desktop.
Basic calculator via Python 3
class Cursor():
def __init__(self, s):
self.s = ''.join(s.split())
def is_remains(self, i=0):
return i < len(self.s)
def advance(self, n):
self.s = self.s[n:]
class Node():
def __init__(self, c):
self.inner = PlusMinusNode(c)
def calc(self):
return self.inner.calc()
class PlusMinusNode():
def __init__(self, c):
if not c.is_remains():
raise
self.lhs = MulDivModNode(c)
self.rhs = []
while c.is_remains():
op = c.s[0]
if op == '+':
c.advance(1)
self.rhs.append([op, MulDivModNode(c)])
elif op == '-':
c.advance(1)
self.rhs.append([op, MulDivModNode(c)])
else:
break
def calc(self):
value = self.lhs.calc()
for rhs in self.rhs:
if rhs[0] == '+':
value += rhs[1].calc()
elif rhs[0] == '-':
value -= rhs[1].calc()
return value
class MulDivModNode():
def __init__(self, c):
if not c.is_remains():
raise
self.lhs = PowNode(c)
self.rhs = []
while c.is_remains():
op = c.s[0]
if op == '*':
c.advance(1)
self.rhs.append([op, PowNode(c)])
elif op == '/':
c.advance(1)
self.rhs.append([op, PowNode(c)])
elif op == '%':
c.advance(1)
self.rhs.append([op, PowNode(c)])
else:
break
def calc(self):
value = self.lhs.calc()
for rhs in self.rhs:
if rhs[0] == '*':
value *= rhs[1].calc()
elif rhs[0] == '/':
print(rhs[0])
value /= rhs[1].calc()
elif rhs[0] == '%':
value %= rhs[1].calc()
return value
class PowNode():
def __init__(self, c):
if not c.is_remains():
raise
self.lhs = LeafNode(c)
self.rhs = []
while c.is_remains():
op = c.s[0]
if op == '^':
c.advance(1)
self.rhs.append([op, LeafNode(c)])
else:
break
def calc(self):
value = self.lhs.calc()
for rhs in self.rhs:
if rhs[0] == '^':
value **= rhs[1].calc()
return value
class LeafNode():
def __init__(self, c):
if not c.is_remains():
raise
if c.s[0] == '(':
c.advance(1)
self.node = Node(c)
if not c.is_remains() or c.s[0] != ')':
raise
c.advance(1)
else:
self.node = NumberNode(c)
def calc(self):
return self.node.calc()
class NumberNode():
def __init__(self, c):
prefix = None
while True:
if not c.is_remains():
raise
if c.s[0] == '+':
if prefix != '-':
prefix = '+'
c.advance(1)
elif c.s[0] == '-':
if prefix == '+':
prefix = '-'
else:
prefix = '+'
c.advance(1)
else:
break
i = 0
while c.is_remains(i) and c.s[i].isdigit():
i += 1
if i == 0:
raise
self.n = float(c.s[:i])
c.advance(i)
if prefix == '-':
self.n = -self.n
def calc(self):
return self.n
while True:
s = input("enter an expression: ")
c = Cursor(s)
try:
node = Node(c)
except:
print("the given expression is invalid, try again")
continue
print("the answer is", node.calc())
print("")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment