How to resolve the algorithm Parsing/RPN calculator algorithm step by step in the REXX programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Parsing/RPN calculator algorithm step by step in the REXX programming language

Table of Contents

Problem Statement

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.

3 4 2 * 1 5 - 2 3 ^ ^ / +

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Parsing/RPN calculator algorithm step by step in the REXX programming language

Source code in the rexx programming language

/* REXX ***************************************************************
* 09.11.2012 Walter Pachl  translates from PL/I
**********************************************************************/
fid='rpl.txt'
ex=linein(fid)
Say 'Input:' ex
/* ex=' 3 4 2 * 1 5 - 2 3 ^ ^ / +' */
Numeric Digits 15
expr=''
st.=0
Say 'Stack contents:'
do While ex<>''
  Parse Var ex ch +1 ex
  expr=expr||ch;
  if ch<>' ' then do
    select
      When pos(ch,'0123456789')>0 Then Do
        Call stack ch
        Iterate
        End
      when ch='+' Then do; operand=getstack(); st.sti = st.sti +  operand; end;
      when ch='-' Then do; operand=getstack(); st.sti = st.sti -  operand; end;
      when ch='*' Then do; operand=getstack(); st.sti = st.sti *  operand; end;
      when ch='/' Then do; operand=getstack(); st.sti = st.sti /  operand; end;
      when ch='^' Then do; operand=getstack(); st.sti = st.sti ** operand; end;
      end;
    call show_stack
    end
  end
Say 'The reverse polish expression = 'expr
Say 'The evaluated expression = 'st.1
Exit
stack: Procedure Expose st.
/* put the argument on top of the stack */
  z=st.0+1
  st.z=arg(1)
  st.0=z
  Return
getstack: Procedure Expose st. sti
/* remove and return the stack's top element */
  z=st.0
  stk=st.z
  st.0=st.0-1
  sti=st.0
  Return stk
show_stack: procedure Expose st.
/* show the stack's contents */
  ol=''
  do i=1 To st.0
    ol=ol format(st.i,5,10)
    End
  Say ol
  Return


/*REXX program  evaluates  a   ═════ Reverse Polish notation  (RPN) ═════   expression. */
parse arg x                                      /*obtain optional arguments from the CL*/
if x=''  then x= "3 4 2 * 1 5 - 2 3 ^ ^ / +"     /*Not specified?  Then use the default.*/
tokens=words(x)                                  /*save the  number  of  tokens   "  ". */
showSteps=1                                      /*set to 0 if working steps not wanted.*/
ox=x                                             /*save the  original  value of  X.     */
            do i=1  for tokens;   @.i=word(x,i)  /*assign the input tokens to an array. */
            end   /*i*/
