diff --git a/calc_engine.py b/calc_engine.py index 8674efe..06727e1 100644 --- a/calc_engine.py +++ b/calc_engine.py @@ -3,6 +3,217 @@ import token def calculate_results(tokens): return 0 + +def handle_parenthesis(tokens, call_has_priority = False): + running_value = 0 + previous_token = CToken("", token.TokenType.unknown) + + while True: + if len(tokens) == 0: + break + + current_token = tokens.pop() + + if current_token.type == token.TokenType.constant: + previous_token = current_token + + elif current_token == token.TokenType.exp_start: + running_value = handle_parenthesis(tokens) + + elif current_token.type == token.TokenType.add or current_token.type == token.TokenType.subtract: + look_ahead = tokens.pop() + + if look_ahead.type == token.TokenType.exp_start: + tmp = handle_parenthesis(tokens) + + if running_value == 0: + running_value = operate(previous_token.value, tmp, current_token.type) + else: + running_value = operate(running_value, tmp, current_token.type) + continue + + tokens.append(look_ahead) + tokens.append(current_token) + + if not previous_token.type == token.TokenType.unknown: + tokens.append(previous_token) + else: + tokens.append(CToken(running_value, token.TokenType.constant)) + + running_value = handle_add_and_subtract(tokens) + #Set the previous_token to an invalid state so its not used by mistake. + previous_token.type = token.TokenType.unknown + + elif current_token.type == token.TokenType.power: + look_ahead = tokens.pop() + + if look_ahead.type == token.TokenType.exp_start: + power_of = handle_parenthesis(tokens, True) + + running_value = operate(previous_token.value, power_of, current_token.type) + #Set the previous_token to an invalid state so its not used by mistake. + previous_token.type = token.TokenType.unknown + continue + + running_value = operate(previous_token.value, look_ahead.value, current_token.type) + #Set the previous_token to an invalid state so its not used by mistake. + previous_token.type = token.TokenType.unknown + + elif current_token.type == token.TokenType.multiply or current_token.type == token.TokenType.divide: + look_ahead = peek_list(tokens) + + if look_ahead.type == token.TokenType.exp_start: + tokens.pop() + running_value = operate(previous_token.value, handle_parenthesis(tokens), current_token.type) + #Set the previous_token to an invalid state so its not used by mistake. + previous_token.type = token.TokenType.unknown + continue + + tokens.append(current_token) + + if not previous_token.type == token.TokenType.unknown: + tokens.append(previous_token) + else: + tokens.append(CToken(running_value, token.TokenType.constant)) + + running_value = handle_multiply_and_division(tokens) + #Set the previous_token to an invalid state so its not used by mistake. + previous_token.type = token.TokenType.unknown + + elif current_token.type == token.TokenType.exp_end: + + if len(tokens) > 0 and peek_list(tokens).type == token.TokenType.power: + tokens.pop() + running_value = operate(running_value, tokens.pop().value, token.TokenType.power) + + if !caller_has_priority and len(tokens) > 0 and (peek_list(tokens).type == token.TokenType.multiply or peek_list(tokens).type == token.TokenType.divide): + operator = tokens.pop() + two_ahead = tokens.pop() + + if two_ahead.type == token.TokenType.exp_start: + running_value = operate(running_value, handle_parenthesis(tokens), operator.type) + else: + running_value = operate(running_value, two_ahead.value, operator.type) + + break + + return running_value + +def handle_multiply_and_division(tokens): + running_value = 0 + previous_token = CToken("", token.TokenType.unknown) + + while True: + if len(tokens) == 0: + break + + current_token = peek_list(tokens) + #check to see if we want to deal with this token here, making sure not to consume it just incase we + #don't want to process it here. + if current_token.type != token.TokenType.multiply and current_token.type != token.TokenType.divide and current_token.type != token.TokenType.constant and current_token.type != token.TokenType.variable: + break + + #"Commit" the current token. + current_token = tokens.pop() + + if current_token.type == token.TokenType.constant: + previous_token = current_token + continue + + elif current_token.type == token.TokenType.multiply or current_token.type == token.TokenType.divide: + look_ahead = tokens.pop() + + if look_ahead.type == token.TokenType.exp_start: + tmp = handle_parenthesis(tokens, True) + + if running_value == 0: + running_value = operate(previous_token.value, tmp, current_token.type) + else: + running_value = operate(running_value, tmp, current_token.type) + + #Set the previous_token to an invalid state so its not used by mistake. + previous_token.type = token.TokenType.unknown + continue + + if look_ahead.type == token.TokenType.constant: + if running_value == 0: + running_value = operate(previous_token.value, look_ahead.value, current_token.type) + else: + running_value = operate(running_value, look_ahead.value, current_token.type) + + #Set the previous_token to an invalid state so its not used by mistake. + previous_token.type = token.TokenType.unknown + + return running_value + +def handle_add_and_subtract(tokens): + running_value = 0 + previous_token = CToken("", token.TokenType.unknown) + + while True: + if len(tokens) == 0: + break + + current_token = tokens.pop() + + if current_token.type == token.TokenType.constant: + previous_token = current_token + continue + + if current_token.type == token.TokenType.exp_end: + tokens.append(current_token) + break + + if current_token.type == token.TokenType.exp_start: + running_value = handle_parenthesis(tokens) + + elif current_token.type == token.TokenType.add or current_token.type == token.TokenType.subtract: + look_ahead = tokens.pop() + + if look_ahead.type == token.TokenType.exp_start: + tmp = handle_parenthesis(tokens) + + if running_value == 0: + running_value = operate(previous_token.value, tmp, current_token.type) + else: + running_value = operate(running_value, tmp, current_token.type) + previous_token.type = token.TokenType.unknown + + if len(tokens) > 0: + two_ahead = peek_list(tokens) + + if two_ahead.type == token.TokenType.multiply or two_ahead.type == token.TokenType.divide: + tokens.append(look_ahead) + + tmp = handle_multiply_and_division(tokens) + + if running_value == 0: + running_value = operate(previous_token.value, tmp, current_token.type) + else: + running_value = operate(running_value, tmp, current_token.type) + previous_token.type = token.TokenType.unknown + + else: + if running_value == 0: + running_value = operate(previous_token.value, look_ahead.value, current_token.type) + else: + running_value = operate(running_value, look_ahead.value, current_token.type) + previous_token.type = token.TokenType.unknown + + elif current_token.type == token.TokenType.multiply or current_token.type == token.TokenType.divide: + tokens.append(current_token) + + if previous_token.type != token.TokenType.unknown: + tokens.append(previous_token) + else: + tokens.append(CToken(running_value, token.TokenType.constant)) + + running_value = handle_multiply_and_division(tokens) + + previous_token.type = token.TokenType.unknown + + return running_value + def peek_list(tokens): if tokens: diff --git a/tokenizer.py b/tokenizer.py index 485f9a8..88385b3 100644 --- a/tokenizer.py +++ b/tokenizer.py @@ -1,10 +1,10 @@ import token def get_tokens_from_expression_string(expression_string): - """ - Takes user input of an actuarial formula and parses the formula to id its components. - :return: tokens (List of objects of CToken class). - """ + + #Takes user input of an actuarial formula and parses the formula to id its components. + #:return: tokens (List of objects of CToken class). + tokens = [] # List of objects of CToken class tmp = "" parsing_number = False