1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188:
| unit modParser;
interface uses sysutils,stdctrls,classes,math,dialogs;
TYPE EparserError=class(Exception); Rparameters= record x,y,z:extended; end; Const parameter:Rparameters=(x:1;y:1;z:1); TYPE
TZMathEdit=class(TEdit) private function getEvaluatedString:string; public property TextValue:string read getEvaluatedString; end;
function EvaluateToFloat(s0:string):extended; Function GetEvaluationError:string; procedure Register;
implementation
const sopps:string=('+-*/^'); Pi = 3.1415926535897932384626433832795; var EvaluationError:string;
procedure Register; begin RegisterComponents('Samples', [TZMathEdit]); end; function evaluate(s0:string):extended;forward;
procedure matchbracket(var i:integer;s0:string); var j,len:integer; begin j:=1;len:=length(s0); repeat inc(i); if i>len then raise EparserError.Create('missing '')'''); if s0[i]='(' then inc(j); if s0[i]=')' then dec(j); if j<0 then raise EparserError.Create('missing ''('''); until j=0; end;
function getvalue(s0:string):extended; begin if length(s0)<1 then raise EparserError.Create('syntax error'); if length(s0)=1 then result:=StrToDbl(s0) else case s0[1] of 'x':result:=parameter.x; 'y':result:=parameter.y; 'z':result:=parameter.z; else result:=StrToDbl(s0); end; end;
function specialF(p1:integer;s0:string):extended; var operstr: string; arg : extended; begin operstr:=copy(s0,1,p1-1); operstr := LowerCase(operstr); if s0[length(s0)]<>')' then EparserError.CreateFmt('incorrect syntax %s',[s0]); arg:=evaluate(copy(s0,p1+1,length(s0)-p1-1)); if operstr = 'sin' then result:=sin(arg) else if operstr = 'cos' then result:=cos(arg) else if operstr = 'tan' then result:=sin(arg)/cos(arg) else if operstr = 'cot' then result:=cos(arg)/sin(arg) else if operstr = 'sec' then result:=1/sin(arg) else if operstr = 'cosec' then result:=1/cos(arg) else if operstr = 'arctan' then result:=arctan(arg) else if operstr = 'arccot' then result:=1/arctan(arg) else if operstr = 'arcsin' then result:=arcsin(arg) else if operstr = 'arccos' then result:=arccos(arg) else if operstr = 'log' then result:=ln(arg)/ln(10) else if operstr = 'ln' then result:=ln(arg) else if operstr = 'exp' then result:=exp(arg) else if operstr = 'sqrt' then result:=sqrt(arg) else if operstr = 'rad' then result:=arg*Pi/180 else if operstr = 'deg' then result:=arg*180/Pi else if operstr = 'pi' then result:=Pi else if operstr = 'round' then result:=Round(arg) else if operstr = 'trunc' then result:=Trunc(arg) else raise EparserError.CreateFmt('unknown function %s',[s0]); end;
function calculate(p1:integer;s0:string):extended; var v1,v2:extended; begin v1:=evaluate(copy(s0,1,p1-1)); v2:=evaluate(copy(s0,p1+1,length(s0)-p1)); case s0[p1] of '+': result:=v1+v2; '-': result:=v1-v2; '/': result:=v1/v2; '*': result:=v1*v2; '^': result:=exp(v2*ln(v1)); else raise EparserError.CreateFmt('invalid operation %s',[s0]); end; end;
function getfirstopp(tot:integer;s0:string):integer; var i:integer; begin if tot=0 then tot:=length(s0); for i:=1 to 5 do begin result:=pos(sopps[i],s0); if ((i<3) and (result>0)) then if ((result=1) or (pos(s0[result-1],sopps)>0)) then result:=0; if result>0 then if result<tot then exit; end; if result>tot then result:=0; end;
function Evaluate(s0:string):extended; var p1,p2,q1:integer; begin p1:=pos('(',s0);p2:=p1; if p2>0 then matchbracket(p2,s0); if p1=1 then begin if p2=length(s0) then begin delete(s0,p2,1);delete(s0,1,1); result:=evaluate(s0); end else result:=calculate(p2+1,s0); exit; end; q1:=getfirstopp(p1,s0); if (p1+q1=0) then begin result:=getvalue(s0); exit; end; if q1<>0 then result:=calculate(q1,s0) else if length(s0)>p2 then result:=calculate(p2+1,s0) else result:=specialF(p1,s0); end;
procedure Cleanup(var s0:string); var i:integer; begin s0:=lowercase(s0); i:=pos(' ',s0); while i>0 do begin delete(s0,i,1); i:=pos(' ',s0); end; end;
function TZMathEdit.GetEvaluatedString:string; var s0:string; begin s0:=text; TRY cleanup(s0); result:=FloatToStr(Evaluate(s0)); EXCEPT on e:exception do result:=e.message; END; end;
function EvaluateToFloat(s0:string):extended; begin TRY evaluationerror:=''; Cleanup(s0); result:=Evaluate(s0); EXCEPT on e:exception do begin evaluationerror:=e.message; result:=0; end; END; end;
Function GetEvaluationError:string; begin result:=evaluationerror; end;
end. |