{                 Arthur Thiago Lebrum     -  012558-1

                  Daniel da Silva Taranta  -  002558-5
}                  

program equacao;

uses crt;

{inicio da extrutura de pilha}
type tpilhar = record
                    vet:  array[1..200] of real;
                    topo: integer;
              end;

type tpilhac = record
                    vet:  array[1..200] of char;
                    topo: integer;
              end;

var pr: tpilhar;
    pc: tpilhac;
    e : string;

procedure inicio; forward;

procedure initr(var p:tpilhar);
begin
     p.topo:=0;
end;

procedure initc(var p:tpilhac);
begin
     p.topo:=0;
end;

function isemptyr(p:tpilhar):boolean;
begin
     isemptyr:=(p.topo=0);
end;

function isemptyc(p:tpilhac):boolean;
begin
     isemptyc:=(p.topo=0);
end;

function isfullr(p:tpilhar):boolean;
begin
     isfullr:=(p.topo=200);
end;

function isfullc(p:tpilhac):boolean;
begin
     isfullc:=(p.topo=200);
end;

procedure pushr(var p:tpilhar;elem:real);
begin
     if isfullr(p) then
        begin
        writeln('OVERFLOW!');
        readln;
        halt;
        end
     else
        begin
        p.topo:=p.topo+1;
        p.vet[p.topo]:=elem;
        end;
end;

procedure pushc(var p:tpilhac;elem:char);
begin
     if isfullc(p) then
        begin
        writeln('OVERFLOW!');
        readln;
        halt;
        end
     else
        begin
        p.topo:=p.topo+1;
        p.vet[p.topo]:=elem;
        end;
end;

function popr(var p:tpilhar): real;
begin
     if isemptyr(p) then
        begin
        writeln('UNDERFLOW!');
        readln;
        halt;
        end
     else
        begin
        popr:=p.vet[p.topo];
        p.topo:=p.topo-1;
        end;
end;

function popc(var p:tpilhac): char;
begin
     if isemptyc(p) then
        begin
        writeln('UNDERFLOW!');
        readln;
        halt;
        end
     else
        begin
        popc:=p.vet[p.topo];
        p.topo:=p.topo-1;
        end;
end;

function topr(p:tpilhar): real;
begin
     topr:=p.vet[p.topo];
end;

function topc(p:tpilhac): char;
begin
     topc:=p.vet[p.topo];
end;
{fim da estrutura de pilha}

function prio(c:char):integer;
begin
     case c of
     '(': prio:=3;
     '-',
     '+': prio:=2;
     '/',
     '*': prio:=1;
     end;
end;

function posfixa(p:tpilhac; e:string):string;
var i : integer;
    num,s : string;
begin
     for i:=1 to length(e) do
     begin
          if e[i] in ['(',')','/','*','-','+'] then
          begin
               if num<>'' then
                  begin
                  s := s + num + ' ';
                  num := '';
                  end;
               if e[i] = '(' then pushc(p,e[i]);
               if e[i] in ['-','+','/','*'] then
                  begin
                  while prio(e[i]) >= prio(topc(p)) do s := s + popc(p);
                  pushc(p,e[i]);
                  end;
               if e[i] = ')' then
                  begin
                       while topc(p)<>'(' do s := s + popc(p);
                       popc(p);
                  end;
          end
          else
          begin
               num:=num+e[i]
          end;
     end;
s := s + num;
while not isemptyc(p) do s := s + popc(p);
writeln;
writeln('       Expresao posfixa: ' + s);
posfixa := s;
end;

procedure calcula(p:tpilhar;s:string);
var i,Code : integer;
    num    : string;
    r1,r2  : real;
begin
num:='';
     for i:=1 to length(s) do
     begin
          if s[i] in ['/','*','-','+',' '] then
          begin
               if num<>'' then
                  begin
                  Val(num, r1, Code);
                  pushr(p,r1);
                  num := '';
                  end;
               if s[i] in ['-','+','/','*'] then
                  begin
                       r2:=popr(p);
                       r1:=popr(p);
                       case s[i] of
                            '-': r1 := r1 - r2;
                            '+': r1 := r1 + r2;
                            '/': r1 := r1 / r2;
                            '*': r1 := r1 * r2;
                            end;
                       pushr(p,r1);
                  end;
          end
          else
          begin
               num:=num+s[i]
          end;
     end;
writeln;
write('O resultado da expresao: ');
writeln(r1:00:00);
writeln;
writeln;
inicio;
end;

procedure inicio;
begin
initr(pr);
initc(pc);
write(' Entre com uma expresao: ');
readln(e);
if e<>'' then calcula(pr,posfixa(pc,e));
end;

begin
clrscr;
inicio;
end.