Contributor: RAINER HUEBENTHAL        

{
>Does anyone have any source for evaluating math expressions? I would like to
>find some source that can evaluate an expression like
>
> 5 * (3 + 4)  or B * 3 + C
}

Program Test;

Uses
  Strings; {You have to use your own unit}

Var
  x : Real;
  maxvar : Integer;
  s : String;

Const
  maxfun = 21;
  func : Array[1..maxfun] Of String[9] =
           ('LN', 'SINH', 'SIN', 'COSH', 'COS', 'TANH', 'TAN', 'COTH', 'COT',
            'SQRT', 'SQR', 'EXP', 'ARCSIN', 'ARSINH', 'ARCCOS', 'ARCOSH',
            'ARCTAN', 'ARTANH', 'ARCCOT', 'ARCOTH', 'NEG');

Var
  errnum : Integer;

Function Calculate(f : String) : Real;

Var
{  errnum : Integer;}
  eps : Real;

  Function Eval(l, r : Integer) : Real;

  Var
    i, j, k, wo, op : Integer;
    result, t1, t2 : real;

  Begin
    If errnum > 0 Then Exit;
    wo := 0; op := 6; k := 0;

    While (f[l] = '(') And (f[r] = ')') Do Begin
      Inc(l); Dec(r);
    End;

    If l > r Then Begin
      errnum := 1; eval := 0.0; Exit;
    End;

    For i := l To r Do Begin

       Case f[i] of
          '(':  Inc(k);
          ')':  Dec(k);
          Else If k = 0 Then
            Case f[i] of

              '+' : Begin
                wo := i; op := 1
              End;

              '-' : Begin
                wo := i; op := 2
              End;

              '*' : If op > 2 Then Begin
                wo := i; op := 3
              End;

              '/' : If op > 2 Then Begin
                wo := i; op := 4
              End;

              '^' : If op > 4 Then Begin
                wo := i; op := 5
              End;

          End;
       End;
    End;

    If k <> 0 Then Begin
      errnum := 2; eval := 0.0; Exit;
    End;

    If op < 6 Then Begin
       t1 := eval(l, wo-1); If errnum > 0 Then Exit;
       t2 := eval(wo+1, r); If errnum > 0 Then Exit;
    End;

    Case op of
       1 : Begin
         eval := t1 + t2;
       End;

       2 : Begin
         eval := t1 - t2;
       End;

       3 : Begin
         eval := t1 * t2;
       End;

       4 : Begin
         If Abs(t2) < eps Then Begin errnum := 4; eval := 0.0; Exit; End;
         eval := t1 / t2;
       End;

       5 : Begin
         If t1 < eps Then Begin errnum := 3; eval := 0.0; Exit; End;
         eval := exp(t2*ln(t1));
       End;

       6 : Begin

         i:=0;
         Repeat
           Inc(i);
         Until (i > maxfun) Or (Pos(func[i], f) = l);

         If i <= maxfun Then t1 := eval(l+length(func[i]), r);
         If errnum > 0 Then Exit;

         Case i Of
           1 : Begin
             eval := ln(t1);
           End;

           2 : Begin
             eval := (exp(t1)-exp(-t1))/2;
           End;

           3 : Begin
             eval := sin(t1);
           End;

           4 : Begin
             eval := (exp(t1)+exp(-t1))/2;
           End;

           5 : Begin
             eval := cos(t1);
           End;

           6 : Begin
             eval := exp(-t1)/(exp(t1)+exp(-t1))*2+1;
           End;

           7 : Begin
             eval := sin(t1)/cos(t1);
           End;

           8 : Begin
             eval := exp(-t1)/(exp(t1)-exp(-t1))*2+1;
           End;

           9 : Begin
             eval := cos(t1)/sin(t1);
           End;

          10 : Begin
            eval := sqrt(t1);
          End;

          11 : Begin
            eval := sqr(t1);
          End;

          12 : Begin
            eval := exp(t1);
          End;

          13 : Begin
            eval := arctan(t1/sqrt(1-sqr(t1)));
          End;

          14 : Begin
            eval := ln(t1+sqrt(sqr(t1+1)));
          End;

          15 : Begin
            eval := -arctan(t1/sqrt(1-sqr(t1)))+pi/2;
          End;

          16 : Begin
            eval := ln(t1+sqrt(sqr(t1-1)));
          End;

          17 : Begin
            eval := arctan(t1);
          End;

          18 : Begin
            eval := ln((1+t1)/(1-t1))/2;
          End;

          19 : Begin
            eval := arctan(t1)+pi/2;
          End;

          20 : Begin
            eval := ln((t1+1)/(t1-1))/2;
          End;

          21 : Begin
            eval := -t1;
          End;

          Else
            If copy(f, l, r-l+1) = 'PI' Then
              eval := Pi
            Else If copy(f, l, r-l+1) = 'E' Then
              eval := 2.718281828
            Else Begin
              Val(copy(f, l, r-l+1), result, j);
              If j = 0 Then Begin
                eval := result;
              End Else Begin
                {here you can handle other variables}
                errnum := 5; eval := 0.0; Exit;
              End;
            End;

         End
       End
    End
  End;

Begin
{  errnum := 0;} eps := 1.0E-9;

  f := StripBlanks(UpStr(f));
  Calculate := Eval(1, length(f));
End;

Begin
READLN(s);
While length(s) > 0 do Begin
  errnum := 0; x := calculate(s);
  writeln('Ergebnis : ',x:14:6, ' Fehlercode : ', errnum);
  readln(s);
End;
End.

{
You have to write your own function STRIPBLANKS, which eliminates ALL
blanks in a string. And the only variables supported are e and pi. But
it is not difficult to handle other variables.

}