You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
1.7 KiB
73 lines
1.7 KiB
use "itertools"
|
|
|
|
class RPN
|
|
fun operate(a : I64, b : I64, op : String) : I64 =>
|
|
match op
|
|
| "+" => return a + b
|
|
| "*" => return a * b
|
|
| "/" => return a / b
|
|
| "-" => return a - b
|
|
else
|
|
0
|
|
end
|
|
|
|
fun calculate(exp : String, env : Env)? =>
|
|
let tokens = this.tokenize(exp)
|
|
let stack : Array[I64] = []
|
|
|
|
for token in tokens do
|
|
match token
|
|
| let op : String =>
|
|
try
|
|
stack.push(this.operate(stack.pop()?, stack.pop()?, op))
|
|
else
|
|
env.out.print("Error: stack underflow, exiting")
|
|
return
|
|
end
|
|
|
|
| let n : I64 =>
|
|
stack.push(n)
|
|
end
|
|
end
|
|
|
|
env.out.print(stack.apply(0)?.string())
|
|
|
|
None
|
|
|
|
fun tokenize(exp : String) : Iter[(I64 | String)] =>
|
|
// We use a union type since read_int returns (I64, USize), and we want I64 | String
|
|
Iter[String](exp.split(" ").values())
|
|
.filter({
|
|
(c) => (c != "") and (c != "\t") and (c != "\n")
|
|
})
|
|
.map[(I64 | String)]({
|
|
(n) =>
|
|
try
|
|
// ? indicates it could return an exception
|
|
match n.read_int[I64]() ?
|
|
// returns the character if no int was found
|
|
| (0, 0) => n
|
|
| (let n' : I64, let s : USize) => n'
|
|
end
|
|
else
|
|
n
|
|
end
|
|
})
|
|
|
|
new val create() =>
|
|
// Make the RPN class a val
|
|
// This means the instance is immutable
|
|
// It can be safely aliased
|
|
"""
|
|
"""
|
|
|
|
actor Main
|
|
new create(env : Env) =>
|
|
let calc = RPN.create()
|
|
let input : String = " ".join(Iter[String](env.args.values()).skip(1))
|
|
|
|
try
|
|
calc.calculate(input, env)?
|
|
else
|
|
None
|
|
end
|
|
|