mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-07 08:58:15 +02:00
codetools: expreval: stack
git-svn-id: trunk@22779 -
This commit is contained in:
parent
5f2cf12f1f
commit
da872a80c7
@ -954,24 +954,32 @@ function TExpressionEvaluator.EvalPChar(Expression: PChar; ExprLen: PtrInt
|
|||||||
|
|
||||||
brackets ()
|
brackets ()
|
||||||
unary operators: not, defined, undefined
|
unary operators: not, defined, undefined
|
||||||
binary operators: < <= = <> => > and or xor shl shr
|
binary operators: + - * / < <= = <> => > div mod and or xor shl shr
|
||||||
functions: defined(), undefined(), declared()
|
functions: defined(), undefined(), declared()
|
||||||
}
|
}
|
||||||
{type
|
type
|
||||||
TOperandAndOperator = record
|
TOperandAndOperator = record
|
||||||
Operand: TValue;
|
Operand: TOperandValue;
|
||||||
theOperator: PChar;
|
theOperator: PChar;
|
||||||
OperatorLvl: integer;
|
OperatorLvl: integer;
|
||||||
end;
|
end;
|
||||||
TExprStack = array[0..4] of TOperandAndOperator;
|
TExprStack = array[0..3] of TOperandAndOperator;
|
||||||
|
|
||||||
var
|
var
|
||||||
|
Operand: TOperandValue;
|
||||||
ExprStack: TExprStack;
|
ExprStack: TExprStack;
|
||||||
StackPtr: integer;}
|
StackPtr: integer; // -1 = empty
|
||||||
var
|
|
||||||
ExprEnd: Pointer;
|
ExprEnd: Pointer;
|
||||||
p, AtomStart: PChar;
|
p, AtomStart: PChar;
|
||||||
|
|
||||||
|
procedure FreeStack;
|
||||||
|
begin
|
||||||
|
while StackPtr>=0 do begin
|
||||||
|
FreeOperandValue(ExprStack[StackPtr].Operand);
|
||||||
|
dec(StackPtr);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function GetAtom: string;
|
function GetAtom: string;
|
||||||
begin
|
begin
|
||||||
Setlength(Result,p-AtomStart);
|
Setlength(Result,p-AtomStart);
|
||||||
@ -1035,6 +1043,11 @@ var
|
|||||||
Error(NewErrorPos,'identifier missing');
|
Error(NewErrorPos,'identifier missing');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure OperatorMissing(NewErrorPos: PChar);
|
||||||
|
begin
|
||||||
|
Error(NewErrorPos,'operator missing');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure CharMissing(NewErrorPos: PChar; c: char);
|
procedure CharMissing(NewErrorPos: PChar; c: char);
|
||||||
begin
|
begin
|
||||||
Error(NewErrorPos,c+' missing');
|
Error(NewErrorPos,c+' missing');
|
||||||
@ -1100,7 +1113,7 @@ var
|
|||||||
Result:=true;
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ReadOperand(out Operand: TOperandValue): boolean;
|
function ReadOperand: boolean;
|
||||||
{ Examples:
|
{ Examples:
|
||||||
Variable
|
Variable
|
||||||
not Variable
|
not Variable
|
||||||
@ -1111,12 +1124,13 @@ var
|
|||||||
i: LongInt;
|
i: LongInt;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
|
if AtomStart>=ExprEnd then exit;
|
||||||
DebugLn(['ReadOperand ',GetAtom]);
|
DebugLn(['ReadOperand ',GetAtom]);
|
||||||
case UpChars[AtomStart^] of
|
case UpChars[AtomStart^] of
|
||||||
'N':
|
'N':
|
||||||
if CompareIdentifiers(AtomStart,'NOT')=0 then begin
|
if CompareIdentifiers(AtomStart,'NOT')=0 then begin
|
||||||
// not
|
// not
|
||||||
if not ReadOperand(Operand) then exit;
|
if not ReadOperand then exit;
|
||||||
if (Operand.Len=1) and (Operand.Value^='1') then begin
|
if (Operand.Len=1) and (Operand.Value^='1') then begin
|
||||||
SetOperandValueConst(Operand,'-1');
|
SetOperandValueConst(Operand,'-1');
|
||||||
end else begin
|
end else begin
|
||||||
@ -1156,8 +1170,97 @@ var
|
|||||||
IdentifierMissing(AtomStart);
|
IdentifierMissing(AtomStart);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function ExecuteStack(LowerOrEqualOperatorLvl: integer): boolean;
|
||||||
|
var
|
||||||
|
Op: PChar;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
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
|
||||||
|
'>':
|
||||||
|
begin
|
||||||
|
// <>
|
||||||
|
end;
|
||||||
|
'=':
|
||||||
|
begin
|
||||||
|
//<=
|
||||||
|
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
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
'O': // OR
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
'X': // XOR
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
dec(StackPtr);
|
||||||
|
end;
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
Operand: TOperandValue;
|
OperatorLvl: Integer;
|
||||||
begin
|
begin
|
||||||
p:=Expression;
|
p:=Expression;
|
||||||
Result:='0';
|
Result:='0';
|
||||||
@ -1172,14 +1275,70 @@ begin
|
|||||||
ExpressionMissing(AtomStart);
|
ExpressionMissing(AtomStart);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
// read operand
|
StackPtr:=-1;
|
||||||
Operand:=CleanOperandValue;
|
Operand:=CleanOperandValue;
|
||||||
ReadOperand(Operand);
|
FErrorPos:=-1;
|
||||||
ReadNextAtom;
|
fErrorMsg:='';
|
||||||
// set result
|
while AtomStart<ExprEnd do begin
|
||||||
SetLength(Result,Operand.Len);
|
// read operand
|
||||||
if Result<>'' then
|
if not ReadOperand then
|
||||||
System.Move(Operand.Value^,Result[1],length(Result));
|
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
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
'O':
|
||||||
|
case UpChars[AtomStart[1]] of
|
||||||
|
'R': if p-AtomStart=2 then OperatorLvl:=2;
|
||||||
|
end;
|
||||||
|
'X': if CompareIdentifiers(AtomStart,'XOR')=0 then OperatorLvl:=2;
|
||||||
|
end;
|
||||||
|
if OperatorLvl=0 then begin
|
||||||
|
OperatorMissing(AtomStart);
|
||||||
|
break;
|
||||||
|
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;
|
||||||
|
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);
|
FreeOperandValue(Operand);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user