cxregexpr.pas
来自「胜天进销存源码,国产优秀的进销存」· PAS 代码 · 共 2,586 行 · 第 1/5 页
PAS
2,586 行
end;
procedure TcxRegExpr.Clear;
begin
FStream.Size := 0;
FErrors.Clear;
FLexems.Clear;
FBlocks.Clear;
if FAutomat <> nil then
FAutomat.Free;
FAutomat := nil;
FIndex := 0;
FLexemIndex := 0;
FChar := 0;
FLine := 1;
FCompiled := False;
end;
function TcxRegExpr.Decimal(AToken: Char): Boolean;
begin
if AToken in ['0','1','2','3','4','5','6','7','8','9'] then
Result := True
else
Result := False;
end;
function TcxRegExpr.EmptyStream: Boolean;
var
AToken: Char;
I: Integer;
begin
if FStream.Size = 0 then
Result := True
else
begin
I := 0;
while LookToken(AToken, I) do
begin
if not Space(AToken) then
begin
Result := False;
Exit;
end;
Inc(I);
end;
Result := True;
end;
end;
function TcxRegExpr.CreateLexem(ALine: Integer; AChar: Integer; ACode: Integer;
AValue: string): TcxLexem;
begin
Result.Line := ALine;
Result.Char := AChar;
Result.Code := ACode;
Result.Value := AValue;
end;
function TcxRegExpr.GetLexem(var ALexem: TcxLexem): Boolean;
begin
if (FLexemIndex >= 0) and (FLexemIndex < FLexems.Count) then
begin
ALexem := FLexems[FLexemIndex];
Inc(FLexemIndex);
Result := True;
end
else
Result := False;
end;
function TcxRegExpr.GetToken(out AToken: Char): Boolean;
begin
Result := LookToken(AToken, 0);
if Result then
begin
Inc(FIndex);
if AToken = #13 then
Inc(FLine);
if AToken = #10 then
FChar := 0
else
Inc(FChar);
end;
end;
function TcxRegExpr.GetStream: TStream;
begin
if FCompiled then
Result := FStream
else
Result := nil;
end;
function TcxRegExpr.Hexadecimal(AToken: Char): Boolean;
begin
Result := (AToken >= '0') and (AToken <= '9') or
(AToken >= 'A') and (AToken <= 'F') or
(AToken >= 'a') and (AToken <= 'f');
end;
function TcxRegExpr.LookToken(out AToken: Char; APtr: Integer): Boolean;
begin
Result := ((FIndex + APtr) < FStream.Size) and ((FIndex + APtr) >= 0);
if Result then
AToken := Char(PByteArray(FStream.Memory)[FIndex + APtr]);
end;
function TcxRegExpr.ParseAlt(AAlt: TcxRegExprParserAlt; Global: Boolean): Boolean;
var
ALexem: TcxLexem;
ACurrentItem: TcxRegExprParserItem;
procedure AddItem(AItem: TcxRegExprParserItem);
begin
ACurrentItem := AItem;
AAlt.Add(AItem);
end;
procedure SetQuantifier(AQuantifier: TcxRegExprQuantifier);
var
ABlock: TcxRegExprParserBlockItem;
begin
if ACurrentItem.NotQuantifier then
ACurrentItem.SetQuantifier(AQuantifier)
else
begin
ABlock := TcxRegExprParserBlockItem.Create(AQuantifier);
ABlock.Alts.AddAlt;
ABlock.Alts.LastAlt.Add(ACurrentItem);
ACurrentItem := ABlock;
AAlt.FItems[AAlt.FItems.Count - 1] := ABlock;
end;
end;
function CreateParameterQuantifierBlock(AIndex, ACount: Integer): TcxRegExprParserItem;
begin
if AIndex < (ACount - 1) then
begin
Result := TcxRegExprParserBlockItem.Create(TcxRegExprQuestionQuantifier.Create);
with TcxRegExprParserBlockItem(Result).Alts do
begin
AddAlt;
LastAlt.Add(ACurrentItem.Clone);
LastAlt.Add(CreateParameterQuantifierBlock(AIndex + 1, ACount));
end;
end
else
begin
Result := ACurrentItem.Clone;
Result.SetQuantifier(TcxRegExprQuestionQuantifier.Create);
end;
end;
procedure SetParameterQuantifier(A, B: Integer);
var
ABlock: TcxRegExprParserBlockItem;
AItem: TcxRegExprParserItem;
I: Integer;
begin
if ACurrentItem.CanMissing then
begin
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprCantUseParameterQuantifier)));
Exit;
end;
ABlock := TcxRegExprParserBlockItem.Create(TcxRegExprSimpleQuantifier.Create);
ABlock.Alts.AddAlt;
for I := 0 to A - 1 do
ABlock.Alts.LastAlt.Add(ACurrentItem.Clone);
if B = -1 then
begin
AItem := ACurrentItem.Clone;
AItem.SetQuantifier(TcxRegExprStarQuantifier.Create);
ABlock.Alts.LastAlt.Add(AItem);
end
else if B > A then
ABlock.Alts.LastAlt.Add(CreateParameterQuantifierBlock(A, B));
ACurrentItem := ABlock;
AAlt.LastItem := ABlock;
end;
procedure SetQuestionQuantifier;
begin
SetQuantifier(TcxRegExprQuestionQuantifier.Create);
end;
procedure SetPlusQuantifier;
begin
if ACurrentItem.CanEmpty then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprCantUsePlusQuantifier)))
else
SetQuantifier(TcxRegExprPlusQuantifier.Create);
end;
procedure SetStarQuantifier;
begin
if ACurrentItem.CanEmpty then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprCantUseStarQuantifier)))
else
SetQuantifier(TcxRegExprStarQuantifier.Create);
end;
var
RefNumber: Integer;
A, B: Integer;
begin
ACurrentItem := nil;
if GetLexem(ALexem) then
begin
if (TcxRegExprLexemCode(ALexem.Code) = relcSpecial) and (ALexem.Value[1] = '|') then
begin
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprCantCreateEmptyAlt)));
Result := True;
Exit;
end;
if not Global then
begin
if (TcxRegExprLexemCode(ALexem.Code) = relcSpecial) and (ALexem.Value[1] = ')') then
begin
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprCantCreateEmptyBlock)));
Result := False;
Exit;
end;
end;
end
else
begin
FErrors.Add(TcxRegExprError.Create(0, 0, cxGetResourceString(@scxRegExprCantCreateEmptyAlt)));
Result := False;
Exit;
end;
repeat
case TcxRegExprLexemCode(ALexem.Code) of
relcSymbol:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprSymbol.Create(
ALexem.Value[1]))));
relcSpecial:
begin
case ALexem.Value[1] of
'|':
begin
Result := True;
Exit;
end;
'(':
AddItem(ParseBlock);
')':
begin
if Global then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalSymbol), [')'])))
else
begin
Result := False;
Exit;
end;
end;
'[':
AddItem(ParseEnumeration);
']':
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalSymbol), [']'])));
'{':
begin
if ACurrentItem = nil then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprIncorrectParameterQuantifier)))
else
begin
ParseQuantifier(A, B);
SetParameterQuantifier(A, B);
end;
end;
'}':
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalSymbol), ['}'])));
'-':
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalSymbol), ['-'])));
'?':
begin
if ACurrentItem = nil then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalQuantifier), ['?'])))
else
SetQuestionQuantifier;
end;
'+':
begin
if ACurrentItem = nil then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalQuantifier), ['+'])))
else
SetPlusQuantifier;
end;
'*':
begin
if ACurrentItem = nil then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalQuantifier), ['*'])))
else
SetStarQuantifier;
end;
end;
end;
relcInteger:
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprIllegalIntegerValue)));
relcTimeSeparator:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprTimeSeparator.Create)));
relcDateSeparator:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprDateSeparator.Create)));
relcAll:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprAll.Create)));
relcId:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprIdLetter.Create)));
relcNotId:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprIdLetter.Create(True))));
relcDigit:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprDigit.Create)));
relcNotDigit:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprDigit.Create(True))));
relcSpace:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprSpace.Create)));
relcNotSpace:
AddItem(
TcxRegExprParserSimpleItem.Create(
TcxRegExprSimpleState.Create(
TcxRegExprSpace.Create(True))));
relcReference:
begin
RefNumber := StrToInt(ALexem.Value) - 1;
if RefNumber >= FBlocks.Count then
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprTooBigReferenceNumber)))
else
AddItem(TcxRegExprParserItem(FBlocks[RefNumber]).Clone);
end;
end;
until not GetLexem(ALexem);
Result := False;
end;
function TcxRegExpr.ParseBlock: TcxRegExprParserBlockItem;
begin
Result := TcxRegExprParserBlockItem.Create;
FBlocks.Add(Result);
repeat
Result.Alts.AddAlt;
until not ParseAlt(Result.Alts.LastAlt, False);
end;
function TcxRegExpr.ParseEnumeration: TcxRegExprParserSimpleItem;
var
ALexem: TcxLexem;
ALexem1: TcxLexem;
Enumeration: TcxRegExprUserEnumeration;
begin
GetLexem(ALexem);
if (TcxRegExprLexemCode(ALexem.Code) = relcSpecial) and (ALexem.Value[1] = '^') then
begin
Enumeration := TcxRegExprUserEnumeration.Create(True);
GetLexem(ALexem);
end
else
Enumeration := TcxRegExprUserEnumeration.Create;
Result := TcxRegExprParserSimpleItem.Create(TcxRegExprSimpleState.Create(Enumeration));
if (TcxRegExprLexemCode(ALexem.Code) = relcSpecial) and (ALexem.Value[1] = ']') then
begin
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
cxGetResourceString(@scxRegExprCantCreateEmptyEnum)));
Exit;
end;
repeat
GetLexem(ALexem1);
if (TcxRegExprLexemCode(ALexem1.Code) = relcSpecial) and (ALexem1.Value[1] = '-') then
begin
GetLexem(ALexem1);
if ALexem.Value[1] < ALexem1.Value[1] then
Enumeration.Add(TcxRegExprSubrange.Create(ALexem.Value[1], ALexem1.Value[1]))
else
FErrors.Add(TcxRegExprError.Create(ALexem1.Line, ALexem1.Char,
cxGetResourceString(@scxRegExprSubrangeOrder)));
GetLexem(ALexem);
while (TcxRegExprLexemCode(ALexem.Code) = relcSpecial) and (ALexem.Value[1] = '-') do
begin
FErrors.Add(TcxRegExprError.Create(ALexem.Line, ALexem.Char,
Format(cxGetResourceString(@scxRegExprIllegalSymbol), ['-'])));
GetLexem(ALexem);
end;
end
else
begin
case TcxRegExprLexemCode(ALexem.Code) of
relcTimeSeparator:
Enumeration.Add(TcxRegExprTimeSeparator.Create);
relcDateSeparator:
Enumeration.Add(TcxRegExprDateSeparator.Create);
relcAll:
Enumeration.Add(TcxRegExprAll.Create);
relcId:
Enumeration.Add(TcxRegExprIdLetter.Create);
relcNotId:
Enumeration.Add(TcxRegExprIdLetter.Create(True));
relcDigit:
Enumeration.Add(TcxRegExprDigit.Create);
relcNotDigit:
Enumeration.Add(TcxRegExprDigit.Create(True));
relcSpace:
Enumeration.Add(TcxRegExprSpace.Create);
relcNotSpace:
Enumeration.Add(TcxRegExprSpace.Create(True));
else
Enumeration.Add(TcxRegExprSymbol.Create(ALexem.Value[1]));
end;
ALexem := ALexem1;
end;
until (TcxRegExprLexemCode(ALexem.Code) = relcSpecial) and (ALexem.Value[1] = ']');
end;
procedure TcxRegExpr.ParseExpr;
var
Expr: TcxRegExprParserAlts;
begin
Expr := TcxRegExprParserAlts.Create;
repeat
Expr.AddAlt;
until not ParseAlt(Expr.LastAlt);
if FErrors.Count > 0 then
Expr.Free
else
begin
Expr.CreateConnections;
Expr.CreateFinalStates;
FAutomat := TcxRegExprAutomat.Create(Expr, Self);
end;
end;
procedure TcxRegExpr.ParseQuantifier(var A: Integer; var B: Integer);
var
ALexem: TcxLexem;
begin
GetLexem(ALexem);
if TcxRegExprLexemCode(ALexem.Code) = relcInteger then
begin
A := StrToInt(ALexem.Value);
GetLexem(ALexem);
if TcxRegExprLexemCode(ALexem.Code) = relcSpecial then
begin
if ALexem.Value = ',' then
begin
GetLexem(ALexem);
if TcxRegExprLexemCode(ALexem.Code) = relcInteger then
begin
B := StrToInt(ALexem.Value);
if B >= A then
begin
GetLexem(ALexem);
if (TcxRegExprLexemCode(ALexem.Code) = relcSpecial) and (ALexem.Value = '}') then
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?