x=space(x)                                       /*remove any superfluous blanks in  X. */
L=max(20, length(x))                             /*use 20 for the minimum display width.*/
numeric digits L                                 /*ensure enough decimal digits for ans.*/
say center('operand', L, "─")        center('stack', L+L, "─")           /*display title*/
$=                                               /*nullify the stack (completely empty).*/
       do k=1  for tokens;   ?=@.k;   ??=?       /*process each token from the  @. list.*/
       #=words($)                                /*stack the count (the number entries).*/
       if datatype(?,'N')  then do;  $=$ ?;   call show  "add to───►stack";  iterate;  end
       if ?=='^'           then ??= "**"         /*REXXify    ^ ───► **    (make legal).*/
       interpret 'y='word($,#-1)  ??  word($,#)  /*compute via the famous REXX INTERPRET*/
       if datatype(y,'N')  then y=y/1            /*normalize the number with ÷ by unity.*/
       $=subword($, 1, #-2)     y                /*rebuild the stack with the answer.   */
       call show ?                               /*display steps (tracing into),  maybe.*/
       end   /*k*/
say                                              /*display a blank line, better perusing*/
say ' RPN input:'  ox;   say "  answer──►"$      /*display original input;  display ans.*/
parse source upper . y .                         /*invoked via  C.L.  or via a REXX pgm?*/
if y=='COMMAND' | \datatype($,"W")  then exit    /*stick a fork in it,  we're all done. */
                                    else exit $  /*return the answer  ───►  the invoker.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: if showSteps  then say center(arg(1), L)            left(space($), L);        return


/*REXX program  evaluates  a   ═════ Reverse Polish notation  (RPN) ═════   expression. */
parse arg x                                      /*obtain optional arguments from the CL*/
if x=''  then x= "3 4 2 * 1 5 - 2 3 ^ ^ / +"     /*Not specified?  Then use the default.*/
tokens=words(x)                                  /*save the  number  of  tokens   "  ". */
showSteps=1                                      /*set to 0 if working steps not wanted.*/
ox=x                                             /*save the  original  value of  X.     */
            do i=1  for tokens;   @.i=word(x,i)  /*assign the input tokens to an array. */
            end   /*i*/
x=space(x)                                       /*remove any superfluous blanks in  X. */
L=max(20, length(x))                             /*use 20 for the minimum display width.*/
numeric digits L                                 /*ensure enough decimal digits for ans.*/
say center('operand', L, "─")        center('stack', L+L, "─")           /*display title*/
Dop= '/ // % ÷';             Bop='& | &&'        /*division operators;  binary operands.*/
Aop= '- + * ^ **'  Dop Bop;  Lop=Aop "||"        /*arithmetic operators; legal operands.*/
$=                                               /*nullify the stack (completely empty).*/
       do k=1  for tokens;   ?=@.k;   ??=?       /*process each token from the  @. list.*/
       #=words($);  b=word($, max(1, #) )        /*the stack count;  the last entry.    */
                    a=word($, max(1, #-1) )      /*stack's  "first"  operand.           */
       division  =wordpos(?, Dop)\==0            /*flag:  doing a some kind of division.*/
       arith     =wordpos(?, Aop)\==0            /*flag:  doing arithmetic.             */
       bitOp     =wordpos(?, Bop)\==0            /*flag:  doing some kind of binary oper*/
       if datatype(?, 'N')   then do; $=$ ?;  call show  "add to───►stack";  iterate;  end
       if wordpos(?, Lop)==0 then do; $=e 'illegal operator:' ?;      leave; end
       if w<2                then do; $=e 'illegal RPN expression.';  leave; end
       if ?=='^'             then ??= "**"       /*REXXify  ^ ──► **   (make it legal). */
       if ?=='÷'             then ??= "/"        /*REXXify  ÷ ──► /    (make it legal). */
       if division  &  b=0   then do; $=e 'division by zero.'      ;  leave; end
       if bitOp & \isBit(a)  then do; $=e "token isn't logical: " a;  leave; end
       if bitOp & \isBit(b)  then do; $=e "token isn't logical: " b;  leave; end
       interpret 'y='   a   ??   b               /*compute with two stack operands*/
       if datatype(y, 'W')   then y=y/1          /*normalize the number with ÷ by unity.*/
       _=subword($, 1, #-2);      $=_ y          /*rebuild the stack with the answer.   */
       call show ?                               /*display (possibly)  a working step.  */
       end   /*k*/
say                                              /*display a blank line, better perusing*/
if word($,1)==e  then $=                         /*handle the special case of errors.   */
say ' RPN input:'  ox;   say " answer───►"$      /*display original input;  display ans.*/
parse source upper . y .                         /*invoked via  C.L.  or via a REXX pgm?*/
if y=='COMMAND' | \datatype($,"W")  then exit    /*stick a fork in it,  we're all done. */
                                    else exit $  /*return the answer  ───►  the invoker.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
isBit: return arg(1)==0 | arg(1)==1              /*returns   1   if arg1 is a binary bit*/
show:  if showSteps  then say center(arg(1), L)           left(space($), L);        return


  

You may also check:How to resolve the algorithm Sort a list of object identifiers step by step in the VBScript programming language
You may also check:How to resolve the algorithm Arithmetic-geometric mean step by step in the Pascal programming language
You may also check:How to resolve the algorithm Sorting algorithms/Gnome sort step by step in the Common Lisp programming language
You may also check:How to resolve the algorithm Compare a list of strings step by step in the Sidef programming language
You may also check:How to resolve the algorithm Ackermann function step by step in the MAXScript programming language