PLACE |
spec |
solutions |
Scala |
The program starts by creating a stack variable st
where intermediate values go in the course of evaluating an RPN expression.
The reading and processing of the input are performed in an ‘infinite’ loop. In fact the loop does end by calling exit
upon detection of null
instead of an actual string – signifying end-of-input – as the value received in s
from readLine
.
A non-null
string s
is being split into an array of tokens tks
by first replacing all tab characters with spaces and then telling split
to use spaces as delimiters. As empty tokens appear wherever there are two or more spaces in a row, the former get removed by calling filter
.
The tks
array is processed by means of a for
loop where individual tokens tk
are extracted in sequence.
A token tk
is tried as a number at first. If it fails to parse as such, toDouble
raises an exception, and the catch
part of the try
statement reacts by checking whether tk
is an operator character; if so, the corresponding operation is performed, provided there are arguments for it kept on the stack st
. In case the latter does not hold, one of the two calls of pop
fails with generating an exception.
The initial zero values for x
and y
in the for
's body are immaterial but required by the language's rules.
A successfully processed token eventually leads to a value x
, either directly read or computed, being pushed on the stack. For a token that is neither a number nor an operator, however, an exception is throw
n explicitly. An exception is also raised if, after all the tokens successfully get processed, st
happens to hold more than one number. Thus all kinds of syntax errors that may be there in an RPN expression result in an exception being raised. As the whole evaluation of an input line takes place within a try
statement, any such exception is caught and handled by printing an error message instead of a numeric result.
The names Stack
and exit
are qualified by prefixing them by the corresponding package names. Others, namely readLine
and println
are not explicitly qualified. They are provided (along with a number of other definitions of basic entities) by an implicitly imported object called Predef
.
As given here, the program can be run by the Scala interpreter but not compiled. If a form suitable for compiling is needed, a couple of lines must be added to put an object context around the code.
var st = new scala.collection.mutable.Stack[Double] while (true) { var s = readLine if (s==null) sys.exit() val tks = s.replaceAllLiterally("\t"," ").split(" ").filter(_!="") try { for (tk <- tks) { var x = 0.; var y = 0. try {x = tk.toDouble} catch {case _ => { y = st.pop; x = st.pop tk match {case "+" => x += y case "-" => x -= y case "*" => x *= y case "/" => x /= y case _ => throw new Error}}} st.push(x) } if (st.length>1) throw new Error if (!st.isEmpty) println(st.pop) } catch {case _ => {println("error"); st.clear}} }
boykobbatgmaildotcom