Task: Parsing_RPN calculator algorithm







Python: def op_pow(stack):
    b = stack.pop(); a = stack.pop()
    stack.append( a ** b )
def op_mul(stack):
    b = stack.pop(); a = stack.pop()
    stack.append( a * b )
def op_div(stack):
    b = stack.pop(); a = stack.pop()
    stack.append( a / b )
def op_add(stack):
    b = stack.pop(); a = stack.pop()
    stack.append( a + b )
def op_sub(stack):
    b = stack.pop(); a = stack.pop()
    stack.append( a - b )
def op_num(stack, num):
    stack.append( num )
    
ops = {
 '^': op_pow,
 '*': op_mul,
 '/': op_div,
 '+': op_add,
 '-': op_sub,
 }

def get_input(inp = None):
    'Inputs an expression and returns list of tokens'
    
    if inp is None:
        inp = input('expression: ')
    tokens = inp.strip().split()
    return tokens

def rpn_calc(tokens):
    stack = []
    table = ['TOKEN,ACTION,STACK'.split(',')]
    for token in tokens:
        if token in ops:
            action = 'Apply op to top of stack'
            ops[token](stack)
            table.append( (token, action, ' '.join(str(s) for s in stack)) )
        else:
            action = 'Push num onto top of stack'
            op_num(stack, eval(token))
            table.append( (token, action, ' '.join(str(s) for s in stack)) )
    return table

if __name__ == '__main__':
    rpn = '3 4 2 * 1 5 - 2 3 ^ ^ / +'
    print( 'For RPN expression: %r\n' % rpn )
    rp = rpn_calc(get_input(rpn))
    maxcolwidths = [max(len(y) for y in x) for x in zip(*rp)]
    row = rp[0]
    print( ' '.join('{cell:^{width}}'.format(width=width, cell=cell) for (width, cell) in zip(maxcolwidths, row)))
    for row in rp[1:]:
        print( ' '.join('{cell:<{width}}'.format(width=width, cell=cell) for (width, cell) in zip(maxcolwidths, row)))

    print('\n The final output value is: %r' % rp[-1][2])



COBOL:        IDENTIFICATION DIVISION.
       PROGRAM-ID. RPN.
       AUTHOR.  Bill Gunshannon.
       INSTALLATION.  
       DATE-WRITTEN.  9 Feb 2020.
      ************************************************************
      ** Program Abstract:
      **   Create a stack-based evaluator for an expression in  
      **   reverse Polish notation (RPN)   that also shows the
      **   changes in the stack as each individual token is
      **   processed as a table.
      ************************************************************
       
       DATA DIVISION.
       
       
       WORKING-STORAGE SECTION.
       
       01  LineIn               PIC X(25).
       01  IP                   PIC 99
                  VALUE 1.
       01  CInNum               PIC XXXX.

       01  Stack                PIC S999999V9999999
               OCCURS  50 times.
       01  SP                   PIC 99
                  VALUE 1.
       01  Operator             PIC X.
       01  Value1               PIC S999999V9999999.
       01  Value2               PIC S999999V9999999.
       01  Result               PIC S999999V9999999.
       01  Idx                  PIC 99.
       01  FormatNum            PIC ZZZZZZ9.9999999.
       01  Zip                  PIC X.
       
       PROCEDURE DIVISION.
       
       Main-Program.
            DISPLAY "Enter the RPN Equation: " 
                     WITH NO ADVANCING.
            ACCEPT LineIn.

            PERFORM UNTIL IP GREATER THAN 
                          FUNCTION STORED-CHAR-LENGTH(LineIn)


            UNSTRING LineIn DELIMITED BY SPACE INTO CInNum 
                    WITH POINTER IP

            MOVE CInNum TO Operator

            PERFORM Do-Operation

            PERFORM Show-Stack

            END-PERFORM.

            DISPLAY "End Result: " FormatNum

           STOP RUN.
       
       Do-Operation.

          EVALUATE Operator
          WHEN "+"
                        PERFORM Pop
                        Compute Result = Value2 + Value1
                        PERFORM Push

          WHEN "-"
                        PERFORM Pop
                        Compute Result = Value2 - Value1
                        PERFORM Push

          WHEN "*"
                        PERFORM Pop
                        Compute Result = Value2 * Value1
                        PERFORM Push

          WHEN "/"
                        PERFORM Pop
                        Compute Result = Value2 / Value1
                        PERFORM Push

          WHEN "^"
                        PERFORM Pop
                        Compute Result = Value2 ** Value1
                        PERFORM Push

          WHEN NUMERIC
                       MOVE Operator TO Result
                       PERFORM Push
          END-EVALUATE.


       Show-Stack.

              DISPLAY "STACK: " WITH NO ADVANCING.
              MOVE 1 TO Idx.
              PERFORM UNTIL (Idx = SP)
                      MOVE Stack(Idx) TO FormatNum
                      IF Stack(Idx) IS NEGATIVE
                         THEN
                              DISPLAY "    -" FUNCTION TRIM(FormatNum)
                                             WITH NO ADVANCING
                         ELSE
                              DISPLAY FormatNum WITH NO ADVANCING
                     END-IF
                      ADD 1 to Idx
              END-PERFORM.
                      DISPLAY " ".

       Push.

             MOVE Result TO Stack(SP)
             ADD 1 TO SP.

       Pop.

            SUBTRACT 1 FROM SP
            MOVE Stack(SP) TO Value1
            SUBTRACT 1 FROM SP
            MOVE Stack(SP) TO Value2.


       END-PROGRAM.