diff --git a/parser.py b/parser.py new file mode 100644 index 0000000..900c5cd --- /dev/null +++ b/parser.py @@ -0,0 +1,183 @@ +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))