# RPN Calculator in Rexx

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 `i=4` and `s.i='+'`, the string `s.2=s.2 + s.3` would be generated and executed by `interpret`.

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
```

boykobbatgmaildotcom