Cleaned up the AST code and updated the calc_engine code.

This commit is contained in:
2020-07-01 21:40:18 -05:00
parent fcd0076891
commit 503b16ec65
2 changed files with 44 additions and 271 deletions
+37 -128
View File
@@ -1,7 +1,6 @@
import ptoken as token
import tokenizer
import uuid
import calc_engine
from collections import deque
class Op:
@@ -20,55 +19,63 @@ class Num:
def __str__(self):
return self.value
class Variable:
def __init__(self, token):
self.symbol = token.value
self.value = None
def __str__(self):
if self.value == None:
return self.symbol
else:
return str(self.value)
class Parser:
def __init__(self, tokens):
if len(tokens) == 0:
raise ValueError("Token list can't be empty")
self.tokens = tokens
self.current_token = self.tokens.popleft()
self.current_token = None
self.advance_current_token()
self.ast = self.generate_ast()
def eat(self, token_type):
if self.current_token.type != token_type:
print("grammar")
def advance_current_token(self):
if len(self.tokens) > 0:
self.current_token = self.tokens.popleft()
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)
node = Num(self.current_token)
self.advance_current_token()
return node
elif self.current_token.type == token.TokenType.variable:
node = Variable(self.current_token)
self.advance_current_token()
return node
elif self.current_token.type == token.TokenType.exp_start:
self.eat(token.TokenType.exp_start)
self.advance_current_token() # (
node = self.topLevel()
self.eat(token.TokenType.exp_end)
self.advance_current_token() # )
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)
tmp = self.current_token
self.advance_current_token()
node = Op(left=node, op=tmp.type, right=self.factor())
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())
tmp = self.current_token
self.advance_current_token()
node = Op(left=node, op=tmp.type, right=self.lowLevel())
return node
@@ -76,109 +83,11 @@ class Parser:
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())
tmp = self.current_token
self.advance_current_token()
node = Op(left=node, op=tmp.type, right=self.midLevel())
return node
def parse(self):
#print("C: %s" %(self.current_token))
def generate_ast(self):
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 = False
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))