47 lines
1.4 KiB
SQL
47 lines
1.4 KiB
SQL
create or replace function rpn_calc(str varchar2) return number as
|
|
type num_aa is table of number index by pls_integer;
|
|
type num_stack is record (a num_aa, top pls_integer default 0);
|
|
ns num_stack;
|
|
pos1 integer := 1;
|
|
pos2 integer;
|
|
token varchar2(100);
|
|
op2 number;
|
|
procedure push(s in out nocopy num_stack, x number) is
|
|
begin
|
|
s.top := s.top + 1;
|
|
s.a(s.top) := x;
|
|
end;
|
|
function pop(s in out nocopy num_stack) return number is
|
|
x number;
|
|
begin
|
|
x := s.a(s.top);
|
|
s.top := s.top - 1;
|
|
return x;
|
|
end;
|
|
procedure print_stack(s num_stack) is -- for debugging only; remove from final version
|
|
ps varchar2(4000);
|
|
begin
|
|
for i in 1 .. s.top loop
|
|
ps := ps || s.a(i) || ' ';
|
|
end loop;
|
|
dbms_output.put_line('Stack: ' || rtrim(ps));
|
|
end;
|
|
begin
|
|
while pos1 <= length(str) loop
|
|
pos2 := instr(str || ' ', ' ', pos1);
|
|
token := substr(str, pos1, pos2 - pos1);
|
|
pos1 := pos2 + 1;
|
|
case token
|
|
when '+' then push(ns, pop(ns) + pop(ns));
|
|
when '-' then op2 := pop(ns); push(ns, pop(ns) - op2);
|
|
when '*' then push(ns, pop(ns) * pop(ns));
|
|
when '/' then op2 := pop(ns); push(ns, pop(ns) / op2);
|
|
when '^' then op2 := pop(ns); push(ns, power(pop(ns), op2));
|
|
else push(ns, to_number(token));
|
|
end case;
|
|
print_stack(ns); -- for debugging purposes only
|
|
end loop;
|
|
return pop(ns);
|
|
end rpn_calc;
|
|
/
|