-- Nome del programma: Equation_Parsing.adb -- Autori : Stefano Candolfi, Jonathan Rey -- Data : 31.05.2001 - 27.06.2001 -- Scopo: Package body per il Package Equation_Parsing with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions; package body Equation_Parsing is function Evaluate(F: STRING; Lung_F: INTEGER; X: FLOAT) return FLOAT is type T_ENTITA is (Operatore, No); type T_NODO (Termine: T_ENTITA); type P_RAMO is access T_NODO; type T_NODO (Termine : T_ENTITA) is record case Termine is when Operatore => Nodo_Operatore: CHARACTER; Sx: P_RAMO; Dx: P_RAMO; when No => Nodo_Numero: FLOAT; end case; end record; F_String: STRING(1..100); Result: FLOAT; Root : P_RAMO; -------------------------------------------------------------------------------- function Find_Operator (Funz: STRING; Ini, Fi :INTEGER ) return INTEGER is Trovato : BOOLEAN := False; Giri : INTEGER := 1; Parentesi : INTEGER := 0; Indice : INTEGER := 0; Inizio,Fine : INTEGER; begin Inizio:=Ini; Fine:=Fi; if(Funz(Inizio)='(')and(Funz(Fine)=')')then Inizio:=Inizio+1; Fine:=Fine+1; end if; loop Parentesi := 0; Parentesi := 0; for I in Inizio..Fine loop if Giri < 6 then -- fino al sesto giro cerco if Funz(I) = '(' then -- solo fuori dalle parentesi Parentesi := Parentesi + 1; end if; end if; if Funz(I) = ')' then Parentesi := Parentesi - 1; end if; if((Giri = 1) or (Giri = 6)) and (Parentesi = 0) then if Funz(I) = '+' then -- esco se trovo un + Trovato := True; Indice := I; exit; end if; end if; if((Giri = 2) or (Giri = 7)) and (Parentesi = 0) then if Funz(I) = '-' then -- cerco l`ultimo - e esco Indice := I; Trovato := True; end if; end if; if((Giri = 3) or (Giri = 8)) and (Parentesi = 0) then if Funz(I) = '*' then -- esco se trovo un * Trovato := True; Indice := I; exit; end if; end if; if((Giri = 4) or (Giri = 9)) and (Parentesi = 0) then if Funz(I) ='/' then -- cerco l`ultimo \ e esco Trovato := True; Indice := I; exit; end if; end if; if((Giri = 5) or (Giri = 10)) and (Parentesi = 0) then if Funz(I)= '^' then -- esco se trovo ^ Trovato := True; Indice := I; exit; end if; end if; end loop; Giri := Giri + 1; exit when (Giri = 11) or (Trovato = true); end loop; if Trovato = False then Indice := -1; -- se non trovo un operatore ritorno -1 end if; return indice; -- ritorno l`indice dell`operatore end Find_Operator; -------------------------------------------------------------------------------- function Converter(Numero_Str: STRING; Ini, Fine: INTEGER) return FLOAT is Result : FLOAT; Indent_Sup : INTEGER; Conta_Sup : INTEGER := 0; Temp : STRING(1..100); Incognita: BOOLEAN := False; begin Temp := Numero_Str; for I in Ini..Fine loop if Numero_Str(I) = '(' then Temp(I..I) := "0"; -- se trova una '(' mette a '0' end if; if Numero_Str(I) = ')' then Conta_Sup := Conta_Sup + 1; -- se trova una ')' incrementa end if; if Numero_Str(I) = 'X' or Numero_Str(I) = 'x' then Incognita := True; -- se trova una x da il valore end if; -- assegnato dall'utente end loop; if Incognita then Result := X; else Indent_Sup := Fine - Conta_Sup; -- diminuisce di quante ')' ha trovato Result := FLOAT'Value(Temp(Ini..Indent_Sup)); -- attributo per conversione end if; -- di una stringa a un float return Result; end Converter; -------------------------------------------------------------------------------- procedure Create_Tree( P: in out P_RAMO; Funz : in out STRING; Ini,Fine : in INTEGER ) is N: INTEGER; Numero : FLOAT; begin N := Find_Operator(Funz, Ini, Fine); -- cerco l`operatore if N = -1 then P := new T_NODO(Termine => No); -- creo nuovo nodo contenente il valore Numero := Converter(Funz, Ini, Fine); P.Nodo_Numero := Numero; else P := new T_NODO(Termine => Operatore); P.Nodo_Operatore := Funz(N); -- creo nuovo nodo e richiamo la funzione Create_Tree(P.Sx, Funz, Ini, N-1); Create_Tree(P.Dx, Funz, N+1, Fine); end if; end Create_Tree; -------------------------------------------------------------------------------- function Calculate_Tree(I: P_RAMO) return FLOAT is Ok: BOOLEAN; Result: FLOAT; function Value(I: P_RAMO) return FLOAT is X1, X2 : FLOAT; begin if Ok then case I.Termine is -- valuta se e' operatore o numero when Operatore => case I.Nodo_Operatore is -- valuta l'operazione da fare when '+' => return Value(I.Sx) + Value(I.Dx); when '-' => return Value(I.Sx) - Value(I.Dx); when '*' => return Value(I.Sx) * Value(I.Dx); when '/' => return Value(I.Sx) / Value(I.Dx); when '^' => X1 := Value(I.Sx); X2 := Value(I.Dx); return X1**X2; when others => null; end case; when No => return I.Nodo_Numero; end case; end if; end Value; begin if I.Termine /= No then -- se e' un operatore richiamo Ok := True; -- la funzione Value ricorsivamente Result:= Value(I); end if; return Result; end Calculate_Tree; -- Inizio corpo della funzione Evaluate ---------------------------------------- begin if Lung_F <= 100 then -- se una stringa e' piu' grande F_String(1..100) := F(1..100); -- o piccola viene "standardizzata" else -- alle nostre esigenze F_String(1..Lung_F) := F(1..Lung_F); end if; Create_Tree(Root, F_String, 1, Lung_F); Result := Calculate_Tree(Root); return Result; end Evaluate; end Equation_Parsing;