mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-03 11:18:21 +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 ()
|
||||
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()
|
||||
}
|
||||
{type
|
||||
type
|
||||
TOperandAndOperator = record
|
||||
Operand: TValue;
|
||||
Operand: TOperandValue;
|
||||
theOperator: PChar;
|
||||
OperatorLvl: integer;
|
||||
end;
|
||||
TExprStack = array[0..4] of TOperandAndOperator;
|
||||
TExprStack = array[0..3] of TOperandAndOperator;
|
||||
|
||||
var
|
||||
Operand: TOperandValue;
|
||||
ExprStack: TExprStack;
|
||||
StackPtr: integer;}
|
||||
var
|
||||
StackPtr: integer; // -1 = empty
|
||||
ExprEnd: Pointer;
|
||||
p, AtomStart: PChar;
|
||||
|
||||
procedure FreeStack;
|
||||
begin
|
||||
while StackPtr>=0 do begin
|
||||
FreeOperandValue(ExprStack[StackPtr].Operand);
|
||||
dec(StackPtr);
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetAtom: string;
|
||||
begin
|
||||
Setlength(Result,p-AtomStart);
|
||||
@ -1035,6 +1043,11 @@ var
|
||||
Error(NewErrorPos,'identifier missing');
|
||||
end;
|
||||
|
||||
procedure OperatorMissing(NewErrorPos: PChar);
|
||||
begin
|
||||
Error(NewErrorPos,'operator missing');
|
||||
end;
|
||||
|
||||
procedure CharMissing(NewErrorPos: PChar; c: char);
|
||||
begin
|
||||
Error(NewErrorPos,c+' missing');
|
||||
@ -1100,7 +1113,7 @@ var
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function ReadOperand(out Operand: TOperandValue): boolean;
|
||||
function ReadOperand: boolean;
|
||||
{ Examples:
|
||||
Variable
|
||||
not Variable
|
||||
@ -1111,12 +1124,13 @@ var
|
||||
i: LongInt;
|
||||
begin
|
||||
Result:=false;
|
||||
if AtomStart>=ExprEnd then exit;
|
||||
DebugLn(['ReadOperand ',GetAtom]);
|
||||
case UpChars[AtomStart^] of
|
||||
'N':
|
||||
if CompareIdentifiers(AtomStart,'NOT')=0 then begin
|
||||
// not
|
||||
if not ReadOperand(Operand) then exit;
|
||||
if not ReadOperand then exit;
|
||||
if (Operand.Len=1) and (Operand.Value^='1') then begin
|
||||
SetOperandValueConst(Operand,'-1');
|
||||
end else begin
|
||||
@ -1156,8 +1170,97 @@ var
|
||||
IdentifierMissing(AtomStart);
|
||||
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
|
||||
Operand: TOperandValue;
|
||||
OperatorLvl: Integer;
|
||||
begin
|
||||
p:=Expression;
|
||||
Result:='0';
|
||||
@ -1172,14 +1275,70 @@ begin
|
||||
ExpressionMissing(AtomStart);
|
||||
exit;
|
||||
end;
|
||||
// read operand
|
||||
StackPtr:=-1;
|
||||
Operand:=CleanOperandValue;
|
||||
ReadOperand(Operand);
|
||||
ReadNextAtom;
|
||||
// set result
|
||||
SetLength(Result,Operand.Len);
|
||||
if Result<>'' then
|
||||
System.Move(Operand.Value^,Result[1],length(Result));
|
||||
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
|
||||
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);
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user