import ptoken import tokenizer import copy from collections import deque debug = False def calculate_results(tokens): return process_tokens(convert_to_deque(tokens), True) def process_tokens(tokens, top_level = False): pending_operations = [] running_total = 0 p_ops_ran = False while True: if not tokens: break token = tokens.popleft() if not top_level and token.type == ptoken.TokenType.exp_end: if tokens: look_ahead = tokens[0] if look_ahead.type == ptoken.TokenType.power: tokens.popleft() two_ahead = tokens.popleft() tmp = process_tokens(convert_to_deque(pending_operations)) if two_ahead.type == ptoken.TokenType.exp_start: two_ahead = ptoken.Token(process_tokens(tokens), ptoken.TokenType.constant) return operate(tmp, two_ahead.value, look_ahead.type) break if token.type == ptoken.TokenType.exp_start: tmp = process_tokens(tokens) pending_operations.append(ptoken.Token(tmp, ptoken.TokenType.constant)) elif token.type == ptoken.TokenType.power: look_ahead = tokens.popleft() #if look_ahead.type == ptoken.TokenType.exp_start: # look_ahead = ptoken.Token(process_tokens(tokens), ptoken.TokenType.constant) pending_operations.append(ptoken.Token(operate(pending_operations.pop().value, look_ahead.value, token.type), ptoken.TokenType.constant)) elif token.type == ptoken.TokenType.add or token.type == ptoken.TokenType.subtract: if pending_operations and p_ops_ran: tmp = convert_to_deque(pending_operations) previous_token = ptoken.Token(handle_pending(tmp), ptoken.TokenType.constant) pending_operations = [] pending_operations.append(previous_token) pending_operations.append(token) p_ops_ran = False elif token.type == ptoken.TokenType.constant: pending_operations.append(token) p_ops_ran = False elif token.type == ptoken.TokenType.multiply or token.type == ptoken.TokenType.divide: look_behind = pending_operations.pop() look_ahead = tokens.popleft() two_ahead = tokens[0] if look_ahead.type == ptoken.TokenType.exp_start: look_ahead = ptoken.Token(process_tokens(tokens), ptoken.TokenType.constant) if two_ahead.type == ptoken.TokenType.power: tokens.popleft() three_ahead = tokens.popleft() if three_ahead.type != ptoken.TokenType.exp_start: look_ahead = ptoken.Token(operate(look_ahead.value, three_ahead.value, two_ahead.type), ptoken.TokenType.constant) else: tmp = process_tokens(tokens) look_ahead = ptoken.Token(operate(look_ahead.value, tmp, two_ahead.type), ptoken.TokenType.constant) running_total = operate(look_behind.value, look_ahead.value, token.type) pending_operations.append(ptoken.Token(running_total, ptoken.TokenType.constant)) p_ops_ran = True #tokenizer.print_token_list(pending_operations) if pending_operations: if len(pending_operations) == 1: return float(pending_operations.pop().value) return handle_pending(convert_to_deque(pending_operations)) return running_total #handle add/sub def handle_pending(tokens): running_total = 0 previous_token = None if len(tokens) == 1: return float(tokens[0].value) while True: if not tokens: break tmp_token = tokens.popleft() if tmp_token.type == ptoken.TokenType.constant: previous_token = tmp_token elif tmp_token.type == ptoken.TokenType.add or tmp_token.type == ptoken.TokenType.subtract: look_ahead = tokens.popleft() running_total = operate(previous_token.value, look_ahead.value, tmp_token.type) previous_token = ptoken.Token(running_total, ptoken.TokenType.constant) return running_total def convert_to_deque(tokens): deq = deque() for tk in tokens: deq.append(tk) return deq def operate(n1, n2, tokenType): n1 = float(n1) n2 = float(n2) if tokenType == ptoken.TokenType.add: if debug: print("Adding %f and %f to get %f." %(n1, n2, n1 + n2)) return n1 + n2 elif tokenType == ptoken.TokenType.subtract: if debug: print("Subtracting %f and %f to get %f." %(n1, n2, n1 - n2)) return n1 - n2 elif tokenType == ptoken.TokenType.multiply: if debug: print("Multiplying %f and %f to get %f" %(n1, n2, n1 * n2)) return n1 * n2 elif tokenType == ptoken.TokenType.divide: if debug: print("Dividing %f and %f to get %f" %(n1, n2, n1 / n2)) return n1 / n2 elif tokenType == ptoken.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) def print_t(tokens): tmp = copy.deepcopy(tokens) while True: if not tmp: break token = tmp.popleft() print("%s" %(token.value), end = "") print()