[Back to MATH SWAG index]  [Back to Main SWAG index]  [Original]

{
³ I've written a pwoerfull formula evaluator which can be extended
³ during run-time by adding fuctions, vars and strings containing
³ Because its not very small post me a message if you want to receive it.

Here it goes. It's a unit and an example/demo of some features.

{---------------------------------------------------------}
{  Project : Text Formula Parser                          }
{  Auteur  : G.W. van der Vegt                            }
{---------------------------------------------------------}
{  Datum .tijd  Revisie                                   }
{  900530.1900  Creatie (function call/exits removed)     }
{  900531.1900  Revisie (Boolean expressions)             }
{  900104.2100  Revisie (HEAP Function Storage)           }
{  910327.1345  External Real string vars (tfp_realstr)   }
{               are corrected the same way as the parser  }
{               corrects them before using TURBO's VAL    }
{---------------------------------------------------------}

UNIT Tfp_01;

INTERFACE

{---------------------------------------------------------}
{----Initializes function database                        }
{---------------------------------------------------------}

PROCEDURE Tfp_init(no : INTEGER);

{---------------------------------------------------------}
{----Parses s and returns REAL or STR(REAL:m:n)           }
{---------------------------------------------------------}

FUNCTION  Tfp_parse2real(s : STRING) : REAL;

FUNCTION  Tfp_parse2str(s : STRING;m,n : INTEGER) : STRING;

{---------------------------------------------------------}
{----Tfp_errormsg(tfp_ernr) returns errormessage          }
{---------------------------------------------------------}

VAR
  Tfp_ernr  : BYTE;                     {----Errorcode}

FUNCTION  Tfp_errormsg(nr : INTEGER) : STRING;


{---------------------------------------------------------}
{----Internal structure for functions/vars                }
{---------------------------------------------------------}

TYPE
  tfp_fname = STRING[12];               {----String name                     }

  tfp_ftype = (tfp_noparm,              {----Function or Function()          }
               tfp_1real,               {----Function(VAR r)                 }
               tfp_2real,               {----Function(VAR r1,r2)             }
               tfp_nreal,               {----Function(VAR r;n  INTEGER)      }
               tfp_realvar,             {----Real VAR                        }
               tfp_intvar,              {----Integer VAR                     }
               tfp_boolvar,             {----Boolean VAR                     }
               tfp_realstr);            {----Real String VAR                 }

CONST
  tfp_true  = 1.0;                      {----REAL value for BOOLEAN TRUE     }
  tfp_false = 0.0;                      {----REAL value for BOOLEAN FALSE    }

{---------------------------------------------------------}
{----Adds own FUNCTION or VAR to the parser               }
{    All FUNCTIONS & VARS must be compiled                }
{    with the FAR switch on                               }
{---------------------------------------------------------}

PROCEDURE Tfp_addobj(a : pointer;n : tfp_fname;t : tfp_ftype);


{---------------------------------------------------------}
{----Add Internal Function Packs                          }
{---------------------------------------------------------}

PROCEDURE Tfp_addgonio;

PROCEDURE Tfp_addlogic;

PROCEDURE Tfp_addmath;

PROCEDURE Tfp_addmisc;

{---------------------------------------------------------}

IMPLEMENTATION

CONST
  maxreal  = +9.99999999e37;            {----Internal maxreal                }
  maxparm  = 16;                        {----Maximum number of parameters    }

VAR
  maxfie   : INTEGER;                   {----max no of functions & vars      }
  fiesiz   : INTEGER;                   {----current no of functions & vars  }

TYPE
  fie      = RECORD
               fname : tfp_fname;       {----Name of function or var         }
               faddr : POINTER;         {----FAR POINTER to function or var  }
               ftype : tfp_ftype;       {----Type of entry                   }
             END;

  fieptr   = ARRAY[1..1] OF fie;        {----Will be used as [1..maxfie]     }

VAR
  fiearr   : ^fieptr;                   {----Array of functions & vars       }

{---------------------------------------------------------}

VAR
  Line     : STRING;                    {----Internal copy of string to Parse}
  Lp       : INTEGER;                   {----Parsing Pointer into Line       }
  Nextchar : CHAR;                      {----Character at Lp Postion         }

{---------------------------------------------------------}
{----Tricky stuff to call FUNCTIONS                       }
{---------------------------------------------------------}

{$F+}

VAR
  GluePtr : POINTER;

FUNCTION Call_noparm : REAL;

 INLINE($FF/$1E/GluePtr);  {CALL DWORD PTR GluePtr}

FUNCTION Call_1real(VAR r) : REAL;

 INLINE($FF/$1E/GluePtr);  {CALL DWORD PTR GluePtr}

FUNCTION Call_2real(VAR r1,r2) : REAL;

 INLINE($FF/$1E/GluePtr);  {CALL DWORD PTR GluePtr}

FUNCTION Call_nreal(VAR r,n) : REAL;
 INLINE($FF/$1E/GluePtr);  {CALL DWORD PTR GluePtr}

{$F-}

{---------------------------------------------------------}
{----This routine skips one character                     }
{---------------------------------------------------------}

PROCEDURE Newchar;

BEGIN
  IF (lp<LENGTH(Line))
    THEN INC(Lp);
  Nextchar:=UPCASE(Line[Lp]);
END;

{---------------------------------------------------------}
{----This routine skips one character and                 }
{    all folowing spaces from an expression               }
{---------------------------------------------------------}

PROCEDURE Skip;

BEGIN
  REPEAT
    Newchar;
  UNTIL (Nextchar<>' ');
END;

{---------------------------------------------------------}
{  Number     = Real    (Bv 23.4E-5)                      }
{               Integer (Bv -45)                          }
{---------------------------------------------------------}

FUNCTION Eval_number : REAL;

VAR
  Temp  : STRING;
  Err   : INTEGER;
  value : REAL;

BEGIN
{----Correct .xx to 0.xx}
  IF (Nextchar='.')
    THEN Temp:='0'+Nextchar
    ELSE Temp:=Nextchar;

  Newchar;

{----Correct ñ.xx to ñ0.xx}
  IF (LENGTH(temp)=1) AND (Temp[1] IN ['+','-']) AND (Nextchar='.')
    THEN Temp:=Temp+'0';

  WHILE Nextchar IN ['0'..'9','.','E'] DO
    BEGIN
      Temp:=Temp+Nextchar;
      IF (Nextchar='E')
        THEN
          BEGIN
          {----Correct ñxxx.E to ñxxx.0E}
            IF (Temp[LENGTH(Temp)-1]='.')
              THEN INSERT('0',Temp,LENGTH(Temp));
            Newchar;
            IF (Nextchar IN ['+','-'])
              THEN
                BEGIN
                  Temp:=Temp+Nextchar;
                  Newchar;
                END;
          END
        ELSE Newchar;
    END;

{----Skip trailing spaces}
  IF (line[lp]=' ')
    THEN WHILE (Line[lp]=' ') DO INC(lp);
  nextchar:=line[lp];

{----Correct ñxx. to ñxx.0 but NOT ñxxEñyy.}
  IF (temp[LENGTH(temp)]='.') AND
     (POS('E',temp)=0)
    THEN Temp:=Temp+'0';

  VAL(Temp,value,Err);

  IF (Err<>0) THEN tfp_ernr:=1;

  IF (tfp_ernr=0)
    THEN Eval_number:=value
    ELSE Eval_number:=0;
END;

{---------------------------------------------------------}

FUNCTION Eval_b_expr : REAL; FORWARD;

{---------------------------------------------------------}
{  Factor     = Number                                    }
{    (External) Function()                                }
{    (External) Function(Expr)                            }
{    (External) Function(Expr,Expr)                       }
{     External  Var Real                                  }
{     External  Var Integer                               }
{     External  Var Boolean                               }
{     External  Var realstring                            }
{               (R_Expr)                                  }
{---------------------------------------------------------}

FUNCTION Eval_factor : REAL;

VAR
  ferr    : BOOLEAN;
  param   : INTEGER;
  dummy   : ARRAY[0..maxparm] OF REAL;
  value,
  dummy1,
  dummy2  : REAL;
  temp    : tfp_fname;
  e,
  i,
  index   : INTEGER;
  temps   : STRING;

BEGIN
  CASE Nextchar OF
    '+'  : BEGIN
             Newchar;
             value:=+Eval_factor;
           END;
    '-'  : BEGIN
             Newchar;
             value:=-Eval_factor;
           END;

    '0'..'9',
    '.'  : value:=Eval_number;
    'A'..'Z'
         : BEGIN
             ferr:=TRUE;
             Temp:=Nextchar;
             Skip;
             WHILE Nextchar IN ['0'..'9','_','A'..'Z'] DO
               BEGIN
                 Temp:=Temp+Nextchar;
                 Skip;
               END;

           {----Seek function and CALL it}
             {$R-}
             FOR Index:=1 TO Fiesiz DO
               WITH fiearr^[index] DO
                 IF (fname=temp)
                   THEN
                     BEGIN
                       ferr:=FALSE;

                       CASE ftype OF

                       {----Function or Function()}
                         tfp_noparm  : IF (nextchar='(')
                                        THEN
                                          BEGIN
                                            Skip;

                                            IF (nextchar<>')')
                                              THEN tfp_ernr:=15;

                                            Skip;
                                          END;

                       {----Function(r)}
                         tfp_1real   : IF (nextchar='(')
                                         THEN
                                           BEGIN
                                             Skip;

                                             dummy1:=Eval_b_expr;

                                             IF (tfp_ernr=0) AND
                                                (nextchar<>')')
                                               THEN tfp_ernr:=15;

                                             Skip; {----Dump the ')'}
                                           END
                                         ELSE tfp_ernr:=15;

                       {----Function(r1,r2)}
                         tfp_2real   : IF (nextchar='(')
                                         THEN
                                           BEGIN
                                             Skip;

                                             dummy1:=Eval_b_expr;

                                             IF (tfp_ernr=0) AND
                                                (nextchar<>',')
                                               THEN tfp_ernr:=15;

                                             Skip; {----Dump the ','}
                                             dummy2:=Eval_b_expr;

                                              IF (tfp_ernr=0) AND
                                                 (nextchar<>')')
                                                THEN tfp_ernr:=15;

                                              Skip; {----Dump the ')'}
                                            END
                                          ELSE tfp_ernr:=15;

                       {----Function(r,n)}
                         tfp_nreal   : IF (nextchar='(')
                                         THEN
                                           BEGIN
                                             param:=0;

                                             Skip;
                                             dummy[param]:=Eval_b_expr;

                                             IF (tfp_ernr=0) AND
                                                (nextchar<>',')
                                               THEN tfp_ernr:=15
                                               ELSE
                                                 WHILE (tfp_ernr=0) AND
                                                       (nextchar=',') AND
                                                       (param<maxparm) DO
                                                   BEGIN
                                                     Skip; {----Dump the ','}
                                                     INC(param);
                                                     dummy[param]:=Eval_b_expr;
                                                   END;

                                             IF (tfp_ernr=0) AND
                                                (nextchar<>')')
                                               THEN tfp_ernr:=15;

                                             Skip; {----Dump the ')'}
                                           END
                                         ELSE tfp_ernr:=15;
                       {----Real Var}
                         tfp_realvar    : dummy1:=REAL(faddr^);

                       {----Integer Var}
                         tfp_intvar     : dummy1:=1.0*INTEGER(faddr^);

                       {----Boolean Var}
                         tfp_boolvar    : dummy1:=1.0*ORD(BOOLEAN(faddr^));

                       {----Real string Var}
                         tfp_realstr    : BEGIN
                                             temps:=STRING(faddr^);

                                           {----Delete Leading Spaces}
                                             WHILE (Length(temps)>0) AND
                                                   (temps[1]=' ') DO
                                               Delete(temps,1,1);

                                           {----Delete Trailing Spaces}
                                             WHILE (Length(temps)>0) AND
                                                   (temps[Length(temps)]=' ') Do
                                               Delete(temps,Length(temps),1);

                                          {----Correct .xx to 0.xx}
                                             IF (LENGTH(temps)>=1)  AND
                                                (LENGTH(temps)<255) AND
                                                (temps[1]='.')
                                               THEN Insert('0',temps,1);

                                           {----Correct ñ.xx to ñ0.xx}
                                             IF (LENGTH(temps)>=2) AND
                                                (LENGTH(temps)<255) AND
                                                (temps[1] IN ['+','-']) AND
                                                (temps[2]='.')
                                               THEN Insert('0',temps,2);

                                           {----Correct xx.Eyy to xx0.Exx}
                                             IF (Pos('.E',temps)>0) AND
                                                (Length(temps)<255)
                                               THEN Insert('0',temps,Pos('.E',temps));

                                           {----Correct xx.eyy to xx0.exx}
                                             IF (Pos('.e',temps)>0) AND
                                                (Length(temps)<255)
                                               THEN Insert('0',temps,Pos('.e',temps));
                                           {----Correct ñxx. to ñxx.0 but NOT ñ}
                                             IF (temps[LENGTH(temps)]='.') AND
                                                (POS('E',temps)=0) AND
                                                (POS('e',temps)=0) AND
                                                (Length(temps)<255)
                                               THEN Temps:=Temps+'0';

                                             VAL(temps,dummy1,e);
                                             IF (e<>0)
                                               THEN tfp_ernr:=1;
                                           END;
                       END;

                       IF (tfp_ernr=0)
                         THEN
                           BEGIN
                             glueptr:=faddr;

                             CASE ftype OF
                               tfp_noparm   : value:=call_noparm;
                               tfp_1real    : value:=call_1real(dummy1);
                               tfp_2real    : value:=call_2real(dummy1,dummy2);
                               tfp_nreal    : value:=call_nreal(dummy,param);
                               tfp_realvar,
                               tfp_intvar,
                               tfp_boolvar,
                               tfp_realstr  : value:=dummy1;
                             END;
                           END;
                     END;
             IF (ferr=TRUE)
               THEN tfp_ernr:=2;

             {$R+}
           END;

    '('  : BEGIN
             Skip;

             value:=Eval_b_expr;

             IF (tfp_ernr=0) AND (nextchar<>')') THEN tfp_ernr:=3;

             Skip; {----Dump the ')'}
           END;

    ELSE tfp_ernr:=2;
  END;

  IF (tfp_ernr=0)
    THEN Eval_factor:=value
    ELSE Eval_factor:=0;

END;

{---------------------------------------------------------}
{  Term       = Factor ^ Factor                           }
{---------------------------------------------------------}

FUNCTION Eval_term : REAL;

VAR
  value,
  Exponent,
  dummy,
  Base      : REAL;

BEGIN
  value:=Eval_factor;

  WHILE (tfp_ernr=0) AND (Nextchar='^') DO
    BEGIN
      Skip;

      Exponent:=Eval_factor;

      Base:=value;
      IF (tfp_ernr=0) AND (Base=0)
        THEN value:=0
        ELSE
          BEGIN

          {----Over/Underflow Protected}
            dummy:=Exponent*LN(ABS(Base));
            IF (dummy<=LN(MAXREAL))
               THEN value:=EXP(dummy)
               ELSE tfp_ernr:=11;
          END;

      IF (tfp_ernr=0) AND (Base<0)
        THEN
          BEGIN
          {----allow only whole number exponents}
            IF (INT(Exponent)<>Exponent) THEN tfp_ernr:=4;

            IF (tfp_ernr=0) AND ODD(ROUND(exponent)) THEN value:=-value;
          END;
    END;

  IF (tfp_ernr=0)
    THEN Eval_term:=value
    ELSE Eval_term:=0;
END;

{---------------------------------------------------------}
{----Subterm  = Term * Term                               }
{               Term / Term                               }
{---------------------------------------------------------}

FUNCTION Eval_subterm : REAL;

VAR
  value,
  dummy  : REAL;

BEGIN
  value:=Eval_term;

  WHILE (tfp_ernr=0) AND (Nextchar IN ['*','/']) DO
    CASE Nextchar OF

    {----Over/Underflow Protected}
      '*' : BEGIN
              Skip;

              dummy:=Eval_term;

              IF (tfp_ernr<>0) OR (value=0) OR (dummy=0)
                THEN value:=0
                ELSE IF (ABS( LN(ABS(value)) + LN(ABS(dummy)) )<LN(Maxreal))
                  THEN value:= value * dummy
                  ELSE tfp_ernr:=11;
            END;

    {----Over/Underflow Protected}
      '/' : BEGIN
              Skip;

              dummy:=Eval_term;

              IF (tfp_ernr=0)
                THEN
                  BEGIN

                  {----Division by ZERO Protected}
                    IF (dummy<>0)
                      THEN
                        BEGIN
                        {----Underflow Protected}
                          IF (value<>0)
                            THEN
                              IF (ABS( LN(ABS(value))-LN(ABS(dummy)) )
                                 <LN(Maxreal))
                                THEN value:=value/dummy
                                ELSE tfp_ernr:=11
                        END
                      ELSE tfp_ernr:=9;
                  END;
            END;
    END;

  IF (tfp_ernr=0)
    THEN Eval_subterm:=value
    ELSE Eval_subterm:=0;
END;

{---------------------------------------------------------}
{  Real Expr  = Subterm + Subterm                         }
{               Subterm - Subterm                         }
{---------------------------------------------------------}

FUNCTION Eval_r_expr : REAL;

VAR
  dummy,
  dummy2,
  value : REAL;

BEGIN
  value:=Eval_subterm;

  WHILE (tfp_ernr=0) AND (Nextchar IN ['+','-']) DO
    CASE Nextchar OF

      '+' : BEGIN
              Skip;

              dummy:=Eval_subterm;

              IF (tfp_ernr=0)
                THEN
                  BEGIN

                  {----Overflow Protected}
                    IF (ABS( (value/10)+(dummy/10) )<(Maxreal/10))
                      THEN value:=value+dummy
                      ELSE tfp_ernr:=11;
                  END;
            END;

      '-' : BEGIN
              Skip;
              dummy2:=value;

              dummy:=Eval_subterm;

              IF (tfp_ernr=0)
                THEN
                  BEGIN

                  {----Overflow Protected}
                    IF (ABS( (value/10)-(dummy/10) )<(Maxreal/10))
                      THEN value:=value-dummy
                      ELSE tfp_ernr:=11;

                  {----Underflow Protected}
                    IF (value=0) AND (dummy<>dummy2)
                      THEN tfp_ernr:=11;
                  END;

            END;
    END;

{----At this point the current char must be
        1. the EOLN marker or
        2. a right bracket
        3. start of a boolean operator }

  IF NOT (Nextchar IN [#00,')','>','<','=',','])
    THEN tfp_ernr:=2;

  IF (tfp_ernr=0)
    THEN Eval_r_expr:=value
    ELSE Eval_r_expr:=0;
END;

{---------------------------------------------------------}
{  Boolean Expr  = R_Expr <  R_Expr                       }
{                  R_Expr <= R_Expr                       }
{                  R_Expr <> R_Expr                       }
{                  R_Expr =  R_Expr                       }
{                  R_Expr >= R_Expr                       }
{                  R_Expr >  R_Expr                       }
{---------------------------------------------------------}

FUNCTION Eval_b_expr : REAL;

VAR
  value : REAL;

BEGIN
  value:=Eval_r_expr;

  IF (tfp_ernr=0) AND (Nextchar IN ['<','>','='])
    THEN
      CASE Nextchar OF

        '<' : BEGIN
                Skip;
                IF (Nextchar IN ['>','='])
                  THEN
                    CASE Nextchar OF
                      '>' : BEGIN
                              Skip;
                              IF (value<>Eval_r_expr)
                                THEN value:=tfp_true
                                ELSE value:=tfp_false;
                            END;
                      '=' : BEGIN
                              Skip;
                              IF (value<=Eval_r_expr)
                                THEN value:=tfp_true
                                ELSE value:=tfp_false;
                            END;
                    END
                  ELSE
                    BEGIN
                      IF (value<Eval_r_expr)
                        THEN value:=tfp_true
                        ELSE value:=tfp_false;
                    END;
              END;

        '>' : BEGIN
                Skip;
                IF (Nextchar='=')
                  THEN
                    BEGIN
                      Skip;
                      IF (value>=Eval_r_expr)
                        THEN value:=tfp_true
                        ELSE value:=tfp_false;
                    END
                  ELSE
                    BEGIN
                      IF (value>Eval_r_expr)
                        THEN value:=tfp_true
                        ELSE value:=tfp_false;
                    END;
              END;
        '=' : BEGIN
                Skip;
                IF (value=Eval_r_expr)
                  THEN value:=tfp_true
                  ELSE value:=tfp_false;
              END;
      END;

  IF (tfp_ernr=0)
    THEN Eval_b_expr:=value
    ELSE Eval_b_expr:=0.0;
END;

{---------------------------------------------------------}

PROCEDURE Tfp_init(no : INTEGER);

BEGIN
  IF (maxfie>0)
    THEN FREEMEM(fiearr,maxfie*SIZEOF(fiearr^));

  GETMEM(fiearr,no*SIZEOF(fiearr^));

  maxfie:=no;
  fiesiz:=0;
END;

{---------------------------------------------------------}

FUNCTION Tfp_parse2real(s : string) : REAL;

VAR
  i,h     : INTEGER;
  value   : REAL;

BEGIN
  tfp_ernr:=0;

{----Test for match on numbers of ( and ) }
  h:=0;
  FOR i:=1 TO LENGTH(s) DO
    CASE s[i] OF
      '(' : INC(h);
      ')' : DEC(h);
    END;

  IF (h=0)
    THEN
      BEGIN

      {----Continue init}
        lp:=0;

      {----Add a CHR(0) as an EOLN marker}
        line:=S+#00;
        Skip;

      {----Try parsing if any characters left}
        IF (Line[Lp]<>#00)
          THEN value:=Eval_b_expr
          ELSE tfp_ernr:=6;
      END
    ELSE tfp_ernr:=3;

  IF (tfp_ernr<>0)
    THEN tfp_parse2real:=0.0
    ELSE tfp_parse2real:=value;
END;

{---------------------------------------------------------}

FUNCTION Tfp_parse2str(s : STRING;m,n : INTEGER) : STRING;

VAR
  r   : REAL;
  tmp : STRING;

BEGIN
  r:=Tfp_parse2real(s);
  IF (tfp_ernr=0)
    THEN STR(r:m:n,tmp)
    ELSE tmp:='';
  Tfp_parse2str:=tmp;
END;

{---------------------------------------------------------}

FUNCTION Tfp_errormsg;

BEGIN
  CASE nr OF
    0 : Tfp_errormsg:='Correct resultaat';                      {Error 0 }
    1 : Tfp_errormsg:='Ongeldig getal formaat';                 {Error 1 }
    2 : Tfp_errormsg:='Onbekende functie';                      {Error 2 }
    3 : Tfp_errormsg:='Een haakje mist';                        {Error 3 }
    4 : Tfp_errormsg:='Reele exponent geeft een complex getal'; {Error 4 }
    5 : Tfp_errormsg:='TAN( (2n+1)*PI/2 ) bestaat niet';        {Error 5 }
    6 : Tfp_errormsg:='Lege string';                            {Error 6 }
    7 : Tfp_errormsg:='LN(x) of LOG(x) met x<=0 bestaat niet';  {Error 7 }
    8 : Tfp_errormsg:='SQRT(x) met x<0 bestaat niet';           {Error 8 }
    9 : Tfp_errormsg:='Deling door nul';                        {Error 9 }
   10 : Tfp_errormsg:='Teveel functies & constanten';           {Error 10}
   11 : Tfp_errormsg:='Tussenresultaat buiten getalbereik';     {Error 11}
   12 : Tfp_errormsg:='Illegale tekens in functienaam';         {Error 12}
   13 : Tfp_errormsg:='Geen (on)gelijkheid / te complex';       {Error 13}
   14 : Tfp_errormsg:='Geen booleaanse expressie';              {Error 14}
   15 : Tfp_errormsg:='Verkeerd aantal parameters';             {Error 15}
  ELSE  Tfp_errormsg:='Onbekende fout';                         {Error xx}
  END;
END;

{---------------------------------------------------------}

PROCEDURE Tfp_addobj(a : pointer;n : tfp_fname;t : tfp_ftype);

VAR
  i : INTEGER;

BEGIN
  {$R-}
  IF (fiesiz<maxfie)
    THEN
      BEGIN
        INC(fiesiz);
        WITH fiearr^[fiesiz] DO
          BEGIN
            faddr:=a;
            fname:=n;
            FOR i:=1 TO LENGTH(fname) DO
              IF (UPCASE(fname[i]) IN ['0'..'9','_','A'..'Z'])
                THEN fname[i]:=UPCASE(fname[i])
                ELSE tfp_ernr:=12;
              IF (LENGTH(fname)>0) AND
                 NOT (fname[1] IN ['A'..'Z'])
                THEN tfp_ernr:=12;
              ftype:=t;
          END
      END
    ELSE tfp_ernr:=10
  {$R+}
END;

{---------------------------------------------------------}
{----Internal Functions                                   }
{---------------------------------------------------------}

{$F+}
FUNCTION xABS(VAR r : REAL) : REAL;

BEGIN
 xabs:=ABS(r);
END;

FUNCTION xAND(VAR r;VAR n : INTEGER) : REAL;

TYPE
  tmp   = ARRAY[0..0] OF REAL;

VAR
  x     : REAL;
  i     : INTEGER;

BEGIN
{$R-}
  FOR i:=0 TO n DO
    IF (tmp(r)[i]<>tfp_false) AND (tmp(r)[i]<>tfp_true)
      THEN
        BEGIN
          IF (tfp_ernr=0)
            THEN tfp_ernr:=14;
        END;
   IF (tfp_ernr=0) AND (n>0)
     THEN
       BEGIN
         x:=tfp_true*ORD(tmp(r)[0]=tfp_true);
         FOR i:=1 TO n DO
           x:=tfp_true*ORD((x=tfp_true) AND (tmp(r)[i]=tfp_true))
       END
     ELSE tfp_ernr:=15;
  IF tfp_ernr=0
    THEN xAND:=x
    ELSE xAND:=0.0;
{$R+}
END;

FUNCTION xARCTAN(VAR r : REAL) : REAL;

BEGIN
  xARCTAN:=ARCTAN(r);
END;

FUNCTION xCOS(VAR r : REAL) : REAL;

BEGIN
  xCOS:=COS(r);
END;

FUNCTION xDEG(VAR r : REAL) : REAL;

BEGIN
  xDEG:=(r/pi)*180;
END;

FUNCTION xE : REAL;

BEGIN
  xE:=EXP(1);
END;

FUNCTION xEXP(VAR r : REAL) : REAL;

BEGIN
  xEXP:=0;
  IF (ABS(r)<LN(MAXREAL))
    THEN xEXP:=EXP(r)
    ELSE tfp_ernr:=11;
END;

FUNCTION xFALSE : REAL;

BEGIN
  xFALSE:=tfp_false;
END;

FUNCTION xFRAC(VAR r : REAL) : REAL;

BEGIN
  xFRAC:=FRAC(r);
END;

FUNCTION xINT(VAR r : REAL) : REAL;

BEGIN
  xINT:=INT(r);
END;

FUNCTION xLN(VAR r : REAL) : REAL;

BEGIN
  xLN:=0;
  IF (r>0)
    THEN xLN:=LN(r)
    ELSE tfp_ernr:=7;
END;

FUNCTION xLOG(VAR r : REAL) : REAL;

BEGIN
  xLOG:=0;
  IF (r>0)
    THEN xLOG:=LN(r)/LN(10)
    ELSE tfp_ernr:=7;
END;

FUNCTION xMAX(VAR r;VAR n : INTEGER) : REAL;

TYPE
  tmp   = ARRAY[0..0] OF REAL;

VAR
  max   : REAL;
  i     : INTEGER;

BEGIN
{$R-}
  max:=tmp(r)[0];
  FOR i:=1 TO n DO
    IF (tmp(r)[i]>max)
      THEN max:=tmp(r)[i];
  xMAX:=max;
{$R+}
END;

FUNCTION xMIN(VAR r;VAR n : INTEGER) : REAL;

TYPE
  tmp   = ARRAY[0..0] OF REAL;

VAR
  min   : REAL;
  i     : INTEGER;

BEGIN
{$R-}
  min:=tmp(r)[0];
  FOR i:=1 TO n DO
    IF (tmp(r)[i]<min)
      THEN min:=tmp(r)[i];
  xMIN:=min;
{$R+}
END;
FUNCTION xIOR(VAR r;VAR n : INTEGER) : REAL;

TYPE
  tmp   = ARRAY[0..0] OF REAL;

VAR
  x     : REAL;
  i     : INTEGER;

BEGIN
{$R-}
  FOR i:=0 TO n DO
    IF (tmp(r)[i]<>tfp_false) AND (tmp(r)[i]<>tfp_true)
      THEN
        BEGIN
          IF (tfp_ernr=0)
            THEN tfp_ernr:=14;
        END;
   IF (tfp_ernr=0) AND (n>0)
     THEN
       BEGIN
         x:=tfp_true*ORD(tmp(r)[0]=tfp_true);
         FOR i:=1 TO n DO
           x:=tfp_true*ORD((x=tfp_true) OR (tmp(r)[i]=tfp_true))
       END
     ELSE tfp_ernr:=15;
  IF tfp_ernr=0
    THEN xIOR:=x
    ELSE xIOR:=0.0;
{$R+}
END;

FUNCTION xPI : REAL;

BEGIN
  xPI:=PI;
END;

FUNCTION xRAD(VAR r : REAL) : REAL;

BEGIN
  xRAD:=(r/180)*pi;
END;

FUNCTION xROUND(VAR r : REAL) : REAL;

BEGIN
  xROUND:=ROUND(r);
END;

FUNCTION xSGN(VAR r : REAL) : REAL;

BEGIN
  IF (r>=0)
    THEN xSgn:=+1
    ELSE xSgn:=-1;
END;

FUNCTION xSIN(VAR r : REAL) : REAL;

BEGIN
  xSIN:=SIN(r);
END;

FUNCTION xSQR(VAR r : REAL) : REAL;

BEGIN
  xSQR:=0;
  IF ( ABS(2*LN(ABS(r))) )<LN(MAXREAL)
    THEN xSQR:=EXP( 2*LN(ABS(r)) )
    ELSE tfp_ernr:=11;
END;

FUNCTION xSQRT(VAR r : REAL) : REAL;

BEGIN
  xSQRT:=0;
  IF (r>=0)
    THEN xSQRT:=SQRT(r)
    ELSE tfp_ernr:=8;
END;

FUNCTION xTAN(VAR r : REAL) : REAL;

BEGIN
  xTAN:=0;
  IF (COS(r)=0)
    THEN tfp_ernr:=5
    ELSE xTAN:=SIN(r)/COS(r);
END;

FUNCTION xTRUE : REAL;

BEGIN
  xTRUE:=tfp_true;
END;

FUNCTION xXOR(VAR r1,r2 : REAL) : REAL;

BEGIN
 IF ((r1<>tfp_false) AND (r1<>tfp_true)) OR
    ((r2<>tfp_false) AND (r2<>tfp_true))
   THEN
     BEGIN
       IF (tfp_ernr=0)
         THEN tfp_ernr:=14;
     END
   ELSE xxor:=tfp_true*ORD((r1=tfp_true) XOR (r2=tfp_true));
END;

{$F-}

{---------------------------------------------------------}

PROCEDURE Tfp_addgonio;

BEGIN
  Tfp_addobj(@xARCTAN,'ARCTAN',tfp_1real);
  Tfp_addobj(@xCOS   ,'COS'   ,tfp_1real);
  Tfp_addobj(@xDEG   ,'DEG'   ,tfp_1real);
  Tfp_addobj(@xPI    ,'PI'    ,tfp_noparm);
  Tfp_addobj(@xRAD   ,'RAD'   ,tfp_1real);
  Tfp_addobj(@xSIN   ,'SIN'   ,tfp_1real);
  Tfp_addobj(@xTAN   ,'TAN'   ,tfp_1real);
END;

{---------------------------------------------------------}

PROCEDURE Tfp_addlogic;

BEGIN
  Tfp_addobj(@xAND   ,'AND'   ,tfp_nreal);
  Tfp_addobj(@xFALSE ,'FALSE' ,tfp_noparm);
  Tfp_addobj(@xIOR   ,'OR'    ,tfp_nreal);
  Tfp_addobj(@xTRUE  ,'TRUE'  ,tfp_noparm);
  Tfp_addobj(@xXOR   ,'XOR'   ,tfp_2real);
END;

{---------------------------------------------------------}

PROCEDURE Tfp_addmath;
BEGIN
  Tfp_addobj(@xABS   ,'ABS'   ,tfp_1real);
  Tfp_addobj(@xEXP   ,'EXP'   ,tfp_1real);
  Tfp_addobj(@xE     ,'E'     ,tfp_noparm);
  Tfp_addobj(@xLN    ,'LN'    ,tfp_1real);
  Tfp_addobj(@xLOG   ,'LOG'   ,tfp_1real);
  Tfp_addobj(@xSQR   ,'SQR'   ,tfp_1real);
  Tfp_addobj(@xSQRT  ,'SQRT'  ,tfp_1real);
END;

{---------------------------------------------------------}

PROCEDURE Tfp_addmisc;

BEGIN
  Tfp_addobj(@xFRAC  ,'FRAC'  ,tfp_1real);
  Tfp_addobj(@xINT   ,'INT'   ,tfp_1real);
  Tfp_addobj(@xMAX   ,'MAX'   ,tfp_nreal);
  Tfp_addobj(@xMIN   ,'MIN'   ,tfp_nreal);
  Tfp_addobj(@xROUND ,'ROUND' ,tfp_1real);
  Tfp_addobj(@xSGN   ,'SGN'   ,tfp_1real);
END;

{---------------------------------------------------------}

BEGIN
{----Module Init}
  tfp_ernr:=0;
  fiesiz:=0;
  maxfie:=0;
  fiearr:=NIL;
END.

-------------------------------------------------------------<cut here

Program Tfptst;

Uses
  crt,
  tfp_01;

{$F+}  {----Important don't forget it !!!}

Var
  r : real;
  i : Integer;
  t,
  s : String;

FUNCTION xFUZZY(VAR r : REAL) : REAL;

BEGIN
  IF (r>0.5)
    THEN xFUZZY:=0.5
    ELSE xFUZZY:=0.4;
END; {of xFUZZY}

FUNCTION xAGE : REAL;

VAR
  s    : string;
  e    : Integer;
  r    : Real;

BEGIN
{----default value in case of error}
  xAGE:=0;

  Write('Enter your age : '); Readln(s);
  Val(s,r,e);

{----Setting tfp_ernr will flag an error.
     Can be a user defined value}

  IF e<>0
    THEN tfp_ernr:=1
    ELSE xAGE:=r;
END; {of xAge}
{$F-}

Begin
  Tfp_init(40);

{----Add internal function packs}
  Tfp_addgonio;
  Tfp_addlogic;
  Tfp_addmath;
  Tfp_addmisc;

{----Add external functions}
  Tfp_addobj(@r     ,'TEMP'   ,tfp_realvar);
  Tfp_addobj(@i     ,'COUNTER',tfp_intvar);
  Tfp_addobj(@t     ,'USER'   ,tfp_realstr);
  Tfp_addobj(@xfuzzy,'FUZZY'  ,tfp_1real);
  Tfp_addobj(@xage  ,'AGE'    ,tfp_noparm);

  i:=1;
  t:='1.25';
  s:='2*COUNTER';

  Clrscr;

{----Example #1 using FOR index in expression}
  Writeln(tfp_errormsg(tfp_ernr));
  FOR i:=1 TO 3 DO
    Writeln(s,' := ',Tfp_parse2real(s):0:2);
  Writeln(tfp_errormsg(tfp_ernr));

{----Example #2 using a real from the main program}
  r:=15;
  s:='TEMP';
  Writeln(r:0:2,' := ',Tfp_parse2real(s):0:2);

{----Example #3 using a function that does something strange}
  s:='AGE-1';
  Writeln('Last years AGE := ',Tfp_parse2real(s):0:2);

{----Example #4 using a number in a string
     This version doesn't allow recusive formula's yet
     Have a version that does!}
  s:='USER';
  Writeln('USER := ',Tfp_parse2real(s):0:2);

{----All of the above + Internal function PI, &
     Boolean expressions should return 1 because it can't be 1
     Booleans are reals with values of 1.0 and 0.0}
  s:='(SIN(COUNTER+TEMP*FUZZY(AGE)*PI)<>1)=TRUE';
  Writeln('? := ',Tfp_parse2real(s):0:6);

{----Your example goes here, try a readln(s)}

  Writeln(tfp_errormsg(tfp_ernr));
End.

[Back to MATH SWAG index]  [Back to Main SWAG index]  [Original]