📄 uparse.pas
字号:
begin
Name := ExtractShortPathName(ExpandFileName(Name));
if Name <> '' then //directory exists?
Dirs.AddObject(Name, List.Objects[i]) //add to list of directories
end;
end;
end;
var AddFiles :TStrings; //list of files to parse
//list of directories to search for files to parse
AddDirs :TStrings;
//list of files not to parse when found (in/by AddDirs)
SubFiles :TStrings;
//list of directories not to search when searching (in/by AddDirs)
SubDirs :TStrings;
begin
AddFiles := TStringList.Create;
try
AddDirs := TStringList.Create;
try
FProgress.SetWorkText('Splitting list of files/directories...');
//split list of files and directories to parse
SplitLists(Parse, AddFiles, AddDirs);
SubFiles := TStringList.Create;
try
SubDirs := TStringList.Create;
try
FProgress.SetWorkText('Splitting list of ignored files/directories...');
//split list of files and directories not to parse
SplitLists(NotParse, SubFiles, SubDirs);
FProgress.SetWorkText('Parsing files and directories...');
//parse all files and the files in the directories
ParseList(AddFiles, AddDirs, SubFiles, SubDirs);
finally
SubDirs.Free;
end;
finally
SubFiles.Free;
end;
finally
AddDirs.Free;
end;
finally
AddFiles.Free;
end;
end;
{Parses all units the files use (in their interfaces). }
procedure TParserManager.ParseAllUsedUnits;
var Count :Integer; //number of parsed files
i :Integer; //counter through parsed files
FileD :TPascalFile; //each file to be parsed
begin
repeat //as long as no new files found
Count := List.Count; //get number of parsed files
FProgress.Reset;
FProgress.SetWorkText('Parsing first uses-clause...');
FProgress.SetMaximum(Count);
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Parsing file %d of %d',
[i + 1, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
if TFileParser(FileD.Parser).ParseState =
psInterfaceUsesClauseParsed then //not parsed yet?
//parse its used units (in the interface)
TFileParser(FileD.Parser).ParseInterfaceUsedUnits;
FProgress.StepProgress;
end;
until List.Count = Count; //until no new files (from Libs)
end;
{Parses all units the files use and interfaces of units. }
procedure TParserManager.ParseInterfacesAndUsedUnits;
var Count :Integer; //number of parsed files
i :Integer; //counter through parsed files
FileD :TPascalFile; //each file to be parsed
begin
repeat //until no new files (from Libs)
//parse all units the files use (in their interfaces)
ParseAllUsedUnits;
//sort the files into the right order for parsing
SortFileList(List);
FProgress.Reset;
FProgress.SetWorkText('Parsing interface-section...');
Count := List.Count; //get number of parsed files
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Parsing file %d of %d', [i + 1, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
if TFileParser(FileD.Parser).ParseState = //not parsed yet?
psInterfaceUnitsParsed then
//parse the interface-section and the uses-clause of
//the implementation section if it is a unit
TFileParser(FileD.Parser).ParseInterface;
FProgress.StepProgress;
end;
FProgress.Reset;
FProgress.SetWorkText('Parsing later uses-clause and linking interface...');
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Parsing file %d of %d', [i + 1, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
//not parsed yet?
if TFileParser(FileD.Parser).ParseState = psInterfaceParsed then
//parse its used units (in case it's a unit parse also the interface)
TFileParser(FileD.Parser).
LinkUnitInterfaceAndParseImplementationUsedUnits;
FProgress.StepProgress;
end;
until List.Count = Count; //until no new files (from Libs)
end;
{Encapsulates the parsing of several pascal-files. This function provides a
simple way to call the various functions and methods of different classes in
the right sequence. }
procedure TParserManager.DoParseFiles;
var i, j :Integer; //general counter
Count :Integer; //number of parsed files
FileD :TPascalFile; //a file of pascal code to be parsed
//counter through the kind of record-likes
rk :TRecordKind;
Index :Integer; //index in identifiers with the same name
S :String; //name of an identifier for comparison
//for test of identifiers (functions & record-like) with the same
IdentList :TIdentifierList; //name
//for test of identifiers with the same name
Ident :TIdentifier;
SearchIndex :Integer; //index to resume the search
//portability issues of the file
Portability :TIdentPortabilities;
begin
//initialize FProgress-object
FProgress.Reset;
FProgress.SetThrowExceptionOnStepIfAbort(True);
FProgress.SetWorkText('Adding predefined Identifiers...');
FProgress.SetProgressText('');
FProgress.SetProcessText('');
FProgress.SetMaximum(10);
//add list of predefined identifiers
{
if FileExists('PreDefinedIdents.txt') then
TFileParser.GetPreDefinedIdentList.LoadFromFile('PreDefinedIdents.txt');
if FileExists('SystemTypes.txt') then
TFileParser.GetSystemTypeList.LoadFromFile('SystemTypes.txt');
if FileExists('SystemIdents.txt') then
TFileParser.GetSystemIdentList.LoadFromFile('SystemIdents.txt');
}
//create the list for the files to parse only if used by other files
GetLibList;
if assigned(Parse) then //new files to parse specified?
ParseNewFiles; //parse them
//parse all units the files use and interfaces of units
ParseInterfacesAndUsedUnits;
Count := List.Count; //get number of parsed files
FProgress.Reset;
FProgress.SetWorkText('Consistence in hierarchy of record-likes...');
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Parsing file %d of %d', [i + 1, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
//check all public (in the interface declared) record-like types
TFileParser(FileD.Parser).ConsistencyAfterRecordHierarchy;
FProgress.StepProgress;
end;
FProgress.Reset;
FProgress.SetWorkText('Parsing Implementation...');
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Parsing file %d of %d', [i + 1, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
//parse the code of the file
TFileParser(FileD.Parser).ParseImplementations;
FProgress.StepProgress;
end;
FProgress.Reset;
FProgress.SetWorkText('Consistence of record-likes after parsing...');
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Parsing file %d of %d', [i + 1, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
//sorts the different lists of identifiers
TFileParser(FileD.Parser).ConsistencyAfterParse;
FProgress.StepProgress;
end;
FProgress.Reset;
FProgress.SetWorkText('Generating cross-reference...');
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Generating with file %d of %d',
[Count - i, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
//check if correct state of parsing
TFileParser(FileD.Parser).DoCheckParseState(psFinalConsistency);
//generate cross-references (for function-identifiers; used by ~)
for j := 0 to FileD.Idents.Count - 1 do
begin
//generate cross-reference
Ident := FileD.Idents[j].GenerateCrossReference;
if Assigned(Ident) then //function without body found?
TFileParser(FileD.Parser).ExceptionIdentFmt(Ident, etSyntax,
'No implementation/body found for function "%s"!',
[Ident.Name]);
end;
//set new state of parsing
TFileParser(FileD.Parser).ParseState := psCrossReferences;
FProgress.StepProgress;
end;
FProgress.Reset;
FProgress.SetWorkText('Inheriting portability issues...');
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Inheriting in file %d of %d',
[Count - i, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
//check if correct state of parsing
TFileParser(FileD.Parser).DoCheckParseState(psCrossReferences);
//get portability issues of the file
Portability := FileD.Portability;
//let all identifier inherit portability issues
for j := 0 to FileD.Idents.Count - 1 do
FileD.Idents[j].AddPortabilityIssues(Portability);
//set new state of parsing
TFileParser(FileD.Parser).ParseState := psPortabilityIssuesInheritedFirst;
//second time for enumeration items
for j := 0 to FileD.Idents.Count - 1 do
FileD.Idents[j].AddPortabilityIssues(Portability);
//set new state of parsing
TFileParser(FileD.Parser).ParseState :=
psPortabilityIssuesInheritedEnumeration;
FProgress.StepProgress;
end;
FProgress.Reset;
FProgress.SetWorkText('Testing of double names...');
for i := 0 to Count - 1 do //for each file
begin
FileD := List[i]; //get the file
FProgress.SetProgressText(Format('Testing file %d of %d',
[Count - i, Count]));
FProgress.SetProcessText(FileD.InternalFileName);
//test if internal name corresponds to name of file
TestFileName(FileD);
Index := 0;
S := LowerCase(FileD.InternalFileName); //get (internal) name of file
for j := i + 1 to Count - 1 do //compare to each others name
if LowerCase(List[j].InternalFileName) = S then
inc(Index);
FileD.InternalNameIndex := Index; //numerate files with same name
//add a warning, the first time, the name is doubled encountered
if Index = 1 then //i.e. the second time
AddWarning(Format('Files with same internal name: %s',
[FileD.InternalFileName]),
TFileParser(FileD.Parser));
FProgress.StepProgress;
end;
FProgress.Reset;
FProgress.SetWorkText('Testing of double names...');
FProgress.SetMaximum(Count * (ord(high(rk)) - ord(low(rk)) + 1 + 1));
IdentList := TIdentifierList.Create; //create list for all identifiers
try
for rk := high(rk) downto low(rk) do //for each kind of record-like types
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -