184 lines
4.7 KiB
Python
184 lines
4.7 KiB
Python
import ptoken as token
|
|
import tokenizer
|
|
import uuid
|
|
import calc_engine
|
|
|
|
class Op:
|
|
def __init__(self, left, op, right):
|
|
self.left = left
|
|
self.op = op
|
|
self.right = right
|
|
|
|
def __str__(self):
|
|
return "%s (%s) and (%s)" %(token.TokenType.get_operator_verb(self.op), self.left, self.right)
|
|
|
|
class Num:
|
|
def __init__(self, token):
|
|
self.value = token.value
|
|
|
|
def __str__(self):
|
|
return self.value
|
|
|
|
class Parser:
|
|
def __init__(self, tokens):
|
|
self.tokens = tokens
|
|
self.current_token = self.tokens.pop()
|
|
|
|
|
|
def eat(self, token_type):
|
|
if self.current_token.type != token_type:
|
|
print("grammar")
|
|
if len(self.tokens) > 0:
|
|
self.current_token = self.tokens.pop()
|
|
|
|
def factor(self):
|
|
node = self.current_token
|
|
#print(node)
|
|
if self.current_token.type == token.TokenType.constant:
|
|
self.eat(token.TokenType.constant)
|
|
return Num(node)
|
|
elif self.current_token.type == token.TokenType.exp_start:
|
|
self.eat(token.TokenType.exp_start)
|
|
node = self.topLevel()
|
|
self.eat(token.TokenType.exp_end)
|
|
return node
|
|
|
|
def lowLevel(self):
|
|
node = self.factor()
|
|
|
|
while self.current_token.type == token.TokenType.power:
|
|
t = self.current_token
|
|
|
|
if t.type == token.TokenType.power:
|
|
self.eat(token.TokenType.power)
|
|
|
|
node = Op(left=node, op=t.type, right=self.factor())
|
|
|
|
return node
|
|
|
|
def midLevel(self):
|
|
node = self.lowLevel()
|
|
|
|
while self.current_token.type in (token.TokenType.multiply, token.TokenType.divide):
|
|
t = self.current_token
|
|
|
|
if t.type == token.TokenType.multiply:
|
|
self.eat(token.TokenType.multiply)
|
|
elif t.type == token.TokenType.divide:
|
|
self.eat(token.TokenType.divide)
|
|
|
|
node = Op(left=node, op=t.type, right=self.lowLevel())
|
|
|
|
return node
|
|
|
|
def topLevel(self):
|
|
node = self.midLevel()
|
|
|
|
while self.current_token.type in (token.TokenType.add, token.TokenType.subtract):
|
|
t = self.current_token
|
|
|
|
if t.type == token.TokenType.add:
|
|
self.eat(token.TokenType.add)
|
|
elif t.type == token.TokenType.subtract:
|
|
self.eat(token.TokenType.subtract)
|
|
|
|
node = Op(left=node, op=t.type, right=self.midLevel())
|
|
|
|
return node
|
|
|
|
def parse(self):
|
|
#print("C: %s" %(self.current_token))
|
|
return self.topLevel()
|
|
|
|
def print_tree(root):
|
|
depth = Parser.get_tree_diameter(root)
|
|
for i in range(depth):
|
|
print("%s" %("".rjust(depth - i, ' ')), end = "" )
|
|
Parser.print_height(root, i)
|
|
print()
|
|
|
|
def print_height(node, level):
|
|
if node == None:
|
|
return
|
|
|
|
if level == 0:
|
|
print("%s " %(str(node)), end = "")
|
|
else:
|
|
Parser.print_height(node.left, level - 1)
|
|
Parser.print_height(node.right, level - 1)
|
|
|
|
def get_tree_diameter(node):
|
|
if type(node) is Num:
|
|
return 0
|
|
|
|
if node == None:
|
|
return 0
|
|
|
|
return 1 + max(Parser.get_tree_diameter(node.left), Parser.get_tree_diameter(node.right))
|
|
|
|
def p(node):
|
|
|
|
if type(node) is Num:
|
|
#print("%s " %(node), end ="")
|
|
return
|
|
|
|
else:
|
|
#Parser.p(node.left)
|
|
print(node)
|
|
#Parser.p(node.right)
|
|
|
|
Parser.p(node.left)
|
|
Parser.p(node.right)
|
|
|
|
def calc(node):
|
|
|
|
if type(node) is Num:
|
|
return float(node.value)
|
|
|
|
left = calc(node.left)
|
|
right = calc(node.right)
|
|
|
|
return operate(left, right, node.op)
|
|
|
|
debug = True
|
|
def operate(n1, n2, tokenType):
|
|
# Utility function to handle dealing with the various mathmatical operations that the engine can process.
|
|
# Returns the result of any one of five mathmatical operations, else throws an error for unrecognized operations.
|
|
n1 = float(n1)
|
|
n2 = float(n2)
|
|
|
|
if tokenType == token.TokenType.add:
|
|
if debug: print("Adding %f and %f to get %f." %(n1, n2, n1 + n2))
|
|
return n1 + n2
|
|
elif tokenType == token.TokenType.subtract:
|
|
if debug: print("Subtracting %f and %f to get %f." %(n1, n2, n1 - n2))
|
|
return n1 - n2
|
|
elif tokenType == token.TokenType.multiply:
|
|
if debug: print("Multiplying %f and %f to get %f" %(n1, n2, n1 * n2))
|
|
return n1 * n2
|
|
elif tokenType == token.TokenType.divide:
|
|
if debug: print("Dividing %f and %f to get %f" %(n1, n2, n1 / n2))
|
|
return n1 / n2
|
|
elif tokenType == token.TokenType.power:
|
|
if debug: print("Raising %f to the power of %f to get %f" %(n1, n2, n1**n2))
|
|
return n1 ** n2
|
|
else:
|
|
raise TypeError("Invalid operator value " + str(tokenType) + ".", tokenType)
|
|
|
|
# k(((1+i)^n - 1)/i)
|
|
#t = Add()
|
|
#t.add_child(Constant(4))
|
|
#t.add_child(Sub())
|
|
#t.left.add_child(Sub())
|
|
|
|
tokens = tokenizer.get_tokens_from_expression_string("5*2^(2+1)-(1+5)-2^5+5*(2/2*3+5)^2")
|
|
#tokens.reverse()
|
|
#print(calc_engine.calculate_results(tokens))
|
|
#tokens = tokenizer.get_tokens_from_expression_string("200((1-(1.08)^(-12))/0.08)")
|
|
#print(calc_engine.calculate_results(tokens))
|
|
#tokens = tokenizer.get_tokens_from_expression_string("1+6 / 2")
|
|
#n = Parser(tokens)
|
|
#s = n.parse()
|
|
#Parser.p(s)
|
|
#print(calc(s))
|