Fixed a negative number bug in the tokenizer; started work on a new calc_engine. Mostly working as of this commit.
This commit is contained in:
+127
-229
@@ -1,264 +1,162 @@
|
||||
import ptoken as token
|
||||
import ptoken
|
||||
import tokenizer
|
||||
import queue
|
||||
import deque
|
||||
import copy
|
||||
|
||||
debug = False
|
||||
debug = True
|
||||
|
||||
def calculate_results(tokens):
|
||||
new_list = copy.deepcopy(tokens)
|
||||
new_list.reverse()
|
||||
return handle_add_and_subtract(new_list)
|
||||
q = convert_to_queue(tokens)
|
||||
tokenizer.print_token_list(tokens)
|
||||
|
||||
def handle_parenthesis(tokens, call_has_priority = False):
|
||||
running_value = 0
|
||||
previous_token = token.Token("", token.TokenType.unknown)
|
||||
return process_tokens(q, True)
|
||||
|
||||
def process_tokens(tokens, top_level = False):
|
||||
pending_operations = []#queue.Queue()
|
||||
power = 0
|
||||
running_total = 0
|
||||
p_ops_ran = False
|
||||
|
||||
while True:
|
||||
if len(tokens) == 0:
|
||||
if tokens.empty():
|
||||
break
|
||||
|
||||
current_token = tokens.pop()
|
||||
token = tokens.get()
|
||||
|
||||
if current_token.type == token.TokenType.constant:
|
||||
previous_token = current_token
|
||||
if not top_level and token.type == ptoken.TokenType.exp_end:
|
||||
|
||||
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(token.Token(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(token.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 not call_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)
|
||||
#if look_ahead.popleft().type == ptoken.TokenType.power:
|
||||
# power = float(look_ahead.value)
|
||||
|
||||
break
|
||||
|
||||
return running_value
|
||||
|
||||
def handle_multiply_and_division(tokens):
|
||||
running_value = 0
|
||||
previous_token = token.Token("", token.TokenType.unknown)
|
||||
|
||||
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.get()
|
||||
|
||||
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 len(pending_operations) > 0 and p_ops_ran:
|
||||
tmp = convert_to_queue(pending_operations)
|
||||
previous_token = None
|
||||
|
||||
while True:
|
||||
if tmp.empty():
|
||||
break
|
||||
|
||||
tmp_token = tmp.get()
|
||||
|
||||
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 = tmp.get()
|
||||
|
||||
running_total = operate(previous_token.value, look_ahead.value, tmp_token.type)
|
||||
|
||||
previous_token = ptoken.Token(running_total, ptoken.TokenType.constant)
|
||||
|
||||
pending_operations = []
|
||||
pending_operations.append(previous_token)
|
||||
pending_operations.append(token)
|
||||
tokenizer.print_token_list(pending_operations)
|
||||
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_ahead = tokens.get()
|
||||
|
||||
if look_ahead.type == ptoken.TokenType.exp_start:
|
||||
look_ahead = ptoken.Token(process_tokens(tokens), ptoken.TokenType.constant)
|
||||
|
||||
look_behind = pending_operations.pop()
|
||||
|
||||
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 power > 0:
|
||||
running_total = handle_pending(convert_to_queue(pending_operations))
|
||||
|
||||
running_total = operate(running_total, power, ptoken.TokenType.power)
|
||||
elif len(pending_operations) > 0:
|
||||
running_total = handle_pending(convert_to_queue(pending_operations))
|
||||
|
||||
return running_total
|
||||
|
||||
def handle_pending(tokens):
|
||||
running_total = 0
|
||||
previous_token = None
|
||||
|
||||
while True:
|
||||
if len(tokens) == 0:
|
||||
if tokens.empty():
|
||||
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
|
||||
tmp_token = tokens.get()
|
||||
|
||||
#"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 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.get()
|
||||
|
||||
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
|
||||
running_total = operate(previous_token.value, look_ahead.value, tmp_token.type)
|
||||
|
||||
return running_value
|
||||
previous_token = ptoken.Token(running_total, ptoken.TokenType.constant)
|
||||
|
||||
return running_total
|
||||
|
||||
def handle_add_and_subtract(tokens):
|
||||
#
|
||||
# Note: this is should be the first function called to calculate the result of the tokens.
|
||||
# A bit hacky, and not the best name for this method, but it grew "orgranically" to be
|
||||
# this way. For now this is fine, and for what the calc_engine does this may not
|
||||
# need to change for the life of this project.
|
||||
#
|
||||
running_value = 0
|
||||
previous_token = token.Token("", token.TokenType.unknown)
|
||||
def convert_to_queue(tokens):
|
||||
q = queue.Queue()
|
||||
|
||||
while True:
|
||||
|
||||
if len(tokens) == 0:
|
||||
break
|
||||
for tk in tokens:
|
||||
q.put(ptoken.Token(tk.value, tk.type))
|
||||
|
||||
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)
|
||||
#Set the previous_token to an invalid state so its not used by mistake.
|
||||
previous_token.type = token.TokenType.unknown
|
||||
continue
|
||||
|
||||
elif 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)
|
||||
#Set the previous_token to an invalid state so its not used by mistake.
|
||||
previous_token.type = token.TokenType.unknown
|
||||
|
||||
continue
|
||||
|
||||
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
|
||||
|
||||
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(token.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.power:
|
||||
#In theory, if we hit this branch the expression wuld look something like this: a ^ b.
|
||||
|
||||
|
||||
return running_value
|
||||
|
||||
|
||||
def peek_list(tokens):
|
||||
if tokens:
|
||||
return tokens[-1]
|
||||
else:
|
||||
raise IndexError("The token list is empty.", tokens)
|
||||
|
||||
return q
|
||||
|
||||
def operate(n1, n2, tokenType):
|
||||
n1 = float(n1)
|
||||
n2 = float(n2)
|
||||
|
||||
if tokenType == token.TokenType.add:
|
||||
if debug: print("Adding %d and %d to get %d." %(n1, n2, n1 + 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 == token.TokenType.subtract:
|
||||
if debug: print("Subtracting %d and %d to get %d." %(n1, n2, 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 == token.TokenType.multiply:
|
||||
if debug: print("Multiplying %d and %d to get %d" %(n1, n2, 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 == token.TokenType.divide:
|
||||
if debug: print("Dividing %d and %d to get %d" %(n1, n2, 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 == token.TokenType.power:
|
||||
if debug: print("Raising %d to the power of %d to get %d" %(n1, n2, 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 = queue.Queue()
|
||||
|
||||
while True:
|
||||
if tokens.empty():
|
||||
break
|
||||
token = tokens.get()
|
||||
|
||||
print("%s" %(token.value), end = "")
|
||||
tmp.put(token)
|
||||
print()
|
||||
|
||||
return tmp
|
||||
|
||||
Reference in New Issue
Block a user