📄 dedepparser.pas
字号:
unit DeDePParser;
interface
uses Classes, SysUtils;
Type TPredicate = (pNone, pType, pProp, pMeth, pVar, pConst, pProc, pFunc, pClass, pRecord, pEvent, pUses);
Type TOnNewBlockEvent = Procedure (iFrom, iTo : Integer; pType : TPredicate; reserved:Integer) of Object;
Var NewBlockProc : TOnNewBlockEvent;
procedure TruncAll(Var s : String);
Procedure ReplaceString(Var s : String; s1,s2 : String);
Procedure InitNewParse(AList : TStringList; ANewBlockProc : TOnNewBlockEvent; FsFileName : String);
Procedure ParseIT;
Procedure GetChar;
Procedure BackUp;
Procedure Restore;
Procedure Push;
Procedure Pop;
Procedure CorrectEndPos;
Procedure p_Predicate(s : String);
Function ParseClass(s : String) : String;
Procedure PrepareDeclaration(var s : String);
function RemoveComments(s: string): string;
Type TProgresProcedure = Procedure (Max,Pos : Longint) of Object;
Var GlobPos : Integer;
GlobChar : Char;
GlobLevel : Integer;
GlobPredicate : TPredicate;
GlobSubPredicate : TPredicate;
GlobEndParse : Boolean;
GlobComment : Boolean;
GlobString : Boolean;
GlobEvent : Boolean;
GlobClassDefExpected : Boolean;
GlobClassStarted : Boolean;
GlobClassOf : Boolean;
GlobDeclType : Integer;
GlobInterface : Boolean;
GlobName : String;
EndComment : Char;
PASFile : TStringList;
PASMem : TMemoryStream;
ProgresProc : TProgresProcedure;
const STACK_SIZE = 4096;
var
StackPos : Array [1..STACK_SIZE] of Integer;
StackChar : Array [1..STACK_SIZE] of Char;
StackPointer : Integer;
implementation
Var bkPos : Integer;
bkChar : Char;
bInType : Boolean;
bNL : Boolean;
procedure TruncAll(Var s : String);
begin
While Copy(s,1,1)=#32 Do s:=Copy(s,2,Length(s)-1);
While Copy(s,Length(s),1)=#32 Do s:=Copy(s,1,Length(s)-1);
end;
Procedure ReplaceString(Var s : String; s1,s2 : String);
var i : Integer;
Begin
i:=Pos(s1,s);
s:=Copy(s,1,i-1)+s2+Copy(s,i+Length(s1),Length(s)-i-Length(s1)+1);
End;
function RemoveComments(s: string): string;
var s2: string;
begin
while (Pos('(*',s) > 0) and (Pos('*)',s) > Pos('(*',s)) do
Delete(s,Pos('(*',s),Pos('*)',s)-Pos('(*',s)+2);
while Pos('//',s) > 0 do begin
s2 := Copy(s,Pos('//',s),Length(s));
if Pos(#13+#10,s2) > 0 then
Delete(s,Pos('//',s),Pos(#13+#10,s2)-1)
else
Delete(s,Pos('//',s),Length(s));
end;
while (Pos('{',s) > 0) and (Pos('}',s) > Pos('{',s)) do
Delete(s,Pos('{',s),Pos('}',s)-Pos('{',s)+1);
Result := s;
end;
Procedure InitNewParse(AList : TStringList; ANewBlockProc : TOnNewBlockEvent; FsFileName : String);
var s,s1: String;
sz : Cardinal;
Begin
NewBlockProc:=ANewBlockProc;
PASFile.Assign(AList);
If FsfileName<>'' Then
PASMem.LoadFromFile(FsFileName);
PASMem.Seek(0,soFromBeginning);
GlobPos:=0;
GlobLevel:=0;
GlobChar:=#0;
GlobPredicate:=pNone;
StackPointer:=0;
GlobEndParse:=False;
GlobComment:=False;
GlobString:=False;
bInType:=False;
GlobEvent:=False;
GlobClassDefExpected:=False;
GlobClassStarted:=False;
GlobClassOf:=False;
ProgresProc(Pos('IMPLEMENTATION',AnsiUpperCase(PasFile.Text)),0);
End;
Procedure GetChar;
var ch : Char;
Begin
If GlobPos=PASMem.Size Then
Begin
GlobEndParse:=True;
Exit;
End;
Repeat
Inc(GlobPos);
If GlobPos=PASMem.Size Then
Begin
GlobEndParse:=True;
Exit;
End;
PASMem.Seek(GlobPos, soFromBeginning);
PASMem.ReadBuffer(GlobChar,1);//
If GlobChar='''' Then GlobString:=not GlobString;
If (not GlobString) and (GlobComment) and (GlobChar=EndComment) Then
Begin
GlobComment:=False;
EndComment:=#0;
End;
Until (GlobChar in [#13,#32..#255]) and (not GlobString);
If (not GlobString) then
begin
If (GlobChar='{') and (not (GlobComment)) Then
Begin
EndComment:='}';
GlobComment:=True;
End;
If (GlobChar='/')
then begin
PASMem.ReadBuffer(ch,1);
if (ch='/') and not (GlobComment) Then
Begin
EndComment:=#13;
GlobComment:=True;
End
Else PASMem.Seek(-1,soFromCurrent);
end;
end;
End;
Procedure Backup;
Begin
bkPos:=GlobPos;
bkChar:=GlobChar;
End;
Procedure Restore;
Begin
GlobPos:=bkPos;
GlobChar:=bkChar;
End;
Procedure Push;
Begin
If StackPointer=STACK_SIZE Then Raise Exception.Create('Parser stack overflow');
Inc(StackPointer);
StackChar[StackPointer]:=GlobChar;
StackPos[StackPointer]:=GlobPos;
End;
Procedure Pop;
Begin
If StackPointer=0 Then Raise Exception.Create('Parser stack underflow');
GlobChar:=StackChar[StackPointer];
GlobPos:=StackPos[StackPointer];
Dec(StackPointer);
End;
Function ParseWord(s : String) : Boolean;
Begin
Result:= (s='PROCEDURE')
or (s='FUNCTION')
or (s='TYPE')
or (s='VAR');
End;
Procedure ParseIT;
var sWord : String;
bInterface : Boolean;
Begin
sWord:='';
bInterface:=False;
Repeat
GetChar;
If GlobChar='=' Then bInType:=True;
If GlobChar in [#13,';',#32,'(',')','=','+'] Then
Begin
If (Not GlobComment) and (not GlobString) Then
Begin
If sWord='' Then sWord:=GlobChar;
If bInterface Then
p_Predicate(AnsiUpperCase(sWord));
If (not bInterface) and (AnsiUpperCase(sWord)='INTERFACE') Then
begin
bInterface:=True;
push;
end;
If (ParseWord(AnsiUpperCase(sWord))) and (not bInterface) Then GlobEndParse:=True;
If AnsiUpperCase(sWord)='IMPLEMENTATION' Then
begin
GlobEndParse:=True;
end;
End;
sWord:='';
If GlobEndParse Then Break;
bNL:=False;
Continue;
End;
sWord:=sWord+GlobChar;
Until GlobEndParse;
ProgresProc(0,Length(PasFile.Text));
End;
Procedure p_Predicate(s : String);
Var Pred : TPredicate;
beg: Integer;
Begin
If s='' Then Exit;
Pred:=pNone;
If GlobChar='(' Then
Inc(GlobLevel);
If s='IMPLEMENTATION' Then
Begin
GlobEndParse:=True;
Exit;
End;
If s='USES' Then
Begin
Pred:=pUses;
End;
If s='TYPE' Then
Begin
Pred:=pType;
GlobSubPredicate:=pNone;
bInType:=True;
End;
If (s='VAR') and (not GlobEvent) Then
Begin
If GlobLevel=0 Then
Pred:=pVar;
End;
If (s='CONST') and (not GlobEvent) Then
Begin
If GlobLevel=0 Then
Pred:=pConst;
End;
If s='PROCEDURE' Then
Begin
// Procedure in class declaration
If (GlobLevel=0) then
if bInType Then GlobEvent:=True
else Pred:=pFunc;
// Event type Procedure (blah) of object;
If (GlobLevel=1)
then GlobEvent:=True;
End;
If s='FUNCTION' Then
Begin
// Procedure in class declaration
If (GlobLevel=0) then
if bInType Then GlobEvent:=True
else Pred:=pFunc;
// Event type Procedure (blah) of object;
If (GlobLevel=1)
then GlobEvent:=True;
End;
If ((s='CLASS') or (s='OBJECT') or (s='RECORD') or (s='INTERFACE'))
and (Not GlobEvent) Then
begin
If (GlobPredicate=pType) and (GlobLevel in [0,1]) Then Inc(GlobLevel);
if s='RECORD'
then GlobSubPredicate:=pRecord
else begin
GlobSubPredicate:=pClass;
GlobDeclType:=0;
if s<>'INTERFACE' then
begin
GlobClassDefExpected:=True;
GlobClassStarted:=True;
GlobInterface:=False;
end
else GlobInterface:=True;
end;
end;
If (s='END') and (GlobPredicate=pType) Then Dec(GlobLevel);
if (GlobClassDefExpected) and ( not
( (s = #32)
or (s = #13)
or (s = ';')
or (s = 'CLASS')
or (s = 'OBJECT')
or (s = 'OF'))
) then
if GlobClassOf then GlobClassOf:=False
else GlobClassDefExpected:=False;
if (GlobClassDefExpected) and (s = 'OF') then GlobClassOf:=True;
if (GlobClassStarted) and (
(s='PUBLIC')
or (s='PRIVATE')
or (s='PUBLISHED')
or (s='PROTECTED')
or (s='AUTOMATED')
) then GlobClassStarted:=False;
If GlobChar=')' Then
begin
Dec(GlobLevel);
if GlobClassStarted then
begin
GlobClassStarted:=False;
GlobClassDefExpected:=True;
End;
end;
// TMyBlah = class;
// TBlah = Class(TOtherBlah);
// TBlah = Class of BlahBlah;
If (GlobChar=';') and (GlobClassDefExpected)
then Begin
Dec(GlobLevel);
GlobDeclType:=1;
End;
If (GlobPredicate<>Pred) and (Pred<>pNone) Then
Begin
case GlobPredicate of
pNone :
Begin
Backup;
Pop;
Restore;
// Class Parsing Support
If GlobSubPredicate in [pClass,pRecord]
Then NewBlockProc(0, 0, GlobSubPredicate,GlobDeclType)
Else NewBlockProc(0, 0, Pred,GlobDeclType);
End;
Else
If (GlobPredicate in [pProc, pFunc]) and (not (Pred in [pProc, pFunc]))
or (GlobPredicate in [pProp]) and (not (Pred in [pProp]))
or (GlobPredicate in [pType]) and (not (Pred in [pType]))
Then
Begin
Backup;
Pop;
Restore;
NewBlockProc(0, 0, Pred,GlobDeclType);
End;
end; {Case}
GlobPredicate:=Pred;
// Pushes New Beggining
BackUp;
Dec(GlobPos,Length(s)+1);
Push;
Restore;
End;
If (Pred=pNone) and (GlobChar=';') and (GlobLevel=0) Then
Begin
IF GlobPredicate<>pNone Then
Begin
Backup;
Pop;
beg:=GlobPos;
Restore;
CorrectEndPos;
If GlobInterface then GlobDeclType:=GlobDeclType OR $80000000;
// Class Parsing Support
If GlobSubPredicate in [pClass,pRecord]
Then NewBlockProc(beg+1, GlobPos+2, GlobSubPredicate,GlobDeclType)
Else NewBlockProc(beg+1, GlobPos+2, GlobPredicate,GlobDeclType);
GlobSubPredicate:=pNone;
GlobInterface:=False;
//NewBlockProc(beg+1, GlobPos+2, GlobPredicate);
bInType:=False;
GlobClassStarted:=False;
End;
BackUp;
Inc(GlobPos,1);
Push;
Restore;
// Event types Blah = procedure (blah) of object;
if GlobEvent then GlobEvent:=False;
End;
End;
Procedure CorrectEndPos;
var sWord : String;
bCont : Boolean;
Begin
bCont:=True;
If GlobPredicate in [pProc,pFunc] Then
Begin
BackUp;
sWord:='';
While bCont Do
Begin
GetChar;
While GlobChar=#32 Do GetChar;
sWord:=sWord+GlobChar;
Repeat
GetChar;
If GlobChar in [#13,#32,';'] Then
Begin
sWord:=AnsiUpperCase(sWord);
bCont:= (sWord='STDCALL') or (sWord='EXTERNAL')
or (sWord='FAR') or (sWord='PASCAL')
or (sWord='FORWARD') or (sWord='OVERLOAD') or (sWord='REINTRODUCE');
sWord:='';
If GlobComment Then Continue Else Break;
End;
sWord:=sWord+GlobChar;
Until False;
If (bCont) and (GlobChar<>';') Then
Begin
Repeat GetChar Until GlobChar=';';
End;
If bCont Then BackUp;
End; {While}
Restore;
End; {If}
End;
{ TParsedFile }
Function ParseClass(s : String) : String;
var i,iPos : Integer;
sWord : String;
begin
Result:='';
I:=0;
Repeat
iPos:=Pos(#32,s);
sWord:=Copy(s,1,iPos-1);
s:=Copy(s,iPos+1,Length(s));
Inc(i,iPos);
Until i>=Length(s);
end;
Procedure PrepareDeclaration(var s : String);
var i : Integer;
ss : String;
bSkip : Boolean;
ch, cEnd : Char;
Begin
ss:='';
bSkip:=False;
cEnd:=#0;
// Remove comments
For i:=1 To Length(s) Do
Begin
ch:=s[i];
If (bSkip) and (ch=cEnd) Then
Begin
bSkip:=False;
Continue;
End;
If (not bSkip) and (ch='{') Then
Begin
cEnd:='}';
bSkip:=True;
End;
If (not bSkip) and (ch='/') and (s[i+1]='/') Then
Begin
cEnd:=#13;
bSkip:=True;
End;
If not bSkip Then ss:=ss+ch;
End;
s:='';
For i:=1 To Length(ss) Do
If ss[i]=#10
Then If (i<>1) and (ss[i-1]=#13)
Then s:=s+ss[i]
Else Continue
Else s:=s+ss[i];
End;
initialization
PASFile:=TStringList.Create;
PASMem:=TMemoryStream.Create;
NewBlockProc:=nil
finalization
PASFile.Free;
PASMem.Free;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -