74 lines
2.3 KiB
Plaintext
74 lines
2.3 KiB
Plaintext
% Split string by whitespace
|
|
split = iter (expr: string) yields (string)
|
|
own whitespace: string := " \r\n\t"
|
|
cur: array[char] := array[char]$[]
|
|
for c: char in string$chars(expr) do
|
|
if string$indexc(c, whitespace) = 0 then
|
|
array[char]$addh(cur, c)
|
|
else
|
|
if array[char]$empty(cur) then continue end
|
|
yield(string$ac2s(cur))
|
|
cur := array[char]$[]
|
|
end
|
|
end
|
|
if ~array[char]$empty(cur) then
|
|
yield(string$ac2s(cur))
|
|
end
|
|
end split
|
|
|
|
% Tokenize a RPN expression
|
|
token = oneof[number: real, op: char]
|
|
tokens = iter (expr: string) yields (token) signals (parse_error(string))
|
|
own operators: string := "+-*/^"
|
|
for t: string in split(expr) do
|
|
if string$size(t) = 1 cand string$indexc(t[1], operators)~=0 then
|
|
yield(token$make_op(t[1]))
|
|
else
|
|
yield(token$make_number(real$parse(t)))
|
|
except when bad_format:
|
|
signal parse_error(t)
|
|
end
|
|
end
|
|
end
|
|
end tokens
|
|
|
|
% Print the stack
|
|
print_stack = proc (stack: array[real])
|
|
po: stream := stream$primary_output()
|
|
for num: real in array[real]$elements(stack) do
|
|
stream$puts(po, f_form(num, 5, 5) || " ")
|
|
end
|
|
stream$putl(po, "")
|
|
end print_stack
|
|
|
|
% Evaluate an expression, printing the stack at each point
|
|
evaluate_rpn = proc (expr: string) returns (real) signals (parse_error(string), bounds)
|
|
stack: array[real] := array[real]$[]
|
|
for t: token in tokens(expr) do
|
|
tagcase t
|
|
tag number (n: real): array[real]$addh(stack, n)
|
|
tag op (f: char):
|
|
r: real := array[real]$remh(stack)
|
|
l: real := array[real]$remh(stack)
|
|
n: real
|
|
if f='+' then n := l+r
|
|
elseif f='-' then n := l-r
|
|
elseif f='*' then n := l*r
|
|
elseif f='/' then n := l/r
|
|
elseif f='^' then n := l**r
|
|
end
|
|
array[real]$addh(stack, n)
|
|
end
|
|
print_stack(stack)
|
|
end resignal parse_error
|
|
return(array[real]$reml(stack))
|
|
end evaluate_rpn
|
|
|
|
start_up = proc ()
|
|
po: stream := stream$primary_output()
|
|
expr: string := "3 4 2 * 1 5 - 2 3 ^ ^ / +"
|
|
|
|
stream$putl(po, "Expression: " || expr)
|
|
stream$putl(po, "Result: " || f_form(evaluate_rpn(expr), 5, 5))
|
|
end start_up
|