Code: Alles auswählen
program extractor5;
{$I DIRECTIVES}
uses
Classes, SysUtils, IOUtils, FLRE, FLREUnicode;
{ https://github.com/BeRo1985/flre }
function SubStr(const aSource: string; aStart: integer; aEnd: integer = MAXINT): string;
begin
result := Copy(aSource, aStart, aEnd - aStart + 1);
end;
type
TExtractor = class
private
fText: string;
fData: TStringList;
public
constructor Create(const aFileName: string);
destructor Destroy(); override;
procedure Extract(var aCount: integer; const aType: string; const aStart, aEnd: integer);
function Callback(const aInput: PFLRERawByteChar; const aCaptures: TFLRECaptures): TFLRERawByteString;
procedure Restore(const aType: string);
procedure ExtractAll();
procedure SaveText(const aFileName: string);
procedure SaveData(const aFileName: string);
procedure RestoreAll();
procedure Remove(const aType: string);
end;
constructor TExtractor.Create(const aFileName: string);
begin
inherited Create();
fData := TStringList.Create;
fText := TFile.ReadAllText(aFileName);
end;
destructor TExtractor.Destroy();
begin
fData.Free();
inherited Destroy();
end;
procedure TExtractor.Extract(var aCount: integer; const aType: string; const aStart, aEnd: integer);
begin
Inc(aCount);
fData.Append(Format('_%s_%d_=%s', [aType, aCount, SubStr(fText, aStart, aEnd)]));
fText := Format('%s_%s_%d_%s', [SubStr(fText, 1, aStart - 1), aType, aCount, SubStr(fText, aEnd + 1)]);
end;
function TExtractor.Callback(const aInput: PFLRERawByteChar; const aCaptures: TFLRECaptures): TFLRERawByteString;
begin
with aCaptures[0] do result := fData.Values[FLREPtrCopy(aInput, Start, Length)];
end;
procedure TExtractor.Restore(const aType: string);
begin
if Assigned(fData) then
with TFLRE.Create(Format('_%s_\d+_', [aType]), []) do
begin
fText := ReplaceCallback(fText, Callback);
Free();
end;
end;
procedure TExtractor.ExtractAll();
var
c: char;
l: integer;
d: boolean;
cCount,
lCount,
dCount,
i,
iStart,
iEnd: integer;
begin
c := #0;
l := 0;
d := FALSE;
cCount := 0;
lCount := 0;
dCount := 0;
i := 1;
iStart := 0;
iEnd := 0;
while i <= Length(fText) do
begin
if c <> #0 then
begin
if ((c = '{') and (fText[i] = '}'))
or ((c = '(') and (fText[i] = ')') and (fText[i - 1] = '*'))
or ((c = '/') and (i < Length(fText)) and (fText[i + 1] in [#10, #13])) then
begin
iEnd := i;
Extract(cCount, 'comment', iStart, iEnd);
c := #0; // => comment = FALSE
i := iStart - 1;
end;
end else
if l <> 0 then
begin
if fText[i] = '''' then
begin
Inc(l);
if (l mod 2 = 0) and (i < Length(fText)) and (fText[i + 1] <> '''') then
begin
iEnd := i;
Extract(lCount, 'literal', iStart, iEnd);
l := 0; // => literal = FALSE
i := iStart - 1;
end;
end;
end else
if d then
begin
if fText[i] = '}' then
begin
iEnd := i;
Extract(dCount, 'directive', iStart, iEnd);
d := FALSE; // => directive = FALSE
i := iStart - 1;
end;
end else
if ((fText[i] = '{') and (i < Length(fText)) and (fText[i + 1] <> '$'))
or ((fText[i] = '(') and (i < Length(fText)) and (fText[i + 1] = '*'))
or ((fText[i] = '/') and (i < Length(fText)) and (fText[i + 1] = '/')) then
begin
iStart := i;
c := fText[i]; // => comment = TRUE
end else
if fText[i] = '''' then
begin
iStart := i;
l := 1; // => literal = TRUE
end else
if ((fText[i] = '{') and (i < Length(fText)) and (fText[i + 1] = '$')) then
begin
iStart := i;
d := TRUE; // => directive = TRUE
end;
Inc(i);
end;
end;
procedure TExtractor.SaveText(const aFileName: string);
begin
TFile.WriteAllText(aFileName, fText);
end;
procedure TExtractor.SaveData(const aFileName: string);
begin
fData.SaveToFile(aFileName);
end;
procedure TExtractor.RestoreAll();
begin
Restore('[a-z]+');
end;
{$IFDEF VERSION_1}
procedure TExtractor.Remove(const aType: string);
var
captures: TFLREMultiCaptures;
i: integer;
begin
with TFLRE.Create(Format('_%s_\d+_', [aType]), []) do
begin
MaximalDFAStates := 65536;
MatchAll(fText, captures);
for i := High(captures) downto Low(captures) do with captures[i, 0] do Delete(fText, Start, Length);
Free;
end;
end;
{$ELSE}
procedure TExtractor.Remove(const aType: string);
begin
with TFLRE.Create(Format('_%s_\d+_', [aType]), []) do
begin
MaximalDFAStates := 65536;
fText := Replace(fText, '');
Free;
end;
end;
{$ENDIF}
var
filename: string;
begin
if (ParamCount = 1) then
filename := ParamStr(1)
else
filename := {$IFDEF FPC}'extractor5.pp'{$ELSE}'extractor5.dpr'{$ENDIF};
if FileExists(filename) then
with TExtractor.Create(filename) do
begin
ExtractAll();
SaveText('1.txt');
SaveData('2.txt');
Remove('comment');
SaveText('3.txt');
RestoreAll();
SaveText('4.txt');
Free();
end;
end.