4
{ This parser is used only for z = f(x,y) heightfield 3D graphs }
12
Pi: extended = 3.1415926535897932385;
13
PiOn2: extended = 1.5707963267948966192;
14
twoPi: extended = 6.2831853071795864769;
15
PiOn180: extended = 0.017453292519943296;
17
ParseSet: Set of Char =
18
[' ', '!', '(', ')', '*', '+', '-', '.', ',', '/', '0'..'9',
19
'A'..'E', 'G'..'I', 'L', 'N'..'U', 'X', 'Y', '^', '`', #8];
24
function DefName: string; virtual; abstract;
25
function Eval(x: extended): extended; virtual; abstract;
36
function Eval: extended; virtual; abstract;
39
TfxyParser = class(TObject)
40
constructor Create(x, y: extended);
41
destructor Destroy; override;
45
function FunctionOf(i: integer): TFuncDef;
46
function VariableOf(i: integer): TVarDef;
47
function CheckBrackets(const s: string): Boolean;
48
function CompileExpresion(const s: string; var Error: byte): TCalculus;
49
function FactorCompile(const s: string; var Error: byte): TCalculus;
50
function SimpleCompile(const s: string; var Error: byte): TCalculus;
56
function Compile(s: string; var Error: byte): TCalculus;
57
procedure AddVar(v: TVarDef);
58
procedure ConstructLists;
61
TConst = class(TCalculus)
62
constructor Create(c: extended);
64
function Eval: extended; override;
69
TVar = class(TCalculus)
71
constructor Create(v: TVarDef);
72
function Eval: extended; override;
77
TFunc = class(TCalculus)
78
constructor Create(v: TCalculus; f: TFuncDef);
79
destructor Destroy; override;
81
function Eval: extended; override;
87
TOperator = class(TCalculus)
88
constructor Create(c1, c2: TCalculus);
89
destructor Destroy; override;
95
TMinus = class(TOperator)
97
function Eval: extended; override;
100
TSum = class(TOperator)
102
function Eval: extended; override;
105
TProduct = class(TOperator)
107
function Eval: extended; override;
110
TDivision = class(TOperator)
112
function Eval: extended; override;
115
TPower = class(TOperator)
117
function Eval: extended; override;
120
TFactorial = class(TOperator)
122
function Eval: extended; override;
125
TDegToRad = class(TOperator)
127
function Eval: extended; override;
130
TAbs = class(TFuncDef)
132
function DefName: string; override;
133
function Eval(x: extended): extended; override;
136
TInt = class(TFuncDef)
138
function DefName: string; override;
139
function Eval(x: extended): extended; override;
142
TRound = class(TFuncDef)
144
function DefName: string; override;
145
function Eval(x: extended): extended; override;
148
TSqr = class(TFuncDef)
150
function DefName: string; override;
151
function Eval(x: extended): extended; override;
154
TSqrt = class(TFuncDef)
156
function DefName: string; override;
157
function Eval(x: extended): extended; override;
160
TSin = class(TFuncDef)
162
function DefName: string; override;
163
function Eval(x: extended): extended; override;
166
TCos = class(TFuncDef)
168
function DefName: string; override;
169
function Eval(x: extended): extended; override;
172
TTan = class(TFuncDef)
174
function DefName: string; override;
175
function Eval(x: extended): extended; override;
178
TCsc = class(TFuncDef)
180
function DefName: string; override;
181
function Eval(x: extended): extended; override;
184
TSec = class(TFuncDef)
186
function DefName: string; override;
187
function Eval(x: extended): extended; override;
190
TCot = class(TFuncDef)
192
function DefName: string; override;
193
function Eval(x: extended): extended; override;
196
TArcSin = class(TFuncDef)
198
function DefName: string; override;
199
function Eval(x: extended): extended; override;
202
TArcCos = class(TFuncDef)
204
function DefName: string; override;
205
function Eval(x: extended): extended; override;
208
TArcTan = class(TFuncDef)
210
function DefName: string; override;
211
function Eval(x: extended): extended; override;
214
TArcCsc = class(TFuncDef)
216
function DefName: string; override;
217
function Eval(x: extended): extended; override;
220
TArcSec = class(TFuncDef)
222
function DefName: string; override;
223
function Eval(x: extended): extended; override;
226
TArcCot = class(TFuncDef)
228
function DefName: string; override;
229
function Eval(x: extended): extended; override;
232
TLn = class(TFuncDef)
234
function DefName: string; override;
235
function Eval(x: extended): extended; override;
238
TExp = class(TFuncDef)
240
function DefName: string; override;
241
function Eval(x: extended): extended; override;
244
TExp1 = class(TFuncDef)
246
function DefName: string; override;
247
function Eval(x: extended): extended; override;
250
TLog10 = class(TFuncDef)
252
function DefName: string; override;
253
function Eval(x: extended): extended; override;
256
TLog2 = class(TFuncDef)
258
function DefName: string; override;
259
function Eval(x: extended): extended; override;
262
TSinh = class(TFuncDef)
264
function DefName: string; override;
265
function Eval(x: extended): extended; override;
268
TCosh = class(TFuncDef)
270
function DefName: string; override;
271
function Eval(x: extended): extended; override;
274
TTanh = class(TFuncDef)
276
function DefName: string; override;
277
function Eval(x: extended): extended; override;
280
TCsch = class(TFuncDef)
282
function DefName: string; override;
283
function Eval(x: extended): extended; override;
286
TSech = class(TFuncDef)
288
function DefName: string; override;
289
function Eval(x: extended): extended; override;
292
TCoth = class(TFuncDef)
294
function DefName: string; override;
295
function Eval(x: extended): extended; override;
298
TArcSinh = class(TFuncDef)
300
function DefName: string; override;
301
function Eval(x: extended): extended; override;
304
TArcCosh = class(TFuncDef)
306
function DefName: string; override;
307
function Eval(x: extended): extended; override;
310
TArcTanh = class(TFuncDef)
312
function DefName: string; override;
313
function Eval(x: extended): extended; override;
316
TArcCsch = class(TFuncDef)
318
function DefName: string; override;
319
function Eval(x: extended): extended; override;
322
TArcSech = class(TFuncDef)
324
function DefName: string; override;
325
function Eval(x: extended): extended; override;
328
TArcCoth = class(TFuncDef)
330
function DefName: string; override;
331
function Eval(x: extended): extended; override;
334
function ScanText(const s: string): string;
335
function ParseAndEvaluate(const aText: string; var e: byte): extended;
336
function ParseEvaluateFxy(const aVarX, aVarY: extended;
337
const aText: string; var e: byte): extended;
349
constructor TConst.Create(c: extended);
354
function TConst.Eval: extended;
359
constructor TVar.Create(v: TVarDef);
364
function TVar.Eval: extended;
369
constructor TFunc.Create(v: TCalculus; f: TFuncDef);
375
destructor TFunc.Destroy;
380
function TFunc.Eval: extended;
382
Result := Def.Eval(Variable.Eval);
385
constructor TOperator.Create(c1, c2: TCalculus);
391
destructor TOperator.Destroy;
399
constructor TfxyParser.Create(x, y: extended);
402
FunctionList := TList.Create;
403
VariableList := TList.Create;
407
VarX := TVarDef.Create;
412
VarY := TVarDef.Create;
418
destructor TfxyParser.Destroy;
424
function TfxyParser.FunctionOf(i: integer): TFuncDef;
426
Result := TFuncDef(FunctionList.Items[i]);
429
function TfxyParser.VariableOf(i: integer): TVarDef;
431
Result := TVarDef(VariableList.Items[i]);
434
function TfxyParser.CheckBrackets(const s: string): Boolean;
436
i, j, c1, c2: integer;
445
if s[i] = '(' then Inc(c1);
446
if s[i] = ')' then Inc(c2);
452
function TfxyParser.CompileExpresion(const s: string; var Error: byte): TCalculus;
467
if not CheckBrackets(s) then
474
{----- -factor -----}
477
c1 := FactorCompile(copy(s, 2, length(s)-1), e1);
480
c2 := TConst.Create(0);
481
Result := TMinus.Create(c2, c1);
487
{----- exp+factor -----}
488
{----- exp-factor -----}
489
{----- exp!factor -----}
490
{----- exp°factor -----}
491
for i := length(s) downto 1 do
495
c1 := CompileExpresion(copy(s, 1, i -1), e1);
498
c2 := FactorCompile(copy(s, i +1, length(s) -i), e2);
501
Result := TSum.Create(c1, c2);
509
c1 := CompileExpresion(copy(s, 1, i -1), e1);
512
c2 := FactorCompile(copy(s, i +1, length(s) -i), e2);
515
Result := TMinus.Create(c1, c2);
523
c1 := CompileExpresion(copy(s, 1, i -1), e1);
526
c2 := FactorCompile(copy(s, 1, i -1), e2);
529
Result := TFactorial.Create(c1, c2);
537
c1 := CompileExpresion(copy(s, 1, i -1), e1);
540
c2 := FactorCompile(copy(s, 1, i -1), e2);
543
Result := TDegToRad.Create(c1, c2);
550
end; { case s[i] of... }
551
end; { for i := length(s) downto 1 do... }
552
Result := FactorCompile(s, Error);
555
function TfxyParser.FactorCompile(const s: string; var Error: byte): TCalculus;
569
if not CheckBrackets(s) then
576
{----- factor*simple -----}
577
{----- factor/simple -----}
578
for i := length(s) downto 1 do
582
c1 := FactorCompile(copy(s, 1, i -1), e1);
585
c2 := SimpleCompile(copy(s, i +1, length(s) -i), e2);
588
Result := TProduct.Create(c1, c2);
596
c1 := FactorCompile(copy(s, 1, i -1), e1);
599
c2 := SimpleCompile(copy(s, i +1, length(s) -i), e2);
602
Result := TDivision.Create(c1, c2);
609
end; { case s[i] of... }
610
end; { for i := length(s) downto 1 do... }
611
Result := SimpleCompile(s, Error);
614
function TfxyParser.SimpleCompile(const s: string; var Error: byte): TCalculus;
629
if not CheckBrackets(s) then
640
Result := TConst.Create(d);
646
if (s[1] = '(') and (s[length(s)] = ')') then
648
c1 := CompileExpresion(copy(s, 2, length(s)-2), e1);
657
{----- VarName -----}
658
for i := 0 to VariableList.Count -1 do
660
if s = VariableOf(i).VarName then
662
Result := TVar.Create(VariableOf(i));
668
{----- DefNameFunc(exp) -----}
669
for i := 0 to FunctionList.Count -1 do
671
if (Pos(FunctionOf(i).DefName + '(', s) = 1) and (s[length(s)] = ')')
674
c1 := CompileExpresion(copy(s, length(FunctionOf(i).DefName) +2,
675
length(s) - length(FunctionOf(i).DefName) -2), e1);
678
Result := TFunc.Create(c1, FunctionOf(i));
685
{----- simple^simple -----}
686
for i := 1 to length(s) do
690
c1 := SimpleCompile(copy(s, 1, i -1), e1);
693
c2 := SimpleCompile(copy(s, i +1, length(s) -i), e2);
696
Result := TPower.Create(c1, c2);
703
end; { case s[i] of... }
704
end; { for i := 1 to length(s) do... }
710
function TfxyParser.Compile(s: string; var Error: byte): TCalculus;
712
Result := CompileExpresion(s, Error);
715
procedure TfxyParser.AddVar(v: TVarDef);
720
procedure TfxyParser.ConstructLists;
758
Add(TArcSinh.Create);
759
Add(TArcCosh.Create);
760
Add(TArcTanh.Create);
761
Add(TArcCsch.Create);
762
Add(TArcSech.Create);
763
Add(TArcCoth.Create);
776
procedure TfxyParser.ClearLists;
781
for i := 0 to FunctionList.Count -1 do TFuncDef(FunctionList[i]).Free;
783
for i := 0 to VariableList.Count -1 do TVarDef(VariableList[i]).Free;
789
function TMinus.Eval: extended;
791
Result := e1.Eval - e2.Eval;
794
function TSum.Eval: extended;
796
Result := e1.Eval + e2.Eval;
799
function TProduct.Eval: extended;
801
Result := e1.Eval * e2.Eval;
804
function TDivision.Eval: extended;
806
if IsInfinite(e2.Eval) then Result := NaN else Result := e1.Eval/e2.Eval;
809
function TPower.Eval: extended;
810
{ For fractional exponents or exponents greater than MaxInt,
811
base must be greater than 0. }
813
{ e1.Eval base/mantissa e2.Eval exponent }
814
if e1.Eval = 0 then Result := 0 else Result := Power(e1.Eval, e2.Eval)
817
function TFactorial.Eval: extended;
823
if (j < 0) or (j > 1754) then Result := 0.0
827
for i := 2 to j do Result := i*Result;
831
function TDegToRad.Eval: extended;
833
Result := e1.Eval*PiOn180;
836
function TAbs.DefName: string;
841
function TAbs.Eval(x: extended): extended;
846
function TInt.DefName: string;
851
function TInt.Eval(x: extended): extended;
856
function TRound.DefName: string;
861
function TRound.Eval(x: extended): extended;
866
function TSqr.DefName: string;
871
function TSqr.Eval(x: extended): extended;
876
function TSqrt.DefName: string;
881
function TSqrt.Eval(x: extended): extended;
886
function TSin.DefName: string;
891
function TSin.Eval(x: extended): extended;
896
function TCos.DefName: string;
901
function TCos.Eval(x: extended): extended;
906
function TTan.DefName: string;
911
function TTan.Eval(x: extended): extended;
916
function TCsc.DefName: string;
921
function TCsc.Eval(x: extended): extended;
926
function TSec.DefName: string;
931
function TSec.Eval(x: extended): extended;
936
function TCot.DefName: string;
941
function TCot.Eval(x: extended): extended;
946
function TArcSin.DefName: string;
951
function TArcSin.Eval(x: extended): extended;
956
function TArcCos.DefName: string;
961
function TArcCos.Eval(x: extended): extended;
966
function TArcTan.DefName: string;
971
function TArcTan.Eval(x: extended): extended;
976
function TArcCsc.DefName: string;
981
function TArcCsc.Eval(x: extended): extended;
986
function TArcSec.DefName: string;
991
function TArcSec.Eval(x: extended): extended;
996
function TArcCot.DefName: string;
1001
function TArcCot.Eval(x: extended): extended;
1003
Result := ArcCot(x);
1004
if (Result > Pion2) or (Result < -Pion2)
1008
function TLn.DefName: string;
1013
function TLn.Eval(x: extended): extended;
1016
if isNaN(Result) then
1018
case Sign(Result) of
1019
-1:Result := NegInfinity;
1021
1:Result := Infinity;
1026
function TExp.DefName: string;
1031
function TExp.Eval(x: extended): extended;
1036
function TExp1.DefName: string;
1041
function TExp1.Eval(x: extended): extended;
1046
function TLog10.DefName: string;
1051
function TLog10.Eval(x: extended): extended;
1054
if isNaN(Result) then
1056
case Sign(Result) of
1057
-1:Result := NegInfinity;
1059
1:Result := Infinity;
1064
function TLog2.DefName: string;
1069
function TLog2.Eval(x: extended): extended;
1072
if isNaN(Result) then
1074
case Sign(Result) of
1075
-1:Result := NegInfinity;
1077
1:Result := Infinity;
1082
function TSinh.DefName: string;
1087
function TSinh.Eval(x: extended): extended;
1092
function TCosh.DefName: string;
1097
function TCosh.Eval(x: extended): extended;
1102
function TTanh.DefName: string;
1107
function TTanh.Eval(x: extended): extended;
1112
function TCsch.DefName: string;
1117
function TCsch.Eval(x: extended): extended;
1122
function TSech.DefName: string;
1127
function TSech.Eval(x: extended): extended;
1132
function TCoth.DefName: string;
1137
function TCoth.Eval(x: extended): extended;
1142
function TArcSinh.DefName: string;
1144
Result := 'arcsinh';
1147
function TArcSinh.Eval(x: extended): extended;
1149
Result := ArcSinh(x);
1152
function TArcCosh.DefName: string;
1154
Result := 'arccosh';
1157
function TArcCosh.Eval(x: extended): extended;
1159
Result := ArcCosh(x);
1162
function TArcTanh.DefName: string;
1164
Result := 'arctanh';
1167
function TArcTanh.Eval(x: extended): extended;
1169
Result := ArcTanh(x)
1172
function TArcCsch.DefName: string;
1174
Result := 'arccsch';
1177
function TArcCsch.Eval(x: extended): extended;
1179
if x = 0 then Result := Infinity else Result := ArcCsch(x);
1180
{ it would seem that Delphi 7 personal calculates ArcCsch incorrectly }
1183
function TArcSech.DefName: string;
1185
Result := 'arcsech';
1188
function TArcSech.Eval(x: extended): extended;
1190
if x <= 0 then Result := Infinity else Result := ArcSech(x);
1193
function TArcCoth.DefName: string;
1195
Result := 'arccoth';
1198
function TArcCoth.Eval(x: extended): extended;
1200
if (x >= -1) and (x < 0) then Result := NegInfinity else
1201
if (x > 0) and (x <= 1) then Result := Infinity else
1202
if x = 0 then Result := NaN else Result := ArcCoth(x);
1206
function ScanText(const s: string): string;
1207
function DropSpaces_Commas(const s: string): string;
1213
for i := 1 to Length(s) do
1214
if (s[i] <> ' ') and (s[i] <> ',') then Result := Result + s[i];
1215
end; { DropSpaces_Commas }
1220
cc, ccc, isStr: string;
1228
t := DropSpaces_Commas(s);
1232
while i < Length(t) do
1235
c1 := UpCase(t[i +1]);
1236
if i < Length(t) - 1 then c2 := UpCase(t[i +2]) else c2 := #0;
1241
isExp := ccc = 'XP(';
1245
if (i > 3) and ((cc = '0(') or (cc = '2(')) then
1248
then isStr := UpperCase(Copy(t, i -4, 3)) { Log10 }
1249
else isStr := UpperCase(Copy(t, i -3, 3)); { Log2 }
1250
isLog := isStr = 'LOG';
1253
isPwr := CharInSet(c0, ['+', '-', '0'..'9']) and (UpCase(c1) = 'E') and
1254
CharInSet(c2, ['+', '-', '0'..'9']);
1255
nostar := isExp or isLog or isPwr;
1258
CharInSet(c0, ['X', 'Y', 'I', '0'..'9', ')']) and
1259
CharInSet(c1, ['A'..'C', 'E', 'L', 'P', 'S', 'T', 'X', 'Y', '(']) then
1261
Insert('*', Result, i + j);
1268
function ParseAndEvaluate(const aText: string; var e: byte): extended;
1270
aParser: TfxyParser;
1273
aParser := TfxyParser.Create(0, 0);
1278
ViewForm.StatusBar.Panels[4].Text := '';
1279
Calculus := Compile(AnsiLowerCase(aText), ErrorByte);
1281
if ErrorByte > 0 then
1283
with ViewForm.StatusBar.Panels[4] do
1285
1:Text := 'Check Brackets for "'+ aText+'"';
1286
2:Text := 'Unable to Parse "'+aText+'"';
1290
else Result := Calculus.Eval;
1297
function ParseEvaluateFxy(const aVarX, aVarY: extended;
1298
const aText: string; var e: byte): extended;
1300
aParser: TfxyParser;
1303
aParser := TfxyParser.Create(0, 0);
1308
ViewForm.StatusBar.Panels[4].Text := '';
1309
Calculus := Compile(AnsiLowerCase(aText), ErrorByte);
1310
VarX.Value := aVarX;
1311
VarY.Value := aVarY;
1313
if ErrorByte > 0 then
1315
with ViewForm.StatusBar.Panels[4] do
1317
1:Text := 'Check Brackets for "'+ aText+'"';
1318
2:Text := 'Unable to Parse "'+aText+'"';
1322
else Result := Calculus.Eval;
1330
{ Avoids arithmetic exceptions in the above code }
1331
SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,
1332
exOverflow, exUnderflow, exPrecision]);