# RPN Calculator in Icon

Expression orientation and goal-directed computation being characteristic features of Icon, they are intensively used in our calculator implementation. The program shown below is of the stack-based kind and works as follows.

The main loop (re)sets the stack `stk` to an empty array and attempts reading a line from the standard input. If an end of input is encountered, `read` fails, the loop breaks, and the program terminates. If `read` succeeds, its result is enclosed in a pair of blank characters for ease and uniformity of the parsing that follows.

The main loop's body has only two statements, of which the first one is a ‘scan’ operator (`?`) that does most of the work. It sets `line` as the string being parsed and another `while` loop – the right argument of `?` – as the parsing action.

The condition part of that `while` extracts non-blank substrings `s` from `line`, so that `s` can be parsed in the loop's body. Here, `many` returns the index of the first non-blank character, starting from the current position in `line`. Similarly, `upto` returns the index of the first blank after that. In both cases we need to call `tab` so as to advance the current scan position within `line` and return the string between the old and the new current positions: that is how we obtain the current token in `s`.

Note that the calls to `many` and `upto` do not mention `line` explicitly as their argument. They do not have to, because we use them in the context of the `?` operator, where the subject string is implied.

The body of the parsing `while` is a single but complex expression. It calls `real` on `s`, thus attempting to parse it as a number, and if that is successful, the number is pushed (`put`) on the stack. Failing to be a number, `s` might be an operator, so we check whether its length (`*s`) is `1` and whether it is a substring of `"+-*/"`. We also try `pull`ing off the stack twice, and if all this is successful, we finally invoke the procedure corresponding to the arithmetic operation denoted by `s` – that procedure's name is the string `s` itself. The result is pushed onto the stack.

If `s` is neither a number nor an operator, the last alternative of the expression is in turn: it prints an error message and does `break next` to exit the current loop and jump to the next iteration of the enclosing one, which is reading a new line. Note how all the components of the above described long expression are connected to each other with `|` and `&` to ensure the proper succession of the actions taken according to the logic of the computation.

When the parsing is complete and no error occured so far, it remains to see whether there is exactly one number left on the stack; if so, we print it. More than one entries means that the input expression was incorrect (having too few operators), so in this case we print `"error"`. If `line` was initially empty, the stack is empty as well, therefore the call of `pull` fails. Then so does the `if`, and thus nothing at all is printed, as it has to be.

```procedure main()
ws := ' \t'
while stk := [] & line := " " || read() || " " do {
line ? while tab(many(ws)) & s:=tab(upto(ws)) do
put(stk,real(s)) |
(1=*s & find(s,"+-*/") & y:=pull(stk) & put(stk,s(pull(stk),y))) |
(write("error") & break next)
if y:=pull(stk) then write((0=*stk & y) | "error")
}
end
```

boykobbatgmaildotcom