mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 07:39:25 +02:00
* Fix parsing uses unit in filename, added library parsing and exports sections
git-svn-id: trunk@21915 -
This commit is contained in:
parent
07ebc51b6c
commit
7a1d4dfe72
@ -249,7 +249,7 @@ type
|
||||
function ElementTypeName: string; override;
|
||||
public
|
||||
Declarations, ResStrings, Types, Consts, Classes,
|
||||
Functions, Variables, Properties: TFPList;
|
||||
Functions, Variables, Properties, ExportSymbols: TFPList;
|
||||
end;
|
||||
|
||||
{ TPasSection }
|
||||
@ -276,6 +276,9 @@ type
|
||||
TProgramSection = class(TImplementationSection)
|
||||
end;
|
||||
|
||||
TLibrarySection = class(TImplementationSection)
|
||||
end;
|
||||
|
||||
TInitializationSection = class;
|
||||
TFinalizationSection = class;
|
||||
|
||||
@ -308,7 +311,18 @@ type
|
||||
destructor Destroy; override;
|
||||
function ElementTypeName: string; override;
|
||||
Public
|
||||
ProgramSection: TInterfaceSection;
|
||||
ProgramSection: TProgramSection;
|
||||
InputFile,OutPutFile : String;
|
||||
end;
|
||||
|
||||
{ TPasLibrary }
|
||||
|
||||
TPasLibrary = class(TPasModule)
|
||||
Public
|
||||
destructor Destroy; override;
|
||||
function ElementTypeName: string; override;
|
||||
Public
|
||||
LibrarySection: TLibrarySection;
|
||||
InputFile,OutPutFile : String;
|
||||
end;
|
||||
|
||||
@ -567,13 +581,24 @@ type
|
||||
ResultEl: TPasResultElement;
|
||||
end;
|
||||
|
||||
TPasUnresolvedTypeRef = class(TPasType)
|
||||
TPasUnresolvedSymbolRef = class(TPasType)
|
||||
end;
|
||||
|
||||
TPasUnresolvedTypeRef = class(TPasUnresolvedSymbolRef)
|
||||
public
|
||||
// Typerefs cannot be parented! -> AParent _must_ be NIL
|
||||
constructor Create(const AName: string; AParent: TPasElement); override;
|
||||
function ElementTypeName: string; override;
|
||||
end;
|
||||
|
||||
{ TPasUnresolvedUnitRef }
|
||||
|
||||
TPasUnresolvedUnitRef = Class(TPasUnresolvedSymbolRef)
|
||||
function ElementTypeName: string; override;
|
||||
Public
|
||||
FileName : string;
|
||||
end;
|
||||
|
||||
{ TPasStringType }
|
||||
|
||||
TPasStringType = class(TPasUnresolvedTypeRef)
|
||||
@ -605,6 +630,16 @@ type
|
||||
Expr: TPasExpr;
|
||||
end;
|
||||
|
||||
{ TPasExportSymbol }
|
||||
|
||||
TPasExportSymbol = class(TPasElement)
|
||||
ExportName : TPasExpr;
|
||||
Exportindex : TPasExpr;
|
||||
Destructor Destroy; override;
|
||||
function ElementTypeName: string; override;
|
||||
function GetDeclaration(full : boolean) : string; override;
|
||||
end;
|
||||
|
||||
{ TPasConst }
|
||||
|
||||
TPasConst = class(TPasVariable)
|
||||
@ -1078,6 +1113,50 @@ implementation
|
||||
|
||||
uses SysUtils;
|
||||
|
||||
{ TPasExportSymbol }
|
||||
|
||||
destructor TPasExportSymbol.Destroy;
|
||||
begin
|
||||
FreeAndNil(ExportName);
|
||||
FreeAndNil(ExportIndex);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TPasExportSymbol.ElementTypeName: string;
|
||||
begin
|
||||
Result:='Export'
|
||||
end;
|
||||
|
||||
function TPasExportSymbol.GetDeclaration(full: boolean): string;
|
||||
begin
|
||||
Result:=Name;
|
||||
if (ExportName<>Nil) then
|
||||
Result:=Result+' name '+ExportName.GetDeclaration(Full)
|
||||
else if (ExportIndex<>Nil) then
|
||||
Result:=Result+' index '+ExportIndex.GetDeclaration(Full);
|
||||
|
||||
end;
|
||||
|
||||
{ TPasUnresolvedUnitRef }
|
||||
|
||||
function TPasUnresolvedUnitRef.ElementTypeName: string;
|
||||
begin
|
||||
Result:=SPasTreeUnit;
|
||||
end;
|
||||
|
||||
{ TPasLibrary }
|
||||
|
||||
destructor TPasLibrary.Destroy;
|
||||
begin
|
||||
FreeAndNil(LibrarySection);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TPasLibrary.ElementTypeName: string;
|
||||
begin
|
||||
Result:=inherited ElementTypeName;
|
||||
end;
|
||||
|
||||
{ TPasProgram }
|
||||
|
||||
destructor TPasProgram.Destroy;
|
||||
@ -1291,12 +1370,14 @@ begin
|
||||
Functions := TFPList.Create;
|
||||
Variables := TFPList.Create;
|
||||
Properties := TFPList.Create;
|
||||
ExportSymbols := TFPList.Create;
|
||||
end;
|
||||
|
||||
destructor TPasDeclarations.Destroy;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
ExportSymbols.Free;
|
||||
Variables.Free;
|
||||
Functions.Free;
|
||||
Classes.Free;
|
||||
|
@ -200,6 +200,7 @@ type
|
||||
Function ParseClassDecl(Parent: TPasElement; const AClassName: String; AObjKind: TPasObjKind; PackMode : TPackMode= pmNone): TPasType;
|
||||
Function ParseProperty(Parent : TPasElement; Const AName : String; AVisibility : TPasMemberVisibility; IsClass : Boolean) : TPasProperty;
|
||||
function ParseRangeType(AParent: TPasElement; Const TypeName: String; Full : Boolean = True): TPasRangeType;
|
||||
procedure ParseExportDecl(Parent: TPasElement; List: TFPList);
|
||||
// Constant declarations
|
||||
function ParseConstDecl(Parent: TPasElement): TPasConst;
|
||||
function ParseResourcestringDecl(Parent: TPasElement): TPasResString;
|
||||
@ -210,6 +211,7 @@ type
|
||||
procedure ParseMain(var Module: TPasModule);
|
||||
procedure ParseUnit(var Module: TPasModule);
|
||||
procedure ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
|
||||
procedure ParseLibrary(var Module: TPasModule);
|
||||
procedure ParseUsesList(ASection: TPasSection);
|
||||
procedure ParseInterface;
|
||||
procedure ParseImplementation;
|
||||
@ -252,7 +254,8 @@ const
|
||||
WhitespaceTokensToIgnore = [tkWhitespace, tkComment, tkLineEnding, tkTab];
|
||||
|
||||
type
|
||||
TDeclType = (declNone, declConst, declResourcestring, declType, declVar, declThreadvar, declProperty);
|
||||
TDeclType = (declNone, declConst, declResourcestring, declType,
|
||||
declVar, declThreadvar, declProperty, declExports);
|
||||
|
||||
Function IsHintToken(T : String; Out AHint : TPasMemberHint) : boolean;
|
||||
|
||||
@ -1634,6 +1637,8 @@ begin
|
||||
ParseUnit(Module);
|
||||
tkProgram:
|
||||
ParseProgram(Module);
|
||||
tkLibrary:
|
||||
ParseLibrary(Module);
|
||||
else
|
||||
ungettoken;
|
||||
ParseProgram(Module,True);
|
||||
@ -1706,7 +1711,34 @@ begin
|
||||
ParseExc(Format(SParserExpectTokenError,[';']));
|
||||
end;
|
||||
Section := TProgramSection(CreateElement(TProgramSection, '', CurModule));
|
||||
PP.ImplementationSection := Section;
|
||||
PP.ProgramSection := Section;
|
||||
ParseDeclarations(Section);
|
||||
finally
|
||||
FCurModule:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasParser.ParseLibrary(var Module: TPasModule);
|
||||
Var
|
||||
PP : TPasLibrary;
|
||||
Section : TLibrarySection;
|
||||
|
||||
begin
|
||||
Module := nil;
|
||||
PP:=TPasLibrary(CreateElement(TPasLibrary, ExpectIdentifier, Engine.Package));
|
||||
Module :=PP;
|
||||
FCurModule:=Module;
|
||||
try
|
||||
if Assigned(Engine.Package) then
|
||||
begin
|
||||
Module.PackageName := Engine.Package.Name;
|
||||
Engine.Package.Modules.Add(Module);
|
||||
end;
|
||||
NextToken;
|
||||
if (CurToken<>tkSemicolon) then
|
||||
ParseExc(Format(SParserExpectTokenError,[';']));
|
||||
Section := TLibrarySection(CreateElement(TLibrarySection, '', CurModule));
|
||||
PP.LibrarySection := Section;
|
||||
ParseDeclarations(Section);
|
||||
finally
|
||||
FCurModule:=nil;
|
||||
@ -1822,6 +1854,7 @@ var
|
||||
List: TFPList;
|
||||
i,j: Integer;
|
||||
VarEl: TPasVariable;
|
||||
ExpEl: TPasExportSymbol;
|
||||
PropEl : TPasProperty;
|
||||
TypeName: String;
|
||||
PT : TProcType;
|
||||
@ -1872,6 +1905,8 @@ begin
|
||||
ParseExc(SParserSyntaxError);
|
||||
tkConst:
|
||||
CurBlock := declConst;
|
||||
tkexports:
|
||||
CurBlock := declExports;
|
||||
tkResourcestring:
|
||||
CurBlock := declResourcestring;
|
||||
tkType:
|
||||
@ -1947,6 +1982,27 @@ begin
|
||||
Declarations.Types.Add(TypeEl);
|
||||
end;
|
||||
end;
|
||||
declExports:
|
||||
begin
|
||||
List := TFPList.Create;
|
||||
try
|
||||
try
|
||||
ParseExportDecl(Declarations, List);
|
||||
except
|
||||
for i := 0 to List.Count - 1 do
|
||||
TPasExportSymbol(List[i]).Release;
|
||||
raise;
|
||||
end;
|
||||
for i := 0 to List.Count - 1 do
|
||||
begin
|
||||
ExpEl := TPasExportSymbol(List[i]);
|
||||
Declarations.Declarations.Add(ExpEl);
|
||||
Declarations.ExportSymbols.Add(ExpEl);
|
||||
end;
|
||||
finally
|
||||
List.Free;
|
||||
end;
|
||||
end;
|
||||
declVar, declThreadVar:
|
||||
begin
|
||||
List := TFPList.Create;
|
||||
@ -2028,43 +2084,40 @@ end;
|
||||
// Starts after the "uses" token
|
||||
procedure TPasParser.ParseUsesList(ASection: TPasSection);
|
||||
|
||||
function CheckUnit(AUnitName : string):TPasElement;
|
||||
begin
|
||||
function CheckUnit(AUnitName : string):TPasElement;
|
||||
begin
|
||||
result := Engine.FindModule(AUnitName); // should we resolve module here when "IN" filename is not known yet?
|
||||
if Assigned(result) then
|
||||
result.AddRef
|
||||
else
|
||||
Result := TPasType(CreateElement(TPasUnresolvedTypeRef, AUnitName,
|
||||
Result := TPasType(CreateElement(TPasUnresolvedUnitRef, AUnitName,
|
||||
ASection));
|
||||
ASection.UsesList.Add(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
AUnitName: String;
|
||||
Element: TPasElement;
|
||||
begin
|
||||
If not (Asection is TImplementationSection) Then // interface,program,library,package
|
||||
If not (Asection.ClassType=TImplementationSection) Then // interface,program,library,package
|
||||
Element:=CheckUnit('System'); // system always implicitely first.
|
||||
while True do
|
||||
begin
|
||||
Repeat
|
||||
AUnitName := ExpectIdentifier;
|
||||
Element :=CheckUnit(AUnitName);
|
||||
|
||||
NextToken;
|
||||
if (CurToken=tkin) then
|
||||
begin
|
||||
ExpectToken(tkString);
|
||||
if (Element is TPasModule) and (TPasmodule(Element).filename='') then
|
||||
TPasModule(Element).FileName:=curtokenstring
|
||||
else if (Element is TPasUnresolvedUnitRef) then
|
||||
TPasUnresolvedUnitRef(Element).FileName:=curtokenstring;
|
||||
NextToken;
|
||||
end;
|
||||
|
||||
if CurToken = tkin then begin
|
||||
// todo: store unit's file name somewhere
|
||||
NextToken; // skip in
|
||||
ExpectToken(tkString); // skip unit's real file name
|
||||
if (Element is TPasModule) and (TPasmodule(Element).filename<>'') then
|
||||
TPasModule(Element).FileName:=curtokenstring;
|
||||
end;
|
||||
|
||||
if CurToken = tkSemicolon then
|
||||
break
|
||||
else if CurToken <> tkComma then
|
||||
if Not (CurToken in [tkComma,tkSemicolon]) then
|
||||
ParseExc(SParserExpectedCommaSemicolon);
|
||||
end;
|
||||
Until (CurToken=tkSemicolon);
|
||||
end;
|
||||
|
||||
// Starts after the variable name
|
||||
@ -2159,6 +2212,30 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// Starts after Exports, on first identifier.
|
||||
procedure TPasParser.ParseExportDecl(Parent: TPasElement; List: TFPList);
|
||||
Var
|
||||
E : TPasExportSymbol;
|
||||
begin
|
||||
Repeat
|
||||
E:=TPasExportSymbol(CreateElement(TPasExportSymbol,CurtokenString,Parent));
|
||||
List.Add(E);
|
||||
NextToken;
|
||||
if CurTokenIsIdentifier('INDEX') then
|
||||
begin
|
||||
NextToken;
|
||||
E.Exportindex:=DoParseExpression(E,Nil)
|
||||
end
|
||||
else if CurTokenIsIdentifier('NAME') then
|
||||
begin
|
||||
NextToken;
|
||||
E.ExportName:=DoParseExpression(E,Nil)
|
||||
end;
|
||||
if not (CurToken in [tkComma,tkSemicolon]) then
|
||||
ParseExc(SParserExpectedCommaSemicolon);
|
||||
until (CurToken=tkSemicolon);
|
||||
end;
|
||||
|
||||
Function TPasParser.ParseSpecializeType(Parent : TPasElement; Const TypeName : String) : TPasClassType;
|
||||
|
||||
begin
|
||||
|
Loading…
Reference in New Issue
Block a user