#!/usr/bin/python3 # ==================================================================== # evaluate a list of RPN tokens # ==================================================================== import sys from infix_stack import Stack import user_interface as ui explanation = ''' Entered a RPN expression as a string. The operands and operators should be seperated by spaces or commas. For example: '1,2 + /,3' ''' msg0 = 'error: badly formed RPN expression' msg1 = 'error: not enough tokens on the stack for binary operator' # -------------------------------------------------------------------- # ---- convert string to number (int or float) # -------------------------------------------------------------------- def _number(string): tf,n = ui.is_integer(string) if tf is True: return(True,n) tf,n = ui.is_float(string) if tf is True: return(True,n) return (False,0) # -------------------------------------------------------------------- # ---- evaluate RPN expression # -------------------------------------------------------------------- def evaluate_rpn(tokens:list) -> tuple: # ---- convert the token list into a stack of operators # ---- and operands stack = Stack() for token in tokens: tf,n = _number(token[0]) if tf: stack.push(n) # operand continue op = token[0] # operator print(f'op={op:<2} stack={stack.as_list()}') if op == '+': # add a = stack.pop() b = stack.pop() stack.push(b+a) continue if op == '-': # subtract a = stack.pop() b = stack.pop() stack.push(b-a) continue if op == '*': # multiply a = stack.pop() b = stack.pop() stack.push(b*a) continue if op == '/': # divide a = stack.pop() b = stack.pop() stack.push(b/a) continue if op == '%': # modulus (remandier) a = stack.pop() b = stack.pop() stack.push(b%a) continue if op == '**': # power a = stack.pop() b = stack.pop() stack.push(b**a) continue if op == '//': # floor a = stack.pop() b = stack.pop() stack.push(b//a) continue print() print(msg0) print(f'error: bad operator ({op})') break # ---- return results if stack.is_empty(): print(msg0) print('error: stack is empty - no results') return(False,0) if stack.length() > 1: print(msg0) print('error: stack contains more than one value') print(f'stack: {stack.as_list()}') return(False,0) return(True,stack.tos()) # -------------------------------------------------------------------- # ---- main # -------------------------------------------------------------------- if __name__ == '__main__': print(explanation) while True: # ---- ask the user to enter an RPM expression print() ex = ui.get_user_input('Enter RPN expression: ') if not ex: break # ---- convert expression string into a list of strings strings = ex.replace(',',' ').split() if len(strings) == 0: print() print('Error: empty expression') continue ##print() ##print(f'exp: {strings}') ##print() # ---- convert a list of strings to a list of tokens # ---- (add fake type/precedence) tokens = [] for tok in strings: tokens.append((tok,99)) # ---- evaluate token list tf,value = evaluate_rpn(tokens) print() print(f'success = {tf}') print(f'RPN value = {value}')