mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-30 13:29:25 +02:00
codetools: expreval: operators
git-svn-id: trunk@22797 -
This commit is contained in:
parent
c5007165e5
commit
2f9071355c
@ -121,31 +121,13 @@ type
|
||||
implementation
|
||||
|
||||
type
|
||||
TOperator = (
|
||||
opNone,
|
||||
opNot,
|
||||
opDefined,
|
||||
opUndefined,
|
||||
opDeclared,
|
||||
opLowerThan,
|
||||
opLowerOrEqual,
|
||||
opEqual,
|
||||
opNotEqual,
|
||||
opGreaterOrEqual,
|
||||
opGreaterThan,
|
||||
opAnd,
|
||||
opOr,
|
||||
opXor,
|
||||
opShl
|
||||
);
|
||||
TOperandValue = record
|
||||
Value: PChar;
|
||||
Len: PtrInt;
|
||||
Data: array[0..3] of char;
|
||||
Free: boolean;
|
||||
end;
|
||||
const
|
||||
CleanOperandValue: TOperandValue = (Value:nil; Len:0; Data:#0#0#0#0; Free:false);
|
||||
POperandValue = ^TOperandValue;
|
||||
|
||||
var
|
||||
IsWordChar, IsIdentifierChar, IsNumberBeginChar, IsNumberChar:
|
||||
@ -171,6 +153,95 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ClearOperandValue(var V: TOperandValue); inline;
|
||||
begin
|
||||
V.Free:=false;
|
||||
V.Value:=nil;
|
||||
V.Len:=0;
|
||||
end;
|
||||
|
||||
function OperandIsTrue(const V: TOperandValue): boolean; inline;
|
||||
begin
|
||||
Result:=not ((V.Len=1) and (V.Value^='0'));
|
||||
end;
|
||||
|
||||
function OperandToInt64(const V: TOperandValue): int64;
|
||||
var
|
||||
p: PChar;
|
||||
l: PtrInt;
|
||||
Negated: Boolean;
|
||||
c: Char;
|
||||
begin
|
||||
Result:=0;
|
||||
p:=V.Value;
|
||||
l:=V.Len;
|
||||
if l=0 then exit;
|
||||
if p^='-' then begin
|
||||
Negated:=true;
|
||||
inc(p);
|
||||
dec(l);
|
||||
end else
|
||||
Negated:=false;
|
||||
if p^='$' then begin
|
||||
// hex number
|
||||
if l<15 then begin
|
||||
while l>0 do begin
|
||||
c:=p^;
|
||||
case c of
|
||||
'0'..'9': Result:=Result*16+ord(p^)-ord('0');
|
||||
'a'..'f': Result:=Result*16+ord(p^)-ord('a')+10;
|
||||
'A'..'Z': Result:=Result*16+ord(p^)-ord('A')+10;
|
||||
else
|
||||
break;
|
||||
end;
|
||||
inc(p);
|
||||
dec(l);
|
||||
end;
|
||||
end else begin
|
||||
try
|
||||
while l>0 do begin
|
||||
c:=p^;
|
||||
case c of
|
||||
'0'..'9': Result:=Result*16+ord(p^)-ord('0');
|
||||
'a'..'f': Result:=Result*16+ord(p^)-ord('a')+10;
|
||||
'A'..'Z': Result:=Result*16+ord(p^)-ord('A')+10;
|
||||
else
|
||||
break;
|
||||
end;
|
||||
inc(p);
|
||||
dec(l);
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
end else begin
|
||||
// decimal number
|
||||
if l<15 then begin
|
||||
while l>0 do begin
|
||||
if c in ['0'..'9'] then
|
||||
Result:=Result*10+ord(p^)-ord('0')
|
||||
else
|
||||
break;
|
||||
inc(p);
|
||||
dec(l);
|
||||
end;
|
||||
end else begin
|
||||
try
|
||||
while l>0 do begin
|
||||
if c in ['0'..'9'] then
|
||||
Result:=Result*10+ord(p^)-ord('0')
|
||||
else
|
||||
break;
|
||||
inc(p);
|
||||
dec(l);
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if Negated then Result:=-Result;
|
||||
end;
|
||||
|
||||
procedure SetOperandValueChar(var V: TOperandValue; const c: Char);
|
||||
begin
|
||||
if V.Free then FreeOperandValue(V);
|
||||
@ -186,6 +257,79 @@ begin
|
||||
V.Value:=p;
|
||||
end;
|
||||
|
||||
procedure SetOperandValueInt64(var V: TOperandValue; i : int64);
|
||||
const
|
||||
HexChrs: array[0..15] of char = '0123456789ABCDEF';
|
||||
var
|
||||
j: Integer;
|
||||
k: Integer;
|
||||
i2: Int64;
|
||||
begin
|
||||
if (i>=-999) and (i<=9999) then begin
|
||||
// small number => save in data
|
||||
if V.Free then FreeOperandValue(V);
|
||||
V.Value:=@V.Data[0];
|
||||
V.Len:=0;
|
||||
if i<0 then begin
|
||||
// sign
|
||||
V.Data[0]:='-';
|
||||
inc(V.Len);
|
||||
i:=-i;
|
||||
end;
|
||||
if i<10 then
|
||||
j:=1
|
||||
else if i<100 then
|
||||
j:=2
|
||||
else if i<1000 then
|
||||
j:=3
|
||||
else
|
||||
j:=4;
|
||||
inc(V.Len,j);
|
||||
k:=V.Len-1;
|
||||
repeat
|
||||
V.Data[k]:=HexChrs[i mod 10];
|
||||
dec(j);
|
||||
if j=0 then break;
|
||||
i:=i div 10;
|
||||
dec(k);
|
||||
until false;
|
||||
end else begin
|
||||
// big number => save as hex number
|
||||
// calculate needed mem
|
||||
i2:=i;
|
||||
j:=1; // $
|
||||
if i2<0 then begin
|
||||
i2:=-i2;
|
||||
inc(j);
|
||||
end;
|
||||
while i2>0 do begin
|
||||
i2:=i2 shr 4;
|
||||
inc(j);
|
||||
end;
|
||||
V.Len:=j;
|
||||
// allocate mem
|
||||
if V.Free then begin
|
||||
ReAllocMem(V.Value,j);
|
||||
end else begin
|
||||
V.Free:=true;
|
||||
Getmem(V.Value,j);
|
||||
end;
|
||||
// write number
|
||||
if i<0 then i:=-i;
|
||||
while i>0 do begin
|
||||
i:=i shr 4;
|
||||
dec(j);
|
||||
V.Value[j]:=HexChrs[i and $f];
|
||||
end;
|
||||
// write $
|
||||
dec(j);
|
||||
V.Value[j]:='$';
|
||||
// write minus sign
|
||||
if j=0 then
|
||||
V.Value[j]:='-';
|
||||
end;
|
||||
end;
|
||||
|
||||
function CompareOperand(const Operand: TOperandValue; Value: PChar): integer;
|
||||
var
|
||||
p: PChar;
|
||||
@ -236,6 +380,20 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function OperandsAreEqual(const Op1, Op2: TOperandValue): boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result:=false;
|
||||
if Op1.Len<>Op2.Len then exit;
|
||||
i:=Op1.Len-1;
|
||||
while i>=0 do begin
|
||||
if Op1.Value[i]<>Op2.Value[i] then exit;
|
||||
dec(i);
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function GetIdentifierLen(Identifier: PChar): integer;
|
||||
var
|
||||
p: PChar;
|
||||
@ -948,14 +1106,15 @@ end;
|
||||
|
||||
function TExpressionEvaluator.EvalPChar(Expression: PChar; ExprLen: PtrInt
|
||||
): string;
|
||||
{ 1 = true
|
||||
0 = syntax error
|
||||
-1 = false
|
||||
{ 0 = false
|
||||
else true
|
||||
|
||||
brackets ()
|
||||
constants: false, true
|
||||
unary operators: not, defined, undefined
|
||||
binary operators: + - * / < <= = <> => > div mod and or xor shl shr
|
||||
functions: defined(), undefined(), declared()
|
||||
functions: defined(), undefined(), declared(), sizeof()=1, option(),
|
||||
high(), low()
|
||||
}
|
||||
type
|
||||
TOperandAndOperator = record
|
||||
@ -988,6 +1147,9 @@ var
|
||||
end;
|
||||
|
||||
procedure ReadNextAtom;
|
||||
var
|
||||
Float: Boolean;
|
||||
Exponent: Boolean;
|
||||
begin
|
||||
// skip space
|
||||
while p^ in [' ',#9,#10,#13] do inc(p);
|
||||
@ -1003,18 +1165,63 @@ var
|
||||
while IsIdentChar[p^] do inc(p);
|
||||
if p>ExprEnd then p:=ExprEnd;
|
||||
end;
|
||||
'0'..'9':
|
||||
begin
|
||||
inc(p);
|
||||
Float:=false;
|
||||
Exponent:=false;
|
||||
repeat
|
||||
case p^ of
|
||||
'0'..'9': inc(p);
|
||||
'.':
|
||||
if Float then
|
||||
break
|
||||
else begin
|
||||
Float:=true;
|
||||
inc(p);
|
||||
end;
|
||||
'e','E':
|
||||
if Exponent or (not Float) then
|
||||
break
|
||||
else begin
|
||||
Exponent:=true;
|
||||
inc(p);
|
||||
end;
|
||||
else
|
||||
break;
|
||||
end;
|
||||
until p>=ExprEnd;
|
||||
end;
|
||||
'$':
|
||||
begin
|
||||
inc(p);
|
||||
while IsHexNumberChar[p^] do inc(p);
|
||||
end;
|
||||
'>':
|
||||
begin
|
||||
inc(p);
|
||||
case p^ of
|
||||
'=': inc(p); // >=
|
||||
'=','>': inc(p); // >= >>
|
||||
end;
|
||||
end;
|
||||
'<':
|
||||
begin
|
||||
inc(p);
|
||||
case p^ of
|
||||
'>','=': inc(p); // <> <=
|
||||
'<','>','=': inc(p); // <> <= <<
|
||||
end;
|
||||
end;
|
||||
'''':
|
||||
begin
|
||||
inc(p);
|
||||
while (p<=ExprEnd) do begin
|
||||
if p^='''' then begin
|
||||
inc(p);
|
||||
if p^<>'''' then break;
|
||||
inc(p);
|
||||
end else begin
|
||||
inc(p);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
@ -1033,6 +1240,11 @@ var
|
||||
DebugLn(['Error ',ErrorMsg,' at ',ErrorPosition]);
|
||||
end;
|
||||
|
||||
procedure Error(NewErrorPos: PChar; E: Exception);
|
||||
begin
|
||||
Error(NewErrorPos,E.Message);
|
||||
end;
|
||||
|
||||
procedure ExpressionMissing(NewErrorPos: PChar);
|
||||
begin
|
||||
Error(NewErrorPos,'expression missing');
|
||||
@ -1130,11 +1342,12 @@ var
|
||||
'N':
|
||||
if CompareIdentifiers(AtomStart,'NOT')=0 then begin
|
||||
// not
|
||||
if not ReadOperand then exit;
|
||||
if (Operand.Len=1) and (Operand.Value^='1') then begin
|
||||
SetOperandValueConst(Operand,'-1');
|
||||
end else begin
|
||||
ReadNextAtom;
|
||||
if not ReadOperand() then exit;
|
||||
if (Operand.Len=1) and (Operand.Value^='0') then begin
|
||||
SetOperandValueChar(Operand,'1');
|
||||
end else begin
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
exit(true);
|
||||
end;
|
||||
@ -1148,10 +1361,10 @@ var
|
||||
if CompareIdentifiers(AtomStart,'UNDEFINED')=0 then begin
|
||||
// "undefined V" or "undefined(V)"
|
||||
if not ParseDefinedParams(Operand) then exit;
|
||||
if (Operand.Len=1) and (Operand.Value^='1') then begin
|
||||
SetOperandValueConst(Operand,'-1');
|
||||
end else begin
|
||||
if (Operand.Len=1) and (Operand.Value^='0') then begin
|
||||
SetOperandValueChar(Operand,'1');
|
||||
end else begin
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
exit(true);
|
||||
end;
|
||||
@ -1173,90 +1386,177 @@ var
|
||||
function ExecuteStack(LowerOrEqualOperatorLvl: integer): boolean;
|
||||
var
|
||||
Op: PChar;
|
||||
Number1: Int64;
|
||||
Number2: Int64;
|
||||
NumberResult: Int64;
|
||||
StackOperand: POperandValue;
|
||||
begin
|
||||
Result:=false;
|
||||
Result:=true;
|
||||
while (StackPtr>=0)
|
||||
and (ExprStack[StackPtr].OperatorLvl<=LowerOrEqualOperatorLvl) do begin
|
||||
// compute stack item
|
||||
Op:=ExprStack[StackPtr].theOperator;
|
||||
case UpChars[Op^] of
|
||||
'*':
|
||||
begin
|
||||
|
||||
end;
|
||||
'/':
|
||||
begin
|
||||
|
||||
end;
|
||||
'+':
|
||||
begin
|
||||
|
||||
end;
|
||||
'-':
|
||||
begin
|
||||
|
||||
end;
|
||||
'=':
|
||||
begin
|
||||
|
||||
end;
|
||||
'<':
|
||||
case Op[1] of
|
||||
'>':
|
||||
try
|
||||
// compute stack item
|
||||
Op:=ExprStack[StackPtr].theOperator;
|
||||
StackOperand:=@ExprStack[StackPtr].Operand;
|
||||
case UpChars[Op^] of
|
||||
'*': // multiply
|
||||
begin
|
||||
// <>
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1*Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
'+': // Add
|
||||
begin
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1+Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
'-': // subtract
|
||||
begin
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1-Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
'=':
|
||||
if OperandsAreEqual(StackOperand^,Operand) then begin
|
||||
SetOperandValueChar(Operand,'1');
|
||||
end else begin
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
'<':
|
||||
case Op[1] of
|
||||
'>': // <>
|
||||
if OperandsAreEqual(StackOperand^,Operand) then begin
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end else begin
|
||||
SetOperandValueChar(Operand,'1');
|
||||
end;
|
||||
'=':
|
||||
begin
|
||||
// <=
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
if Number1<=Number2 then
|
||||
SetOperandValueChar(Operand,'1')
|
||||
else
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
'<':
|
||||
begin
|
||||
// <<
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1 shl Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
else
|
||||
// <
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
if Number1<Number2 then
|
||||
SetOperandValueChar(Operand,'1')
|
||||
else
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
'>':
|
||||
case Op[1] of
|
||||
'=':
|
||||
begin
|
||||
// >=
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
if Number1>=Number2 then
|
||||
SetOperandValueChar(Operand,'1')
|
||||
else
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
'>':
|
||||
begin
|
||||
// >>
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1 shr Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
else
|
||||
// >
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
if Number1>Number2 then
|
||||
SetOperandValueChar(Operand,'1')
|
||||
else
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
'A': // AND
|
||||
begin
|
||||
//<=
|
||||
if OperandIsTrue(StackOperand^) and OperandIsTrue(Operand) then
|
||||
SetOperandValueChar(Operand,'1')
|
||||
else
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
else
|
||||
// <
|
||||
end;
|
||||
'>':
|
||||
if Op[1]='=' then begin
|
||||
// >=
|
||||
end else begin
|
||||
// >
|
||||
end;
|
||||
'A': // AND
|
||||
begin
|
||||
|
||||
end;
|
||||
'D': // DIV
|
||||
begin
|
||||
|
||||
end;
|
||||
'M': // MOD
|
||||
begin
|
||||
|
||||
end;
|
||||
'S':
|
||||
case UpChars[Op[1]] of
|
||||
'H': // SH
|
||||
case UpChars[Op[2]] of
|
||||
'L': // SHL
|
||||
begin
|
||||
|
||||
end;
|
||||
'R': // SHR
|
||||
begin
|
||||
|
||||
'D': // DIV
|
||||
begin
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1 div Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
'M': // MOD
|
||||
begin
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1 mod Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
'S':
|
||||
case UpChars[Op[1]] of
|
||||
'H': // SH
|
||||
case UpChars[Op[2]] of
|
||||
'L': // SHL
|
||||
begin
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1 shl Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
'R': // SHR
|
||||
begin
|
||||
Number1:=OperandToInt64(StackOperand^);
|
||||
Number2:=OperandToInt64(Operand);
|
||||
NumberResult:=Number1 shr Number2;
|
||||
SetOperandValueInt64(Operand,NumberResult);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
'O': // OR
|
||||
begin
|
||||
if OperandIsTrue(StackOperand^) or OperandIsTrue(Operand) then
|
||||
SetOperandValueChar(Operand,'1')
|
||||
else
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
'X': // XOR
|
||||
begin
|
||||
if OperandIsTrue(StackOperand^) xor OperandIsTrue(Operand) then
|
||||
SetOperandValueChar(Operand,'1')
|
||||
else
|
||||
SetOperandValueChar(Operand,'0');
|
||||
end;
|
||||
end;
|
||||
'O': // OR
|
||||
begin
|
||||
|
||||
end;
|
||||
'X': // XOR
|
||||
begin
|
||||
|
||||
except
|
||||
on E: Exception do begin
|
||||
Result:=false;
|
||||
Error(AtomStart,E);
|
||||
end;
|
||||
end;
|
||||
if not Result then exit;
|
||||
FreeOperandValue(ExprStack[StackPtr].Operand);
|
||||
dec(StackPtr);
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
var
|
||||
@ -1276,70 +1576,87 @@ begin
|
||||
exit;
|
||||
end;
|
||||
StackPtr:=-1;
|
||||
Operand:=CleanOperandValue;
|
||||
ClearOperandValue(Operand);
|
||||
FErrorPos:=-1;
|
||||
fErrorMsg:='';
|
||||
while AtomStart<ExprEnd do begin
|
||||
// read operand
|
||||
if not ReadOperand then
|
||||
break;
|
||||
// read operator
|
||||
ReadNextAtom;
|
||||
if AtomStart>=ExprEnd then break;
|
||||
// level 0: NOT () DEFINED UNDEFINED DECLARED: handled by ReadOperand
|
||||
// level 1: * / DIV MOD AND SHL SHR
|
||||
// level 2: + - OR XOR
|
||||
// level 3: = < > <> >= <=
|
||||
OperatorLvl:=0;
|
||||
case UpChars[AtomStart^] of
|
||||
'*','/': if AtomStart-p=1 then OperatorLvl:=1;
|
||||
'+','-': if AtomStart-p=1 then OperatorLvl:=2;
|
||||
'=': if AtomStart-p=1 then OperatorLvl:=3;
|
||||
'<': if (AtomStart-p=1)
|
||||
or (AtomStart[2] in ['=','>']) then OperatorLvl:=3;
|
||||
'>': if (AtomStart-p=1)
|
||||
or (AtomStart[2]='=') then OperatorLvl:=3;
|
||||
'A': if CompareIdentifiers(AtomStart,'AND')=0 then OperatorLvl:=1;
|
||||
'D': if CompareIdentifiers(AtomStart,'DIV')=0 then OperatorLvl:=1;
|
||||
'M': if CompareIdentifiers(AtomStart,'MOD')=0 then OperatorLvl:=1;
|
||||
'S':
|
||||
case UpChars[AtomStart[1]] of
|
||||
'H': // SH
|
||||
case UpChars[AtomStart[2]] of
|
||||
'L': if p-AtomStart=3 then OperatorLvl:=1; // SHL
|
||||
'R': if p-AtomStart=3 then OperatorLvl:=1; // SHR
|
||||
try
|
||||
while AtomStart<ExprEnd do begin
|
||||
// read operand
|
||||
if not ReadOperand then
|
||||
break;
|
||||
// read operator
|
||||
ReadNextAtom;
|
||||
if AtomStart>=ExprEnd then break;
|
||||
// level 0: NOT () DEFINED UNDEFINED DECLARED: handled by ReadOperand
|
||||
// level 1: * / DIV MOD AND SHL SHR << >>
|
||||
// level 2: + - OR XOR
|
||||
// level 3: = < > <> >= <=
|
||||
OperatorLvl:=0;
|
||||
case UpChars[AtomStart^] of
|
||||
'*','/': if AtomStart-p=1 then OperatorLvl:=1;
|
||||
'+','-': if AtomStart-p=1 then OperatorLvl:=2;
|
||||
'=': if AtomStart-p=1 then OperatorLvl:=3;
|
||||
'<': if (AtomStart-p=1)
|
||||
or (AtomStart[2] in ['=','>']) then
|
||||
OperatorLvl:=3
|
||||
else if AtomStart[2]='<' then
|
||||
OperatorLvl:=1;
|
||||
'>': if (AtomStart-p=1)
|
||||
or (AtomStart[2]='=') then
|
||||
OperatorLvl:=3
|
||||
else if AtomStart[2]='>' then
|
||||
OperatorLvl:=1;
|
||||
'A':
|
||||
if CompareIdentifiers(AtomStart,'AND')=0 then begin
|
||||
OperatorLvl:=1;
|
||||
if not OperandIsTrue(Operand) then break;
|
||||
end;
|
||||
'D': if CompareIdentifiers(AtomStart,'DIV')=0 then OperatorLvl:=1;
|
||||
'M': if CompareIdentifiers(AtomStart,'MOD')=0 then OperatorLvl:=1;
|
||||
'S':
|
||||
case UpChars[AtomStart[1]] of
|
||||
'H': // SH
|
||||
case UpChars[AtomStart[2]] of
|
||||
'L': if p-AtomStart=3 then OperatorLvl:=1; // SHL
|
||||
'R': if p-AtomStart=3 then OperatorLvl:=1; // SHR
|
||||
end;
|
||||
end;
|
||||
'O':
|
||||
case UpChars[AtomStart[1]] of
|
||||
'R':
|
||||
if p-AtomStart=2 then begin
|
||||
OperatorLvl:=2;
|
||||
if OperandIsTrue(Operand) then break;
|
||||
end;
|
||||
end;
|
||||
'X': if CompareIdentifiers(AtomStart,'XOR')=0 then OperatorLvl:=2;
|
||||
end;
|
||||
'O':
|
||||
case UpChars[AtomStart[1]] of
|
||||
'R': if p-AtomStart=2 then OperatorLvl:=2;
|
||||
if OperatorLvl=0 then begin
|
||||
OperatorMissing(AtomStart);
|
||||
break;
|
||||
end;
|
||||
'X': if CompareIdentifiers(AtomStart,'XOR')=0 then OperatorLvl:=2;
|
||||
if not ExecuteStack(OperatorLvl) then break;
|
||||
// push onto stack
|
||||
inc(StackPtr);
|
||||
ExprStack[StackPtr].Operand:=Operand;
|
||||
ExprStack[StackPtr].OperatorLvl:=OperatorLvl;
|
||||
ExprStack[StackPtr].theOperator:=AtomStart;
|
||||
ClearOperandValue(Operand);
|
||||
ReadNextAtom;
|
||||
end;
|
||||
if OperatorLvl=0 then begin
|
||||
OperatorMissing(AtomStart);
|
||||
break;
|
||||
if FErrorPos<0 then begin
|
||||
if ExecuteStack(4) then begin
|
||||
// set result
|
||||
SetLength(Result,Operand.Len);
|
||||
if Result<>'' then
|
||||
System.Move(Operand.Value^,Result[1],length(Result));
|
||||
end;
|
||||
end;
|
||||
if not ExecuteStack(OperatorLvl) then break;
|
||||
// push onto stack
|
||||
inc(StackPtr);
|
||||
ExprStack[StackPtr].Operand:=Operand;
|
||||
ExprStack[StackPtr].OperatorLvl:=OperatorLvl;
|
||||
ExprStack[StackPtr].theOperator:=AtomStart;
|
||||
Operand:=CleanOperandValue;
|
||||
ReadNextAtom;
|
||||
finally
|
||||
// clean up
|
||||
FreeStack;
|
||||
FreeOperandValue(Operand);
|
||||
end;
|
||||
if FErrorPos<0 then begin
|
||||
if ExecuteStack(4) then begin
|
||||
// set result
|
||||
SetLength(Result,Operand.Len);
|
||||
if Result<>'' then
|
||||
System.Move(Operand.Value^,Result[1],length(Result));
|
||||
end;
|
||||
end;
|
||||
// clean up
|
||||
FreeStack;
|
||||
FreeOperandValue(Operand);
|
||||
end;
|
||||
|
||||
function TExpressionEvaluator.AsString: string;
|
||||
|
Loading…
Reference in New Issue
Block a user