📄 dbf_prsdef.pas
字号:
unit dbf_prsdef;
interface
{$I dbf_common.inc}
uses
SysUtils,
Classes,
Db,
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;
PDateTimeRec = ^TDateTimeRec;
{$ifdef SUPPORT_INT64}
PLargeInt = ^Int64;
{$endif}
TExprWord = class;
TExprFunc = procedure(Expr: PExpressionRec);
//-----
TDynamicType = class(TObject)
private
FMemory: PPChar;
FMemoryPos: PPChar;
FSize: PInteger;
public
constructor Create(DestMem, DestPos: PPChar; ASize: 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;
WantsFunction: 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;
procedure SetFixedLen(NewLen: integer); 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 write SetFixedLen;
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;
procedure SetFixedLen(NewLen: integer); override;
public
constructor Create(AName: string; AValue: PPChar);
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);
var
length: integer;
begin
with Param^ do
begin
length := PInteger(Args[1])^;
if length = -1 then
length := StrLen(PPChar(Args[0])^);
Res.Append(PPChar(Args[0])^, length);
end;
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
// delphi wants to call the function pointed to by the variable, use '@'
// fpc simply returns pointer to function, no '@' needed
Result := (@FExprFunc = @_StringVariable) or
(@FExprFunc = @_StringConstant) 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -