123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- {$ifdef win32}
- {$H-}
- {$endif}
- {$ifndef fpc}{$N+}{$endif}
- Unit Expr;
- interface
- const
- IntSize2:longbool=false;
- PROCEDURE Eval(Formula : String; { Expression to be evaluated}
- VAR Value : double; { Return value }
- VAR ErrPos : Integer); { error position }
- {
- Simple recursive expression parser based on the TCALC example of TP3.
- Written by Lars Fosdal 1987
- Released to the public domain 1993
- }
- implementation
- type
- real=double;
- PROCEDURE Eval(Formula : String; { Expression to be evaluated}
- VAR Value : double; { Return value }
- VAR ErrPos : Integer); { error position }
- CONST
- Digit: Set of Char = ['0'..'9'];
- VAR
- Posn : Integer; { Current position in Formula}
- CurrChar : Char; { character at Posn in Formula }
- PROCEDURE ParseNext; { returnerer neste tegn i Formulaen }
- BEGIN
- REPEAT
- Posn:=Posn+1;
- IF Posn<=Length(Formula) THEN CurrChar:=Formula[Posn]
- ELSE CurrChar:=^M;
- UNTIL CurrChar<>' ';
- END { ParseNext };
- FUNCTION add_subt: Real;
- VAR
- E : Real;
- Opr : Char;
- FUNCTION mult_DIV: Real;
- VAR
- S : Real;
- Opr : Char;
- FUNCTION Power: Real;
- VAR
- T : Real;
- FUNCTION SignedOp: Real;
- FUNCTION UnsignedOp: Real;
- TYPE
- StdFunc = (fabs, fsqrt, fsqr, fsin, fcos,
- farctan, fln, flog, fexp, ffact,
- fpred,fsucc,fround,ftrunc);
- StdFuncList = ARRAY[StdFunc] of String[6];
- CONST
- StdFuncName: StdFuncList =
- ('ABS','SQRT','SQR','SIN','COS',
- 'ARCTAN','LN','LOG','EXP','FACT',
- 'PRED','SUCC','ROUND','TRUNC');
- VAR
- L, Start : Integer;
- Funnet : Boolean;
- F : Real;
- Sf : StdFunc;
- FUNCTION Fact(I: Integer): Real;
- BEGIN
- IF I > 0 THEN BEGIN Fact:=I*Fact(I-1); END
- ELSE Fact:=1;
- END { Fact };
- BEGIN { FUNCTION UnsignedOp }
- IF CurrChar in Digit THEN
- BEGIN
- Start:=Posn;
- REPEAT ParseNext UNTIL not (CurrChar in Digit);
- IF CurrChar='.' THEN REPEAT ParseNext UNTIL not (CurrChar in Digit);
- IF CurrChar='E' THEN
- BEGIN
- ParseNext;
- REPEAT ParseNext UNTIL not (CurrChar in Digit);
- END;
- Val(Copy(Formula,Start,Posn-Start),F,ErrPos);
- END ELSE
- IF CurrChar='(' THEN
- BEGIN
- ParseNext;
- F:=add_subt;
- IF CurrChar=')' THEN ParseNext ELSE ErrPos:=Posn;
- END ELSE
- BEGIN
- Funnet:=False;
- FOR sf:=fabs TO ftrunc DO
- IF not Funnet THEN
- BEGIN
- l:=Length(StdFuncName[sf]);
- IF Copy(Formula,Posn,l)=StdFuncName[sf] THEN
- BEGIN
- Posn:=Posn+l-1; ParseNext;
- f:=UnsignedOp{$ifdef fpc}(){$endif};
- CASE sf of
- fabs: f:=abs(f);
- fsqrt: f:=SqrT(f);
- fsqr: f:=Sqr(f);
- fsin: f:=Sin(f);
- fcos: f:=Cos(f);
- farctan: f:=ArcTan(f);
- fln : f:=LN(f);
- flog: f:=LN(f)/LN(10);
- fexp: f:=EXP(f);
- ffact: f:=fact(Trunc(f));
- fpred:f:=f-1;
- fsucc:f:=f+1;
- fround:f:=round(f)+0.0;
- ftrunc:f:=trunc(f)+0.0;
- END;
- Funnet:=True;
- END;
- END;
- IF not Funnet THEN
- BEGIN
- ErrPos:=Posn;
- f:=0;
- END;
- END;
- UnsignedOp:=F;
- END { UnsignedOp};
- BEGIN { SignedOp }
- IF CurrChar='-' THEN
- BEGIN
- ParseNext; SignedOp:=-UnsignedOp;
- END
- ELSE IF CurrChar='!' THEN
- BEGIN
- ParseNext; SignedOp:=not longint(round(UnsignedOp))+0.0;
- END
- ELSE SignedOp:=UnsignedOp;
- END { SignedOp };
- BEGIN { Power }
- T:=SignedOp;
- WHILE CurrChar='^' DO
- BEGIN
- ParseNext;
- IF t<>0 THEN t:=EXP(LN(abs(t))*SignedOp) ELSE t:=0;
- END;
- Power:=t;
- END { Power };
- BEGIN { mult_DIV }
- s:=Power;
- WHILE CurrChar in ['*','/','&','¬','\','«','¯'] DO
- BEGIN
- Opr:=CurrChar; ParseNext;
- CASE Opr of
- '*': s:=s*Power;
- '/': s:=s/Power;
- '&': s:=longint(round(s)) and longint(round(power))+0.0;
- '¬': s:=longint(round(s)) mod longint(round(power))+0.0;
- '\': s:=trunc(s/Power);
- '«': s:=longint(round(s)) shl longint(round(power))+0.0;
- '¯': s:=longint(round(s)) shr longint(round(power))+0.0;
- END;
- END;
- mult_DIV:=s;
- END { mult_DIV };
- BEGIN { add_subt }
- E:=mult_DIV;
- WHILE CurrChar in ['+','-','|','å'] DO
- BEGIN
- Opr:=CurrChar; ParseNext;
- CASE Opr of
- '+': e:=e+mult_DIV;
- '-': e:=e-mult_DIV;
- '|': e:=longint(round(e))or longint(round(mult_DIV))+0.0;
- 'å': e:=longint(round(e))xor longint(round(mult_DIV))+0.0;
- END;
- END;
- add_subt:=E;
- END { add_subt };
- procedure Replace(const _from,_to:string);
- var
- p:longint;
- begin
- repeat
- p:=pos(_from,formula);
- if p>0 then
- begin
- delete(formula,p,length(_from));
- insert(_to,formula,p);
- end;
- until p=0;
- end;
- function HexToDecS:longbool;
- var
- DecError:longbool;
- procedure Decim(const pattern:string);
- var
- p,b:longint;
- x: Longword;
- ss,st:string;
- begin
- repeat
- p:=pos(pattern,formula);
- if p>0 then
- begin
- b:=p+length(pattern);
- ss:='';
- if b<=length(formula)then
- begin
- while formula[b]in['0'..'9','a'..'f','A'..'F']do
- begin
- ss:=ss+formula[b];
- inc(b);
- if b>length(formula)then
- break;
- end;
- val('$'+ss,x,posn);
- DecError:=posn<>0;
- str(x:0,st);
- delete(formula,p,length(pattern)+length(ss));
- insert(st,formula,p);
- end;
- end;
- until p=0;
- end;
- begin
- DecError:=false;
- Decim('0x');
- if not DecError then
- Decim('$');
- HexToDecS:=not DecError;
- end;
- BEGIN {PROC Eval}
- if not HexToDecS then
- begin
- value:=0;
- ErrPos:=Posn;
- exit;
- end;
- IF Formula[1]='.'
- THEN Formula:='0'+Formula;
- IF Formula[1]='+'
- THEN Delete(Formula,1,1);
- FOR Posn:=1 TO Length(Formula)
- DO Formula[Posn] := Upcase(Formula[Posn]);
- replace('<<','«');
- replace('>>','¯');
- replace('^','å');
- replace('**','^');
- replace('DIV','\');
- replace('MOD','¬');
- replace('AND','&');
- replace('XOR','å');
- replace('SHR','¯');
- replace('SHL','«');
- replace('NOT','!');
- replace('OR','|');
- Posn:=0;
- ParseNext;
- Value:=add_subt;
- IF CurrChar=^M THEN ErrPos:=0 ELSE ErrPos:=Posn;
- END {PROC Eval};
- END.
|