mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2026-01-07 07:30:32 +01:00
1043 lines
24 KiB
ObjectPascal
1043 lines
24 KiB
ObjectPascal
unit dbf_prsdef;
|
|
|
|
interface
|
|
|
|
{$I Dbf_Common.inc}
|
|
|
|
uses
|
|
SysUtils,
|
|
Classes,
|
|
Dbf_Common,
|
|
Dbf_PrsSupp;
|
|
|
|
const
|
|
MaxArg = 6;
|
|
ArgAllocSize = 32;
|
|
|
|
type
|
|
TExpressionType = (etInteger, etString, etBoolean, etLargeInt, etFloat, etDateTime,
|
|
etLeftBracket, etRightBracket, etComma, etUnknown);
|
|
|
|
PPChar = ^PChar;
|
|
PBoolean = ^Boolean;
|
|
PInteger = ^Integer;
|
|
PDateTime = ^TDateTime;
|
|
EParserException = class(Exception);
|
|
PExpressionRec = ^TExpressionRec;
|
|
PDynamicType = ^TDynamicType;
|
|
|
|
TExprWord = class;
|
|
|
|
TExprFunc = procedure(Expr: PExpressionRec);
|
|
|
|
//-----
|
|
|
|
TDynamicType = class(TObject)
|
|
private
|
|
FMemory: PPChar;
|
|
FMemoryPos: PPChar;
|
|
FSize: PInteger;
|
|
public
|
|
constructor Create(DestMem, DestPos: PPChar; Size: PInteger);
|
|
|
|
procedure AssureSpace(ASize: Integer);
|
|
procedure Resize(NewSize: Integer; Exact: Boolean);
|
|
procedure Rewind;
|
|
procedure Append(Source: PChar; Length: Integer);
|
|
procedure AppendInteger(Source: Integer);
|
|
|
|
property Memory: PPChar read FMemory;
|
|
property MemoryPos: PPChar read FMemoryPos;
|
|
property Size: PInteger read FSize;
|
|
end;
|
|
|
|
TExpressionRec = record
|
|
//used both as linked tree and linked list for maximum evaluation efficiency
|
|
Oper: TExprFunc;
|
|
Next: PExpressionRec;
|
|
Res: TDynamicType;
|
|
ExprWord: TExprWord;
|
|
AuxData: pointer;
|
|
ResetDest: Boolean;
|
|
Args: array[0..MaxArg-1] of PChar;
|
|
ArgsPos: array[0..MaxArg-1] of PChar;
|
|
ArgsSize: array[0..MaxArg-1] of Integer;
|
|
ArgsType: array[0..MaxArg-1] of TExpressionType;
|
|
ArgList: array[0..MaxArg-1] of PExpressionRec;
|
|
end;
|
|
|
|
TExprCollection = class(TNoOwnerCollection)
|
|
public
|
|
procedure Check;
|
|
procedure EraseExtraBrackets;
|
|
end;
|
|
|
|
TExprWordRec = record
|
|
Name: PChar;
|
|
ShortName: PChar;
|
|
IsOperator: Boolean;
|
|
IsVariable: Boolean;
|
|
IsFunction: Boolean;
|
|
NeedsCopy: Boolean;
|
|
FixedLen: Boolean;
|
|
CanVary: Boolean;
|
|
ResultType: TExpressionType;
|
|
MinArg: Integer;
|
|
MaxArg: Integer;
|
|
TypeSpec: PChar;
|
|
Description: PChar;
|
|
ExprFunc: TExprFunc;
|
|
end;
|
|
|
|
TExprWord = class(TObject)
|
|
private
|
|
FName: string;
|
|
FExprFunc: TExprFunc;
|
|
protected
|
|
FRefCount: Cardinal;
|
|
|
|
function GetIsOperator: Boolean; virtual;
|
|
function GetIsVariable: Boolean;
|
|
function GetNeedsCopy: Boolean;
|
|
function GetFixedLen: Integer; virtual;
|
|
function GetCanVary: Boolean; virtual;
|
|
function GetResultType: TExpressionType; virtual;
|
|
function GetMinFunctionArg: Integer; virtual;
|
|
function GetMaxFunctionArg: Integer; virtual;
|
|
function GetDescription: string; virtual;
|
|
function GetTypeSpec: string; virtual;
|
|
function GetShortName: string; virtual;
|
|
public
|
|
constructor Create(AName: string; AExprFunc: TExprFunc);
|
|
|
|
function LenAsPointer: PInteger; virtual;
|
|
function AsPointer: PChar; virtual;
|
|
function IsFunction: Boolean; virtual;
|
|
|
|
property ExprFunc: TExprFunc read FExprFunc;
|
|
property IsOperator: Boolean read GetIsOperator;
|
|
property CanVary: Boolean read GetCanVary;
|
|
property IsVariable: Boolean read GetIsVariable;
|
|
property NeedsCopy: Boolean read GetNeedsCopy;
|
|
property FixedLen: Integer read GetFixedLen;
|
|
property ResultType: TExpressionType read GetResultType;
|
|
property MinFunctionArg: Integer read GetMinFunctionArg;
|
|
property MaxFunctionArg: Integer read GetMaxFunctionArg;
|
|
property Name: string read FName;
|
|
property ShortName: string read GetShortName;
|
|
property Description: string read GetDescription;
|
|
property TypeSpec: string read GetTypeSpec;
|
|
end;
|
|
|
|
TExpressShortList = class(TSortedCollection)
|
|
public
|
|
function KeyOf(Item: Pointer): Pointer; override;
|
|
function Compare(Key1, Key2: Pointer): Integer; override;
|
|
procedure FreeItem(Item: Pointer); override;
|
|
end;
|
|
|
|
TExpressList = class(TSortedCollection)
|
|
private
|
|
FShortList: TExpressShortList;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Add(Item: Pointer); override;
|
|
function KeyOf(Item: Pointer): Pointer; override;
|
|
function Compare(Key1, Key2: Pointer): Integer; override;
|
|
function Search(Key: Pointer; var Index: Integer): Boolean; override;
|
|
procedure FreeItem(Item: Pointer); override;
|
|
end;
|
|
|
|
TConstant = class(TExprWord)
|
|
private
|
|
FResultType: TExpressionType;
|
|
protected
|
|
function GetResultType: TExpressionType; override;
|
|
public
|
|
constructor Create(AName: string; AVarType: TExpressionType; AExprFunc: TExprFunc);
|
|
end;
|
|
|
|
TFloatConstant = class(TConstant)
|
|
private
|
|
FValue: Double;
|
|
public
|
|
// not overloaded to support older Delphi versions
|
|
constructor Create(AName: string; AValue: string);
|
|
constructor CreateAsDouble(AName: string; AValue: Double);
|
|
|
|
function AsPointer: PChar; override;
|
|
|
|
property Value: Double read FValue write FValue;
|
|
end;
|
|
|
|
TUserConstant = class(TFloatConstant)
|
|
private
|
|
FDescription: string;
|
|
protected
|
|
function GetDescription: string; override;
|
|
public
|
|
constructor CreateAsDouble(AName, Descr: string; AValue: Double);
|
|
end;
|
|
|
|
TStringConstant = class(TConstant)
|
|
private
|
|
FValue: string;
|
|
public
|
|
constructor Create(AValue: string);
|
|
|
|
function AsPointer: PChar; override;
|
|
end;
|
|
|
|
TIntegerConstant = class(TConstant)
|
|
private
|
|
FValue: Integer;
|
|
public
|
|
constructor Create(AValue: Integer);
|
|
|
|
function AsPointer: PChar; override;
|
|
end;
|
|
|
|
TBooleanConstant = class(TConstant)
|
|
private
|
|
FValue: Boolean;
|
|
public
|
|
// not overloaded to support older Delphi versions
|
|
constructor Create(AName: string; AValue: Boolean);
|
|
|
|
function AsPointer: PChar; override;
|
|
|
|
property Value: Boolean read FValue write FValue;
|
|
end;
|
|
|
|
TVariable = class(TExprWord)
|
|
private
|
|
FResultType: TExpressionType;
|
|
protected
|
|
function GetCanVary: Boolean; override;
|
|
function GetResultType: TExpressionType; override;
|
|
public
|
|
constructor Create(AName: string; AVarType: TExpressionType; AExprFunc: TExprFunc);
|
|
end;
|
|
|
|
TFloatVariable = class(TVariable)
|
|
private
|
|
FValue: PDouble;
|
|
public
|
|
constructor Create(AName: string; AValue: PDouble);
|
|
|
|
function AsPointer: PChar; override;
|
|
end;
|
|
|
|
TStringVariable = class(TVariable)
|
|
private
|
|
FValue: PPChar;
|
|
FFixedLen: Integer;
|
|
protected
|
|
function GetFixedLen: Integer; override;
|
|
public
|
|
constructor Create(AName: string; AValue: PPChar; AFixedLen: Integer);
|
|
|
|
function LenAsPointer: PInteger; override;
|
|
function AsPointer: PChar; override;
|
|
|
|
property FixedLen: Integer read FFixedLen;
|
|
end;
|
|
|
|
TDateTimeVariable = class(TVariable)
|
|
private
|
|
FValue: PDateTimeRec;
|
|
public
|
|
constructor Create(AName: string; AValue: PDateTimeRec);
|
|
|
|
function AsPointer: PChar; override;
|
|
end;
|
|
|
|
TIntegerVariable = class(TVariable)
|
|
private
|
|
FValue: PInteger;
|
|
public
|
|
constructor Create(AName: string; AValue: PInteger);
|
|
|
|
function AsPointer: PChar; override;
|
|
end;
|
|
|
|
{$ifdef SUPPORT_INT64}
|
|
|
|
TLargeIntVariable = class(TVariable)
|
|
private
|
|
FValue: PLargeInt;
|
|
public
|
|
constructor Create(AName: string; AValue: PLargeInt);
|
|
|
|
function AsPointer: PChar; override;
|
|
end;
|
|
|
|
{$endif}
|
|
|
|
TBooleanVariable = class(TVariable)
|
|
private
|
|
FValue: PBoolean;
|
|
public
|
|
constructor Create(AName: string; AValue: PBoolean);
|
|
|
|
function AsPointer: PChar; override;
|
|
end;
|
|
|
|
TLeftBracket = class(TExprWord)
|
|
function GetResultType: TExpressionType; override;
|
|
end;
|
|
|
|
TRightBracket = class(TExprWord)
|
|
protected
|
|
function GetResultType: TExpressionType; override;
|
|
end;
|
|
|
|
TComma = class(TExprWord)
|
|
protected
|
|
function GetResultType: TExpressionType; override;
|
|
end;
|
|
|
|
TFunction = class(TExprWord)
|
|
private
|
|
FIsOperator: Boolean;
|
|
FOperPrec: Integer;
|
|
FMinFunctionArg: Integer;
|
|
FMaxFunctionArg: Integer;
|
|
FDescription: string;
|
|
FTypeSpec: string;
|
|
FShortName: string;
|
|
FResultType: TExpressionType;
|
|
protected
|
|
function GetDescription: string; override;
|
|
function GetIsOperator: Boolean; override;
|
|
function GetMinFunctionArg: Integer; override;
|
|
function GetMaxFunctionArg: Integer; override;
|
|
function GetResultType: TExpressionType; override;
|
|
function GetTypeSpec: string; override;
|
|
function GetShortName: string; override;
|
|
|
|
procedure InternalCreate(AName, ATypeSpec: string; AMinFuncArg: Integer; AResultType: TExpressionType;
|
|
AExprFunc: TExprFunc; AIsOperator: Boolean; AOperPrec: Integer);
|
|
public
|
|
constructor Create(AName, AShortName, ATypeSpec: string; AMinFuncArg: Integer; AResultType: TExpressionType; AExprFunc: TExprFunc; Descr: string);
|
|
constructor CreateOper(AName, ATypeSpec: string; AResultType: TExpressionType; AExprFunc: TExprFunc; AOperPrec: Integer);
|
|
|
|
function IsFunction: Boolean; override;
|
|
|
|
property OperPrec: Integer read FOperPrec;
|
|
property TypeSpec: string read FTypeSpec;
|
|
end;
|
|
|
|
TVaryingFunction = class(TFunction)
|
|
// Functions that can vary for ex. random generators
|
|
// should be TVaryingFunction to be sure that they are
|
|
// always evaluated
|
|
protected
|
|
function GetCanVary: Boolean; override;
|
|
end;
|
|
|
|
const
|
|
ListChar = ','; {the delimiter used with the 'in' operator: e.g.,
|
|
('a' in 'a,b') =True
|
|
('c' in 'a,b') =False}
|
|
|
|
function ExprCharToExprType(ExprChar: Char): TExpressionType;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
function ExprCharToExprType(ExprChar: Char): TExpressionType;
|
|
begin
|
|
case ExprChar of
|
|
'B': Result := etBoolean;
|
|
'I': Result := etInteger;
|
|
'L': Result := etLargeInt;
|
|
'F': Result := etFloat;
|
|
'D': Result := etDateTime;
|
|
'S': Result := etString;
|
|
else
|
|
Result := etUnknown;
|
|
end;
|
|
end;
|
|
|
|
procedure _FloatVariable(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
PDouble(Res.MemoryPos^)^ := PDouble(Args[0])^;
|
|
end;
|
|
|
|
procedure _BooleanVariable(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
PBoolean(Res.MemoryPos^)^ := PBoolean(Args[0])^;
|
|
end;
|
|
|
|
procedure _StringConstant(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
Res.Append(Args[0], StrLen(Args[0]));
|
|
end;
|
|
|
|
procedure _StringVariable(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
Res.Append(PPChar(Args[0])^, StrLen(PPChar(Args[0])^));
|
|
end;
|
|
|
|
procedure _StringVariableFixedLen(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
Res.Append(PPChar(Args[0])^, PInteger(Args[1])^);
|
|
end;
|
|
|
|
procedure _DateTimeVariable(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
PDateTimeRec(Res.MemoryPos^)^ := PDateTimeRec(Args[0])^;
|
|
end;
|
|
|
|
procedure _IntegerVariable(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
PInteger(Res.MemoryPos^)^ := PInteger(Args[0])^;
|
|
end;
|
|
|
|
{
|
|
procedure _SmallIntVariable(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
PSmallInt(Res.MemoryPos^)^ := PSmallInt(Args[0])^;
|
|
end;
|
|
}
|
|
|
|
{$ifdef SUPPORT_INT64}
|
|
|
|
procedure _LargeIntVariable(Param: PExpressionRec);
|
|
begin
|
|
with Param^ do
|
|
PLargeInt(Res.MemoryPos^)^ := PLargeInt(Args[0])^;
|
|
end;
|
|
|
|
{$endif}
|
|
|
|
{ TExpressionWord }
|
|
|
|
constructor TExprWord.Create(AName: string; AExprFunc: TExprFunc);
|
|
begin
|
|
FName := AName;
|
|
FExprFunc := AExprFunc;
|
|
end;
|
|
|
|
function TExprWord.GetCanVary: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TExprWord.GetDescription: string;
|
|
begin
|
|
Result := EmptyStr;
|
|
end;
|
|
|
|
function TExprWord.GetShortName: string;
|
|
begin
|
|
Result := EmptyStr;
|
|
end;
|
|
|
|
function TExprWord.GetIsOperator: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TExprWord.GetIsVariable: Boolean;
|
|
begin
|
|
Result := (@FExprFunc = @_StringVariable) or
|
|
(@FExprFunc = @_StringConstant) or
|
|
(@FExprFunc = @_StringVariableFixedLen) or
|
|
(@FExprFunc = @_FloatVariable) or
|
|
(@FExprFunc = @_IntegerVariable) or
|
|
// (@FExprFunc = @_SmallIntVariable) or
|
|
{$ifdef SUPPORT_INT64}
|
|
(@FExprFunc = @_LargeIntVariable) or
|
|
{$endif}
|
|
(@FExprFunc = @_DateTimeVariable) or
|
|
(@FExprFunc = @_BooleanVariable);
|
|
end;
|
|
|
|
function TExprWord.GetNeedsCopy: Boolean;
|
|
begin
|
|
Result := (@FExprFunc <> @_StringConstant) and
|
|
// (@FExprFunc <> @_StringVariable) and
|
|
// (@FExprFunc <> @_StringVariableFixedLen) and
|
|
// string variable cannot be used as normal parameter
|
|
// because it is indirectly referenced and possibly
|
|
// not null-terminated (fixed len)
|
|
(@FExprFunc <> @_FloatVariable) and
|
|
(@FExprFunc <> @_IntegerVariable) and
|
|
// (@FExprFunc <> @_SmallIntVariable) and
|
|
{$ifdef SUPPORT_INT64}
|
|
(@FExprFunc <> @_LargeIntVariable) and
|
|
{$endif}
|
|
(@FExprFunc <> @_DateTimeVariable) and
|
|
(@FExprFunc <> @_BooleanVariable);
|
|
end;
|
|
|
|
function TExprWord.GetFixedLen: Integer;
|
|
begin
|
|
// -1 means variable, non-fixed length
|
|
Result := -1;
|
|
end;
|
|
|
|
function TExprWord.GetMinFunctionArg: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
function TExprWord.GetMaxFunctionArg: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
function TExprWord.GetResultType: TExpressionType;
|
|
begin
|
|
Result := etUnknown;
|
|
end;
|
|
|
|
function TExprWord.GetTypeSpec: string;
|
|
begin
|
|
Result := EmptyStr;
|
|
end;
|
|
|
|
function TExprWord.AsPointer: PChar;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
function TExprWord.LenAsPointer: PInteger;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
function TExprWord.IsFunction: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{ TConstant }
|
|
|
|
constructor TConstant.Create(AName: string; AVarType: TExpressionType; AExprFunc: TExprFunc);
|
|
begin
|
|
inherited Create(AName, AExprFunc);
|
|
|
|
FResultType := AVarType;
|
|
end;
|
|
|
|
function TConstant.GetResultType: TExpressionType;
|
|
begin
|
|
Result := FResultType;
|
|
end;
|
|
|
|
{ TFloatConstant }
|
|
|
|
constructor TFloatConstant.Create(AName, AValue: string);
|
|
begin
|
|
inherited Create(AName, etFloat, _FloatVariable);
|
|
|
|
if Length(AValue) > 0 then
|
|
FValue := StrToFloat(AValue)
|
|
else
|
|
FValue := 0.0;
|
|
end;
|
|
|
|
constructor TFloatConstant.CreateAsDouble(AName: string; AValue: Double);
|
|
begin
|
|
inherited Create(AName, etFloat, _FloatVariable);
|
|
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TFloatConstant.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(@FValue);
|
|
end;
|
|
|
|
{ TUserConstant }
|
|
|
|
constructor TUserConstant.CreateAsDouble(AName, Descr: string; AValue: Double);
|
|
begin
|
|
FDescription := Descr;
|
|
|
|
inherited CreateAsDouble(AName, AValue);
|
|
end;
|
|
|
|
function TUserConstant.GetDescription: string;
|
|
begin
|
|
Result := FDescription;
|
|
end;
|
|
|
|
{ TStringConstant }
|
|
|
|
constructor TStringConstant.Create(AValue: string);
|
|
var
|
|
firstChar, lastChar: Char;
|
|
begin
|
|
inherited Create(AValue, etString, _StringConstant);
|
|
|
|
firstChar := AValue[1];
|
|
lastChar := AValue[Length(AValue)];
|
|
if (firstChar = lastChar) and ((firstChar = '''') or (firstChar = '"')) then
|
|
FValue := Copy(AValue, 2, Length(AValue) - 2)
|
|
else
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TStringConstant.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(FValue);
|
|
end;
|
|
|
|
{ TBooleanConstant }
|
|
|
|
constructor TBooleanConstant.Create(AName: string; AValue: Boolean);
|
|
begin
|
|
inherited Create(AName, etBoolean, _BooleanVariable);
|
|
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TBooleanConstant.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(@FValue);
|
|
end;
|
|
|
|
{ TIntegerConstant }
|
|
|
|
constructor TIntegerConstant.Create(AValue: Integer);
|
|
begin
|
|
inherited Create(IntToStr(AValue), etInteger, _IntegerVariable);
|
|
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TIntegerConstant.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(@FValue);
|
|
end;
|
|
|
|
{ TVariable }
|
|
|
|
constructor TVariable.Create(AName: string; AVarType: TExpressionType; AExprFunc: TExprFunc);
|
|
begin
|
|
inherited Create(AName, AExprFunc);
|
|
|
|
FResultType := AVarType;
|
|
end;
|
|
|
|
function TVariable.GetCanVary: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TVariable.GetResultType: TExpressionType;
|
|
begin
|
|
Result := FResultType;
|
|
end;
|
|
|
|
{ TFloatVariable }
|
|
|
|
constructor TFloatVariable.Create(AName: string; AValue: PDouble);
|
|
begin
|
|
inherited Create(AName, etFloat, _FloatVariable);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TFloatVariable.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(FValue);
|
|
end;
|
|
|
|
{ TStringVariable }
|
|
|
|
constructor TStringVariable.Create(AName: string; AValue: PPChar; AFixedLen: Integer);
|
|
begin
|
|
// variable or fixed length?
|
|
if (AFixedLen < 0) then
|
|
inherited Create(AName, etString, _StringVariable)
|
|
else
|
|
inherited Create(AName, etString, _StringVariableFixedLen);
|
|
|
|
// store pointer to string
|
|
FValue := AValue;
|
|
FFixedLen := AFixedLen;
|
|
end;
|
|
|
|
function TStringVariable.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(FValue);
|
|
end;
|
|
|
|
function TStringVariable.GetFixedLen: Integer;
|
|
begin
|
|
Result := FFixedLen;
|
|
end;
|
|
|
|
function TStringVariable.LenAsPointer: PInteger;
|
|
begin
|
|
Result := @FFixedLen;
|
|
end;
|
|
|
|
{ TDateTimeVariable }
|
|
|
|
constructor TDateTimeVariable.Create(AName: string; AValue: PDateTimeRec);
|
|
begin
|
|
inherited Create(AName, etDateTime, _DateTimeVariable);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TDateTimeVariable.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(FValue);
|
|
end;
|
|
|
|
{ TIntegerVariable }
|
|
|
|
constructor TIntegerVariable.Create(AName: string; AValue: PInteger);
|
|
begin
|
|
inherited Create(AName, etInteger, _IntegerVariable);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TIntegerVariable.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(FValue);
|
|
end;
|
|
|
|
{$ifdef SUPPORT_INT64}
|
|
|
|
{ TLargeIntVariable }
|
|
|
|
constructor TLargeIntVariable.Create(AName: string; AValue: PLargeInt);
|
|
begin
|
|
inherited Create(AName, etLargeInt, _LargeIntVariable);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TLargeIntVariable.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(FValue);
|
|
end;
|
|
|
|
{$endif}
|
|
|
|
{ TBooleanVariable }
|
|
|
|
constructor TBooleanVariable.Create(AName: string; AValue: PBoolean);
|
|
begin
|
|
inherited Create(AName, etBoolean, _BooleanVariable);
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TBooleanVariable.AsPointer: PChar;
|
|
begin
|
|
Result := PChar(FValue);
|
|
end;
|
|
|
|
{ TLeftBracket }
|
|
|
|
function TLeftBracket.GetResultType: TExpressionType;
|
|
begin
|
|
Result := etLeftBracket;
|
|
end;
|
|
|
|
{ TRightBracket }
|
|
|
|
function TRightBracket.GetResultType: TExpressionType;
|
|
begin
|
|
Result := etRightBracket;
|
|
end;
|
|
|
|
{ TComma }
|
|
|
|
function TComma.GetResultType: TExpressionType;
|
|
begin
|
|
Result := etComma;
|
|
end;
|
|
|
|
{ TExpressList }
|
|
|
|
constructor TExpressList.Create;
|
|
begin
|
|
inherited;
|
|
|
|
FShortList := TExpressShortList.Create;
|
|
end;
|
|
|
|
destructor TExpressList.Destroy;
|
|
begin
|
|
inherited;
|
|
FShortList.Free;
|
|
end;
|
|
|
|
procedure TExpressList.Add(Item: Pointer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
inherited;
|
|
|
|
{ remember we reference the object }
|
|
Inc(TExprWord(Item).FRefCount);
|
|
|
|
{ also add ShortName as reference }
|
|
if Length(TExprWord(Item).ShortName) > 0 then
|
|
begin
|
|
FShortList.Search(FShortList.KeyOf(Item), I);
|
|
FShortList.Insert(I, Item);
|
|
end;
|
|
end;
|
|
|
|
function TExpressList.Compare(Key1, Key2: Pointer): Integer;
|
|
begin
|
|
Result := StrIComp(PChar(Key1), PChar(Key2));
|
|
end;
|
|
|
|
function TExpressList.KeyOf(Item: Pointer): Pointer;
|
|
begin
|
|
Result := PChar(TExprWord(Item).Name);
|
|
end;
|
|
|
|
procedure TExpressList.FreeItem(Item: Pointer);
|
|
begin
|
|
Dec(TExprWord(Item).FRefCount);
|
|
FShortList.Remove(Item);
|
|
if TExprWord(Item).FRefCount = 0 then
|
|
inherited;
|
|
end;
|
|
|
|
function TExpressList.Search(Key: Pointer; var Index: Integer): Boolean;
|
|
var
|
|
SecIndex: Integer;
|
|
begin
|
|
Result := inherited Search(Key, Index);
|
|
if not Result then
|
|
begin
|
|
Result := FShortList.Search(Key, SecIndex);
|
|
if Result then
|
|
Index := IndexOf(FShortList.Items[SecIndex]);
|
|
end;
|
|
end;
|
|
|
|
function TExpressShortList.Compare(Key1, Key2: Pointer): Integer;
|
|
begin
|
|
Result := StrIComp(PChar(Key1), PChar(Key2));
|
|
end;
|
|
|
|
function TExpressShortList.KeyOf(Item: Pointer): Pointer;
|
|
begin
|
|
Result := PChar(TExprWord(Item).ShortName);
|
|
end;
|
|
|
|
procedure TExpressShortList.FreeItem(Item: Pointer);
|
|
begin
|
|
end;
|
|
|
|
{ TExprCollection }
|
|
|
|
procedure TExprCollection.Check;
|
|
var
|
|
brCount, I: Integer;
|
|
begin
|
|
brCount := 0;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
case TExprWord(Items[I]).ResultType of
|
|
etLeftBracket: Inc(brCount);
|
|
etRightBracket: Dec(brCount);
|
|
end;
|
|
end;
|
|
if brCount <> 0 then
|
|
raise EParserException.Create('Unequal brackets');
|
|
end;
|
|
|
|
procedure TExprCollection.EraseExtraBrackets;
|
|
var
|
|
I: Integer;
|
|
brCount: Integer;
|
|
begin
|
|
if (TExprWord(Items[0]).ResultType = etLeftBracket) then
|
|
begin
|
|
brCount := 1;
|
|
I := 1;
|
|
while (I < Count) and (brCount > 0) do
|
|
begin
|
|
case TExprWord(Items[I]).ResultType of
|
|
etLeftBracket: Inc(brCount);
|
|
etRightBracket: Dec(brCount);
|
|
end;
|
|
Inc(I);
|
|
end;
|
|
if (brCount = 0) and (I = Count) and (TExprWord(Items[I - 1]).ResultType =
|
|
etRightBracket) then
|
|
begin
|
|
for I := 0 to Count - 3 do
|
|
Items[I] := Items[I + 1];
|
|
Count := Count - 2;
|
|
EraseExtraBrackets; //Check if there are still too many brackets
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TFunction }
|
|
|
|
constructor TFunction.Create(AName, AShortName, ATypeSpec: string; AMinFuncArg: Integer; AResultType: TExpressionType;
|
|
AExprFunc: TExprFunc; Descr: string);
|
|
begin
|
|
//to increase compatibility don't use default parameters
|
|
FDescription := Descr;
|
|
FShortName := AShortName;
|
|
InternalCreate(AName, ATypeSpec, AMinFuncArg, AResultType, AExprFunc, false, 0);
|
|
end;
|
|
|
|
constructor TFunction.CreateOper(AName, ATypeSpec: string; AResultType: TExpressionType;
|
|
AExprFunc: TExprFunc; AOperPrec: Integer);
|
|
begin
|
|
InternalCreate(AName, ATypeSpec, -1, AResultType, AExprFunc, true, AOperPrec);
|
|
end;
|
|
|
|
procedure TFunction.InternalCreate(AName, ATypeSpec: string; AMinFuncArg: Integer; AResultType: TExpressionType;
|
|
AExprFunc: TExprFunc; AIsOperator: Boolean; AOperPrec: Integer);
|
|
begin
|
|
inherited Create(AName, AExprFunc);
|
|
|
|
FMaxFunctionArg := Length(ATypeSpec);
|
|
FMinFunctionArg := AMinFuncArg;
|
|
if AMinFuncArg = -1 then
|
|
FMinFunctionArg := FMaxFunctionArg;
|
|
FIsOperator := AIsOperator;
|
|
FOperPrec := AOperPrec;
|
|
FTypeSpec := ATypeSpec;
|
|
FResultType := AResultType;
|
|
|
|
// check correctness
|
|
if FMaxFunctionArg > MaxArg then
|
|
raise EParserException.Create('Too many arguments');
|
|
end;
|
|
|
|
function TFunction.GetDescription: string;
|
|
begin
|
|
Result := FDescription;
|
|
end;
|
|
|
|
function TFunction.GetIsOperator: Boolean;
|
|
begin
|
|
Result := FIsOperator;
|
|
end;
|
|
|
|
function TFunction.GetMinFunctionArg: Integer;
|
|
begin
|
|
Result := FMinFunctionArg;
|
|
end;
|
|
|
|
function TFunction.GetMaxFunctionArg: Integer;
|
|
begin
|
|
Result := FMaxFunctionArg;
|
|
end;
|
|
|
|
function TFunction.GetResultType: TExpressionType;
|
|
begin
|
|
Result := FResultType;
|
|
end;
|
|
|
|
function TFunction.GetShortName: string;
|
|
begin
|
|
Result := FShortName;
|
|
end;
|
|
|
|
function TFunction.GetTypeSpec: string;
|
|
begin
|
|
Result := FTypeSpec;
|
|
end;
|
|
|
|
function TFunction.IsFunction: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{ TVaryingFunction }
|
|
|
|
function TVaryingFunction.GetCanVary: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{ TDynamicType }
|
|
|
|
constructor TDynamicType.Create(DestMem, DestPos: PPChar; Size: PInteger);
|
|
begin
|
|
inherited Create;
|
|
|
|
FMemory := DestMem;
|
|
FMemoryPos := DestPos;
|
|
FSize := Size;
|
|
end;
|
|
|
|
procedure TDynamicType.Rewind;
|
|
begin
|
|
FMemoryPos^ := FMemory^;
|
|
end;
|
|
|
|
procedure TDynamicType.AssureSpace(ASize: Integer);
|
|
begin
|
|
// need more memory?
|
|
if ((FMemoryPos^) - (FMemory^) + ASize) > (FSize^) then
|
|
Resize((FMemoryPos^) - (FMemory^) + ASize, False);
|
|
end;
|
|
|
|
procedure TDynamicType.Resize(NewSize: Integer; Exact: Boolean);
|
|
var
|
|
tempBuf: PChar;
|
|
bytesCopy, pos: Integer;
|
|
begin
|
|
// if not exact requested make newlength a multiple of ArgAllocSize
|
|
if not Exact then
|
|
NewSize := NewSize div ArgAllocSize * ArgAllocSize + ArgAllocSize;
|
|
// create new buffer
|
|
GetMem(tempBuf, NewSize);
|
|
// copy memory
|
|
bytesCopy := FSize^;
|
|
if bytesCopy > NewSize then
|
|
bytesCopy := NewSize;
|
|
Move(FMemory^^, tempBuf^, bytesCopy);
|
|
// save position in string
|
|
pos := FMemoryPos^ - FMemory^;
|
|
// delete old mem
|
|
FreeMem(FMemory^);
|
|
// assign new
|
|
FMemory^ := tempBuf;
|
|
FSize^ := NewSize;
|
|
// assign position
|
|
FMemoryPos^ := FMemory^ + pos;
|
|
end;
|
|
|
|
procedure TDynamicType.Append(Source: PChar; Length: Integer);
|
|
begin
|
|
// make room for string plus null-terminator
|
|
AssureSpace(Length+4);
|
|
// copy
|
|
Move(Source^, FMemoryPos^^, Length);
|
|
Inc(FMemoryPos^, Length);
|
|
// null-terminate
|
|
FMemoryPos^^ := #0;
|
|
end;
|
|
|
|
procedure TDynamicType.AppendInteger(Source: Integer);
|
|
begin
|
|
// make room for number
|
|
AssureSpace(12);
|
|
Inc(FMemoryPos^, GetStrFromInt(Source, FMemoryPos^));
|
|
FMemoryPos^^ := #0;
|
|
end;
|
|
|
|
end.
|
|
|