PLACE |
spec |
solutions |
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