def evaluate(self, tokenList): """Takes an expression in RPN notation and evaluates it""" tempStack = [] print(tokenList) try: tokenList.reverse() except AttributeError: result = "Error: Invalid tokens!" return result while len(tokenList) > 0: i = tokenList.pop() if isFloat(i): tempStack.append(i) else: op = find(i) if len(tempStack) < op.ops: print("Error: Insufficient values!") break else: value = arithmetic(tempStack.pop(), tempStack.pop(), i) tokenList.append(value) if len(tokenList) == 1 and tempStack == []: result = tokenList[0] return result if len(tokenList) > 1: result = "Error: User input has too many values" return result
def shunting(self, exp): """Takes an expression in infix notation and converts it to Reverse Polish Notation (RPN) using Dijkstra's Shunting Yard Algorithm.""" stack = [] output = [] tempString = "" # Get rid of all spaces for easier computation try: exp = exp.replace(' ', '') except AttributeError: return "Invalid type, string expected!" # Mathematical Sin, Cos, Tan functions, decimals and PI are allowed validChars = set("sincostanpi.") foundLeftParan = False validOutput = True functions = ("sin", "cos", "tan") if exp.count("(") != exp.count(")"): output = "Error: Mismatched parantheses!" print(output) return output # Tokenize the expression char by char for i in exp: # Store chars to see if they're number, function or constant if i.isdigit() or i in validChars: tempString += i # Functions are handled here elif tempString in functions: stack.append(tempString) # Operators are handled here elif is_op(i): # Token transition from number to operator. Get the number! if len(tempString) > 0: if tempString == "pi": tempString = math.pi output.append(float(tempString)) tempString = "" # Find what operator it is op = find(i) # Remove operators from stack onto output according to # their associativity and precedence. # Parans need to be handled separately, see below. while len(stack) > 0 and i != "(" and i != ")" and \ ((op.ass == "l" and (op.pre <= find(stack[-1]).pre)) or \ (op.ass == "r" and (op.pre < find(stack[-1]).pre))): output.append(stack.pop()) # Push the operator onto stack, unless it's right paran. # Because it means the end of precedence, so whatever was # inside those parans, they should be treated carefully if i != ")": stack.append(i) # Ok, that means we've come to an end, the stack is probably # stuffed up too much, so it's time put them in output. elif i == ")": while len(stack) > 0 and stack[-1] != "(": output.append(stack.pop()) # Thank you dear left paran. You've served your purpose. # It was a pleasure to work with you, but there is no need # for you in RPN. You may go now! if len(stack) > 0 and stack[-1] == "(": stack.pop() foundLeftParan = True # And now for something completely (un)expected! if len(stack) == 0 and not foundLeftParan: output = "Error: Mismatched parantheses!" validOutput = False break # Either users didn't read the instructions or they're delibaretely # putting invalid chars in input! Go play with something else! else: output = "Invalid input!" validOutput = False break # Remaining tokens (if any) are added to output if len(tempString) > 0 and validOutput: if tempString == "pi": tempString = math.pi output.append(float(tempString)) # Remaining operators (if any) in the stack are added to the output. while len(stack) > 0: if stack[-1] == "(" or stack[-1] == ")": output = "Invalid input!" break if validOutput: output.append(stack.pop()) return output
def shunting(self, exp): """Takes an expression in infix notation and converts it to Reverse Polish Notation (RPN) using Dijkstra's Shunting Yard Algorithm.""" stack = [] output = [] tempString = "" # Get rid of all spaces for easier computation try: exp = exp.replace(' ','') except AttributeError: return "Invalid type, string expected!" # Mathematical Sin, Cos, Tan functions, decimals and PI are allowed validChars = set("sincostanpi.") foundLeftParan = False validOutput = True functions = ("sin", "cos", "tan") if exp.count("(") != exp.count(")"): output = "Error: Mismatched parantheses!" print(output) return output # Tokenize the expression char by char for i in exp: # Store chars to see if they're number, function or constant if i.isdigit() or i in validChars: tempString += i # Functions are handled here elif tempString in functions: stack.append(tempString) # Operators are handled here elif is_op(i): # Token transition from number to operator. Get the number! if len(tempString) > 0: if tempString == "pi": tempString = math.pi output.append(float(tempString)) tempString = "" # Find what operator it is op = find(i) # Remove operators from stack onto output according to # their associativity and precedence. # Parans need to be handled separately, see below. while len(stack) > 0 and i != "(" and i != ")" and \ ((op.ass == "l" and (op.pre <= find(stack[-1]).pre)) or \ (op.ass == "r" and (op.pre < find(stack[-1]).pre))): output.append(stack.pop()) # Push the operator onto stack, unless it's right paran. # Because it means the end of precedence, so whatever was # inside those parans, they should be treated carefully if i != ")": stack.append(i) # Ok, that means we've come to an end, the stack is probably # stuffed up too much, so it's time put them in output. elif i == ")": while len(stack) > 0 and stack[-1] != "(": output.append(stack.pop()) # Thank you dear left paran. You've served your purpose. # It was a pleasure to work with you, but there is no need # for you in RPN. You may go now! if len(stack) > 0 and stack[-1] == "(": stack.pop() foundLeftParan = True # And now for something completely (un)expected! if len(stack) == 0 and not foundLeftParan: output = "Error: Mismatched parantheses!" validOutput = False break # Either users didn't read the instructions or they're delibaretely # putting invalid chars in input! Go play with something else! else: output = "Invalid input!" validOutput = False break # Remaining tokens (if any) are added to output if len(tempString) > 0 and validOutput: if tempString == "pi": tempString = math.pi output.append(float(tempString)) # Remaining operators (if any) in the stack are added to the output. while len(stack) > 0: if stack[-1] == "(" or stack[-1] == ")": output = "Invalid input!" break if validOutput: output.append(stack.pop()) return output