The program reads input lines in the variable
line. Each line is processed by parsing its beginning, so that a token is extracted and the line is shortened correspondingly. This is done by means of the
parse statement and goes on repeatedly until the line is finally empty. Each token is processed as described below. A stack of intermediate values
s is maintained, with a topmost item indexed by the current value of
i. When there are no more input lines to read, the call of the function
lines in the outer loop returns 0, treated as ‘false’, so the loop is exited and the program terminates.
After a token is extracted into
s.i, it is examined by a call to the function
datatype in order to see if it contains a number – that is what the argument
'N' stands for. Failing this check,
s.i must be an arithmetic operator, or else there is a syntax error.
If the token is an operator, a string is composed and passed to
interpret. That string contains a Rexx statement which performs the arithmetic operation on the top two elements of the stack and modifies the stack accordingly, storing the result as its topmost item.
interpret executes the so formed command in the context of the program – it is just as if that command was in the place of the
interpret statement. For example, if after
parse-ing there was
s.i='+', the string
s.2=s.2 + s.3 would be generated and executed by
Note that when the current token is neither a number nor an operator, or when an operation cannot be performed because the stack has not enough operands (
i<2), the inner loop (processing
line) is exited with
i=2. Thus, the syntax errors due to encountering a wrong token, or having too many operators, are equated to one of another kind – too few operators – and if any of these errors occurs, the final
if will correspondingly output an error message.
do while lines() i = 0 line = linein() do while line\='' parse var line s.i line if datatype(s.i,'N') then i = i+1 else do if i<2 | 1<length(s.i) | 0=pos(s.i,'+-*/') then do; i = 2; leave; end i = i-1 interpret 's.'||(i-1)'=s.'||(i-1) value('s.'||(i+1)) 's.'i end end if i=1 then say value('s.'||(i-1)) else if i>1 then say 'error' end