mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-19 00:09:26 +02:00
* Support for generics
git-svn-id: trunk@19621 -
This commit is contained in:
parent
9324726374
commit
5ea8e65ea2
@ -1439,16 +1439,47 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
|
|||||||
if assigned(pc) then
|
if assigned(pc) then
|
||||||
begin
|
begin
|
||||||
s:=GetIndent(indent);
|
s:=GetIndent(indent);
|
||||||
write(s,pc.Name,'=');
|
if (pc.ObjKind=okGeneric) then
|
||||||
|
begin
|
||||||
|
write(s,'generic ',pc.Name);
|
||||||
|
for l:=0 to pc.GenericTemplateTypes.Count-1 do
|
||||||
|
begin
|
||||||
|
if l=0 then
|
||||||
|
Write('<')
|
||||||
|
else
|
||||||
|
Write(',');
|
||||||
|
Write(TPasGenericTemplateType(pc.GenericTemplateTypes[l]).Name);
|
||||||
|
end;
|
||||||
|
Write('> = ');
|
||||||
|
end
|
||||||
|
else
|
||||||
|
write(s,pc.Name,' = ');
|
||||||
if pc.IsPacked then write('packed ');
|
if pc.IsPacked then write('packed ');
|
||||||
case pc.ObjKind of
|
case pc.ObjKind of
|
||||||
okObject:write('Object');
|
okObject:write('Object');
|
||||||
okClass:write('Class');
|
okClass:write('Class');
|
||||||
okInterface:write('Interface');
|
okInterface:write('Interface');
|
||||||
|
okGeneric:write('class');
|
||||||
|
okspecialize : write('specialize');
|
||||||
end;
|
end;
|
||||||
if assigned(pc.AncestorType) and (pc.AncestorType.ElementTypeName <> '') then
|
if assigned(pc.AncestorType) and (pc.AncestorType.ElementTypeName <> '') then
|
||||||
write('(',pc.AncestorType.Name,')');
|
begin
|
||||||
|
if pc.ObjKind<>okspecialize then
|
||||||
|
write('(',pc.AncestorType.Name,')')
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
write(' ',pc.AncestorType.Name);
|
||||||
|
for l:=0 to pc.GenericTemplateTypes.Count-1 do
|
||||||
|
begin
|
||||||
|
if l=0 then
|
||||||
|
Write('<')
|
||||||
|
else
|
||||||
|
Write(',');
|
||||||
|
Write(TPasGenericTemplateType(pc.GenericTemplateTypes[l]).Name);
|
||||||
|
end;
|
||||||
|
Write('>');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
if pc.IsForward or pc.IsShortDefinition then //pparser.pp: 3417 :class(anchestor); is allowed !
|
if pc.IsForward or pc.IsShortDefinition then //pparser.pp: 3417 :class(anchestor); is allowed !
|
||||||
begin
|
begin
|
||||||
writeln(';');
|
writeln(';');
|
||||||
@ -1562,6 +1593,7 @@ procedure GetTypes(pe:TPasElement; lindent:integer);
|
|||||||
vars.free;
|
vars.free;
|
||||||
end
|
end
|
||||||
else writeln;//(';'); //x=class(y);
|
else writeln;//(';'); //x=class(y);
|
||||||
|
|
||||||
writeln(s,'end;');
|
writeln(s,'end;');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -147,6 +147,14 @@ interface
|
|||||||
Procedure externalnameProc; external name 'aname';
|
Procedure externalnameProc; external name 'aname';
|
||||||
Procedure externallibnameProc; external 'alibrary' name 'aname';
|
Procedure externallibnameProc; external 'alibrary' name 'aname';
|
||||||
|
|
||||||
|
Type
|
||||||
|
generic TFPGListEnumerator<T> = class(TObject)
|
||||||
|
protected
|
||||||
|
FList: TFPSList;
|
||||||
|
FPosition: Integer;
|
||||||
|
function GetCurrent: T;
|
||||||
|
end;
|
||||||
|
TFPGListEnumeratorSpec = specialize TFPGListEnumerator<T>;
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
|
||||||
|
@ -45,6 +45,8 @@ resourcestring
|
|||||||
SPasTreeObjectType = 'object';
|
SPasTreeObjectType = 'object';
|
||||||
SPasTreeClassType = 'class';
|
SPasTreeClassType = 'class';
|
||||||
SPasTreeInterfaceType = 'interface';
|
SPasTreeInterfaceType = 'interface';
|
||||||
|
SPasTreeGenericType = 'generic class';
|
||||||
|
SPasTreeSpecializedType = 'specialized class type';
|
||||||
SPasTreeArgument = 'argument';
|
SPasTreeArgument = 'argument';
|
||||||
SPasTreeProcedureType = 'procedure type';
|
SPasTreeProcedureType = 'procedure type';
|
||||||
SPasTreeResultElement = 'function result';
|
SPasTreeResultElement = 'function result';
|
||||||
@ -453,8 +455,8 @@ type
|
|||||||
Variants: TList; // array of TPasVariant elements, may be nil!
|
Variants: TList; // array of TPasVariant elements, may be nil!
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TPasGenericTemplateType = Class(TPasElement);
|
||||||
TPasObjKind = (okObject, okClass, okInterface);
|
TPasObjKind = (okObject, okClass, okInterface, okGeneric, okSpecialize);
|
||||||
|
|
||||||
{ TPasClassType }
|
{ TPasClassType }
|
||||||
|
|
||||||
@ -475,8 +477,11 @@ type
|
|||||||
ClassVars: TList; // class vars
|
ClassVars: TList; // class vars
|
||||||
Modifiers: TStringList;
|
Modifiers: TStringList;
|
||||||
Interfaces : TList;
|
Interfaces : TList;
|
||||||
|
GenericTemplateTypes : TList;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TArgumentAccess = (argDefault, argConst, argVar, argOut);
|
TArgumentAccess = (argDefault, argConst, argVar, argOut);
|
||||||
|
|
||||||
{ TPasArgument }
|
{ TPasArgument }
|
||||||
@ -1012,7 +1017,7 @@ const
|
|||||||
'default', 'private', 'protected', 'public', 'published', 'automated','strict private', 'strict protected');
|
'default', 'private', 'protected', 'public', 'published', 'automated','strict private', 'strict protected');
|
||||||
|
|
||||||
ObjKindNames: array[TPasObjKind] of string = (
|
ObjKindNames: array[TPasObjKind] of string = (
|
||||||
'object', 'class', 'interface');
|
'object', 'class', 'interface','class','class');
|
||||||
|
|
||||||
OpcodeStrings : Array[TExprOpCode] of string =
|
OpcodeStrings : Array[TExprOpCode] of string =
|
||||||
('','+','-','*','/','div','mod','**',
|
('','+','-','*','/','div','mod','**',
|
||||||
@ -1081,6 +1086,8 @@ begin
|
|||||||
okObject: Result := SPasTreeObjectType;
|
okObject: Result := SPasTreeObjectType;
|
||||||
okClass: Result := SPasTreeClassType;
|
okClass: Result := SPasTreeClassType;
|
||||||
okInterface: Result := SPasTreeInterfaceType;
|
okInterface: Result := SPasTreeInterfaceType;
|
||||||
|
okGeneric : Result := SPasTreeGenericType;
|
||||||
|
okSpecialize : Result := SPasTreeSpecializedType;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1366,6 +1373,8 @@ begin
|
|||||||
Modifiers := TStringList.Create;
|
Modifiers := TStringList.Create;
|
||||||
ClassVars := TList.Create;
|
ClassVars := TList.Create;
|
||||||
Interfaces:= TList.Create;
|
Interfaces:= TList.Create;
|
||||||
|
GenericTemplateTypes:=TList.Create;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TPasClassType.Destroy;
|
destructor TPasClassType.Destroy;
|
||||||
@ -1380,6 +1389,9 @@ begin
|
|||||||
Modifiers.Free;
|
Modifiers.Free;
|
||||||
ClassVars.Free;
|
ClassVars.Free;
|
||||||
Interfaces.Free;
|
Interfaces.Free;
|
||||||
|
for i := 0 to GenericTemplateTypes.Count - 1 do
|
||||||
|
TPasElement(GenericTemplateTypes[i]).Release;
|
||||||
|
GenericTemplateTypes.Free;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ resourcestring
|
|||||||
SParserErrorAtToken = '%s at token "%s" in file %s at line %d column %d';
|
SParserErrorAtToken = '%s at token "%s" in file %s at line %d column %d';
|
||||||
SParserUngetTokenError = 'Internal error: Cannot unget more tokens, history buffer is full';
|
SParserUngetTokenError = 'Internal error: Cannot unget more tokens, history buffer is full';
|
||||||
SParserExpectTokenError = 'Expected "%s"';
|
SParserExpectTokenError = 'Expected "%s"';
|
||||||
|
SParserExpectToken2Error = 'Expected "%s" or "%s"';
|
||||||
SParserExpectedCommaRBracket = 'Expected "," or ")"';
|
SParserExpectedCommaRBracket = 'Expected "," or ")"';
|
||||||
SParserExpectedCommaSemicolon = 'Expected "," or ";"';
|
SParserExpectedCommaSemicolon = 'Expected "," or ";"';
|
||||||
SParserExpectedCommaColon = 'Expected "," or ":"';
|
SParserExpectedCommaColon = 'Expected "," or ":"';
|
||||||
@ -118,7 +119,9 @@ type
|
|||||||
FTokenStringBuffer: array[0..1] of String;
|
FTokenStringBuffer: array[0..1] of String;
|
||||||
FTokenBufferIndex: Integer; // current index in FTokenBuffer
|
FTokenBufferIndex: Integer; // current index in FTokenBuffer
|
||||||
FTokenBufferSize: Integer; // maximum valid index in FTokenBuffer
|
FTokenBufferSize: Integer; // maximum valid index in FTokenBuffer
|
||||||
|
procedure DoParseClassType(AType: TPasClassType; SourceFileName: String; SourceLineNumber: Integer);
|
||||||
procedure ParseExc(const Msg: String);
|
procedure ParseExc(const Msg: String);
|
||||||
|
procedure ReadGenericArguments(List : TList;Parent : TPasElement; IsSpecialize : Boolean);
|
||||||
protected
|
protected
|
||||||
function OpLevel(t: TToken): Integer;
|
function OpLevel(t: TToken): Integer;
|
||||||
Function TokenToExprOp (AToken : TToken) : TExprOpCode;
|
Function TokenToExprOp (AToken : TToken) : TExprOpCode;
|
||||||
@ -181,8 +184,7 @@ type
|
|||||||
function ParseProcedureOrFunctionDecl(Parent: TPasElement;
|
function ParseProcedureOrFunctionDecl(Parent: TPasElement;
|
||||||
ProcType: TProcType): TPasProcedure;
|
ProcType: TProcType): TPasProcedure;
|
||||||
procedure ParseRecordDecl(Parent: TPasRecordType; IsNested: Boolean); // !!!: Optimize this. We have 3x the same wrapper code around it.
|
procedure ParseRecordDecl(Parent: TPasRecordType; IsNested: Boolean); // !!!: Optimize this. We have 3x the same wrapper code around it.
|
||||||
function ParseClassDecl(Parent: TPasElement; const AClassName: String;
|
function ParseClassDecl(Parent: TPasElement; const AClassName: String; AObjKind: TPasObjKind): TPasType;
|
||||||
AObjKind: TPasObjKind): TPasType;
|
|
||||||
procedure ParseProperty(Element:TPasElement);
|
procedure ParseProperty(Element:TPasElement);
|
||||||
procedure ParseProcBeginBlock(Parent: TProcedureBody);
|
procedure ParseProcBeginBlock(Parent: TProcedureBody);
|
||||||
procedure ParseStatement(Parent: TPasImplBlock;
|
procedure ParseStatement(Parent: TPasImplBlock;
|
||||||
@ -1408,6 +1410,7 @@ var
|
|||||||
i,j: Integer;
|
i,j: Integer;
|
||||||
VarEl: TPasVariable;
|
VarEl: TPasVariable;
|
||||||
PropEl : TPasProperty;
|
PropEl : TPasProperty;
|
||||||
|
TypeName: String;
|
||||||
begin
|
begin
|
||||||
CurBlock := declNone;
|
CurBlock := declNone;
|
||||||
while True do
|
while True do
|
||||||
@ -1592,6 +1595,26 @@ begin
|
|||||||
ParseExc(SParserSyntaxError);
|
ParseExc(SParserSyntaxError);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
tkGeneric:
|
||||||
|
begin
|
||||||
|
if CurBlock <> declType then
|
||||||
|
ParseExc(SParserSyntaxError);
|
||||||
|
TypeName := ExpectIdentifier;
|
||||||
|
ClassEl := TPasClassType(Engine.CreateElement(TPasClassType,TypeName,Declarations, Scanner.CurFilename, Scanner.CurRow));
|
||||||
|
ClassEl.ObjKind:=okGeneric;
|
||||||
|
try
|
||||||
|
ReadGenericArguments(ClassEl.GenericTemplateTypes,ClassEl,False);
|
||||||
|
Except
|
||||||
|
List.Free;
|
||||||
|
Raise;
|
||||||
|
end;
|
||||||
|
ExpectToken(tkEqual);
|
||||||
|
ExpectToken(tkClass);
|
||||||
|
NextToken;
|
||||||
|
DoParseClassType(ClassEl, Scanner.CurFilename, Scanner.CurRow);
|
||||||
|
Declarations.Declarations.Add(ClassEl);
|
||||||
|
Declarations.Classes.Add(ClassEl)
|
||||||
|
end;
|
||||||
tkbegin:
|
tkbegin:
|
||||||
begin
|
begin
|
||||||
if Declarations is TProcedureBody then
|
if Declarations is TProcedureBody then
|
||||||
@ -1705,6 +1728,23 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPasParser.ReadGenericArguments(List : TList;Parent : TPasElement; IsSpecialize : Boolean);
|
||||||
|
|
||||||
|
Var
|
||||||
|
N : String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
ExpectToken(tkLessThan);
|
||||||
|
repeat
|
||||||
|
N:=ExpectIdentifier;
|
||||||
|
List.Add(CreateElement(TPasGenericTemplateType,N,Parent));
|
||||||
|
NextToken;
|
||||||
|
if not (CurToken in [tkComma, tkGreaterThan]) then
|
||||||
|
ParseExc(Format(SParserExpectToken2Error,
|
||||||
|
[TokenInfos[tkComma], TokenInfos[tkGreaterThan]]));
|
||||||
|
until CurToken = tkGreaterThan;
|
||||||
|
end;
|
||||||
|
|
||||||
// Starts after the type name
|
// Starts after the type name
|
||||||
function TPasParser.ParseTypeDecl(Parent: TPasElement): TPasType;
|
function TPasParser.ParseTypeDecl(Parent: TPasElement): TPasType;
|
||||||
var
|
var
|
||||||
@ -1935,6 +1975,16 @@ begin
|
|||||||
raise;
|
raise;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
tkSpecialize:
|
||||||
|
begin
|
||||||
|
Result := TPasClassType(Engine.CreateElement(TPasClassType, TypeName,
|
||||||
|
Parent, Scanner.CurFilename, Scanner.CurRow));
|
||||||
|
TPasClassType(Result).ObjKind := okSpecialize;
|
||||||
|
TPasClassType(Result).AncestorType := ParseType(nil);
|
||||||
|
TPasClassType(Result).IsShortDefinition:=True;
|
||||||
|
ReadGenericArguments(TPasClassType(Result).GenericTemplateTypes,Result,True);
|
||||||
|
ExpectToken(tkSemicolon);
|
||||||
|
end;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
UngetToken;
|
UngetToken;
|
||||||
@ -3187,8 +3237,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Starts after the "class" token
|
// Starts after the "class" token
|
||||||
function TPasParser.ParseClassDecl(Parent: TPasElement;
|
Procedure TPasParser.DoParseClassType(AType : TPasClassType; SourceFileName : String; SourceLineNumber : Integer);
|
||||||
const AClassName: String; AObjKind: TPasObjKind): TPasType;
|
|
||||||
var
|
var
|
||||||
CurVisibility: TPasMemberVisibility;
|
CurVisibility: TPasMemberVisibility;
|
||||||
|
|
||||||
@ -3204,7 +3254,7 @@ var
|
|||||||
HasReturnValue:=false;
|
HasReturnValue:=false;
|
||||||
ExpectIdentifier;
|
ExpectIdentifier;
|
||||||
Name := CurTokenString;
|
Name := CurTokenString;
|
||||||
Owner := CheckIfOverloaded(TPasClassType(Result), Name);
|
Owner := CheckIfOverloaded(AType, Name);
|
||||||
case ProcType of
|
case ProcType of
|
||||||
ptFunction:
|
ptFunction:
|
||||||
begin
|
begin
|
||||||
@ -3251,7 +3301,7 @@ var
|
|||||||
if Owner.ClassType = TPasOverloadedProc then
|
if Owner.ClassType = TPasOverloadedProc then
|
||||||
TPasOverloadedProc(Owner).Overloads.Add(Proc)
|
TPasOverloadedProc(Owner).Overloads.Add(Proc)
|
||||||
else
|
else
|
||||||
TPasClassType(Result).Members.Add(Proc);
|
AType.Members.Add(Proc);
|
||||||
|
|
||||||
if HasReturnValue then
|
if HasReturnValue then
|
||||||
pt := ptFunction
|
pt := ptFunction
|
||||||
@ -3321,43 +3371,18 @@ var
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
s, SourceFilename: String;
|
s: String;
|
||||||
i, SourceLinenumber: Integer;
|
i: Integer;
|
||||||
VarList: TList;
|
VarList: TList;
|
||||||
Element: TPasElement;
|
Element: TPasElement;
|
||||||
isStrict: Boolean;
|
isStrict: Boolean;
|
||||||
begin
|
begin
|
||||||
isStrict:=False;
|
isStrict:=False;
|
||||||
|
|
||||||
// Save current parsing position to get it correct in all cases
|
|
||||||
SourceFilename := Scanner.CurFilename;
|
|
||||||
SourceLinenumber := Scanner.CurRow;
|
|
||||||
|
|
||||||
NextToken;
|
|
||||||
|
|
||||||
if (AObjKind = okClass) and (CurToken = tkOf) then
|
|
||||||
begin
|
|
||||||
Result := TPasClassOfType(Engine.CreateElement(TPasClassOfType, AClassName,
|
|
||||||
Parent, SourceFilename, SourceLinenumber));
|
|
||||||
ExpectIdentifier;
|
|
||||||
UngetToken; // Only names are allowed as following type
|
|
||||||
TPasClassOfType(Result).DestType := ParseType(Result);
|
|
||||||
ExpectToken(tkSemicolon);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
Result := TPasClassType(Engine.CreateElement(TPasClassType, AClassName,
|
|
||||||
Parent, SourceFilename, SourceLinenumber));
|
|
||||||
|
|
||||||
try
|
|
||||||
TPasClassType(Result).ObjKind := AObjKind;
|
|
||||||
|
|
||||||
// nettism/new delphi features
|
// nettism/new delphi features
|
||||||
if (CurToken = tkIdentifier) and (AObjKind = okClass) then begin
|
if (CurToken = tkIdentifier) and (Atype.ObjKind in [okClass,okGeneric]) then begin
|
||||||
s := LowerCase(CurTokenString);
|
s := LowerCase(CurTokenString);
|
||||||
if (s = 'sealed') or (s = 'abstract') then begin
|
if (s = 'sealed') or (s = 'abstract') then begin
|
||||||
TPasClassType(Result).Modifiers.Add(s);
|
AType.Modifiers.Add(s);
|
||||||
NextToken;
|
NextToken;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -3365,12 +3390,12 @@ begin
|
|||||||
// Parse ancestor list
|
// Parse ancestor list
|
||||||
if CurToken = tkBraceOpen then
|
if CurToken = tkBraceOpen then
|
||||||
begin
|
begin
|
||||||
TPasClassType(Result).AncestorType := ParseType(nil);
|
AType.AncestorType := ParseType(nil);
|
||||||
{$ifdef Inheritancewarnings}
|
{$ifdef Inheritancewarnings}
|
||||||
s:=TPasClassType(Result).AncestorType.pathname;
|
s:=AType.AncestorType.pathname;
|
||||||
if pos('#',s)=0 then
|
if pos('#',s)=0 then
|
||||||
begin
|
begin
|
||||||
writeln('Note: ', TPasClassType(Result).pathname,'''s ancestor ',s, ' at ',sourcefilename,':',sourcelinenumber,' cannot be resolved fully');
|
writeln('Note: ', AType.pathname,'''s ancestor ',s, ' at ',sourcefilename,':',sourcelinenumber,' cannot be resolved fully');
|
||||||
end;
|
end;
|
||||||
{$endif}
|
{$endif}
|
||||||
while True do
|
while True do
|
||||||
@ -3383,22 +3408,22 @@ begin
|
|||||||
//ExpectIdentifier;
|
//ExpectIdentifier;
|
||||||
Element:=ParseType(Nil); // search interface.
|
Element:=ParseType(Nil); // search interface.
|
||||||
if assigned(element) then
|
if assigned(element) then
|
||||||
TPasClassType(Result).Interfaces.add(element);
|
AType.Interfaces.add(element);
|
||||||
// !!!: Store interface name
|
// !!!: Store interface name
|
||||||
end;
|
end;
|
||||||
NextToken;
|
NextToken;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
TPasClassType(Result).isForward:=CurToken=tkSemicolon;
|
Atype.isForward:=CurToken=tkSemicolon;
|
||||||
if CurToken = tkSemicolon then
|
if CurToken = tkSemicolon then
|
||||||
TPasClassType(Result).IsShortDefinition:=true;
|
AType.IsShortDefinition:=true;
|
||||||
|
|
||||||
if CurToken <> tkSemicolon then
|
if CurToken <> tkSemicolon then
|
||||||
begin
|
begin
|
||||||
if ( AObjKind = okInterface ) and ( CurToken = tkSquaredBraceOpen ) then
|
if ( AType.ObjKind = okInterface ) and ( CurToken = tkSquaredBraceOpen ) then
|
||||||
begin
|
begin
|
||||||
ExpectToken(tkString);
|
ExpectToken(tkString);
|
||||||
TPasClassType(Result).InterfaceGUID := CurTokenString;
|
AType.InterfaceGUID := CurTokenString;
|
||||||
ExpectToken(tkSquaredBraceClose);
|
ExpectToken(tkSquaredBraceClose);
|
||||||
end;
|
end;
|
||||||
CurVisibility := visDefault;
|
CurVisibility := visDefault;
|
||||||
@ -3431,12 +3456,12 @@ begin
|
|||||||
begin
|
begin
|
||||||
VarList := TList.Create;
|
VarList := TList.Create;
|
||||||
try
|
try
|
||||||
ParseInlineVarDecl(Result, VarList, CurVisibility, False);
|
ParseInlineVarDecl(AType, VarList, CurVisibility, False);
|
||||||
for i := 0 to VarList.Count - 1 do
|
for i := 0 to VarList.Count - 1 do
|
||||||
begin
|
begin
|
||||||
Element := TPasElement(VarList[i]);
|
Element := TPasElement(VarList[i]);
|
||||||
Element.Visibility := CurVisibility;
|
Element.Visibility := CurVisibility;
|
||||||
TPasClassType(Result).Members.Add(Element);
|
AType.Members.Add(Element);
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
VarList.Free;
|
VarList.Free;
|
||||||
@ -3470,20 +3495,53 @@ begin
|
|||||||
tkProperty:
|
tkProperty:
|
||||||
begin
|
begin
|
||||||
ExpectIdentifier;
|
ExpectIdentifier;
|
||||||
Element := CreateElement(TPasProperty, CurTokenString, Result, CurVisibility);
|
Element := CreateElement(TPasProperty, CurTokenString, AType, CurVisibility);
|
||||||
TPasClassType(Result).Members.Add(Element);
|
AType.Members.Add(Element);
|
||||||
ParseProperty(Element);
|
ParseProperty(Element);
|
||||||
end;
|
end;
|
||||||
tkVar: // vars (nettism/new delphi features)
|
tkVar: // vars (nettism/new delphi features)
|
||||||
if AObjKind<>okClass then ExpectToken(tkSemicolon);
|
if (not (AType.ObjKind in [okClass,okGeneric])) then
|
||||||
|
ExpectToken(tkSemicolon);
|
||||||
//todo: class vars
|
//todo: class vars
|
||||||
end; // end case
|
end; // end case
|
||||||
NextToken;
|
NextToken;
|
||||||
end;
|
end;
|
||||||
// Eat semicolon after class...end
|
// Eat semicolon after class...end
|
||||||
CheckHint(result,true);
|
CheckHint(AType,true);
|
||||||
// ExpectToken(tkSemicolon);
|
// ExpectToken(tkSemicolon);
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasParser.ParseClassDecl(Parent: TPasElement; const AClassName: String; AObjKind: TPasObjKind): TPasType;
|
||||||
|
|
||||||
|
Var
|
||||||
|
SourcefileName : string;
|
||||||
|
SourceLineNumber : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Save current parsing position to get it correct in all cases
|
||||||
|
SourceFilename := Scanner.CurFilename;
|
||||||
|
SourceLinenumber := Scanner.CurRow;
|
||||||
|
|
||||||
|
NextToken;
|
||||||
|
|
||||||
|
if (AObjKind = okClass) and (CurToken = tkOf) then
|
||||||
|
begin
|
||||||
|
Result := TPasClassOfType(Engine.CreateElement(TPasClassOfType, AClassName,
|
||||||
|
Parent, SourceFilename, SourceLinenumber));
|
||||||
|
ExpectIdentifier;
|
||||||
|
UngetToken; // Only names are allowed as following type
|
||||||
|
TPasClassOfType(Result).DestType := ParseType(Result);
|
||||||
|
ExpectToken(tkSemicolon);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := TPasClassType(Engine.CreateElement(TPasClassType, AClassName,
|
||||||
|
Parent, SourceFilename, SourceLinenumber));
|
||||||
|
|
||||||
|
try
|
||||||
|
TPasClassType(Result).ObjKind := AObjKind;
|
||||||
|
DoParseClassType(TPasClassType(Result),SourceFileName,SourceLineNumber);
|
||||||
except
|
except
|
||||||
Result.Free;
|
Result.Free;
|
||||||
raise;
|
raise;
|
||||||
|
@ -94,6 +94,7 @@ type
|
|||||||
tkfinally,
|
tkfinally,
|
||||||
tkfor,
|
tkfor,
|
||||||
tkfunction,
|
tkfunction,
|
||||||
|
tkgeneric,
|
||||||
tkgoto,
|
tkgoto,
|
||||||
tkif,
|
tkif,
|
||||||
tkimplementation,
|
tkimplementation,
|
||||||
@ -125,6 +126,7 @@ type
|
|||||||
tkset,
|
tkset,
|
||||||
tkshl,
|
tkshl,
|
||||||
tkshr,
|
tkshr,
|
||||||
|
tkspecialize,
|
||||||
// tkstring,
|
// tkstring,
|
||||||
tkthen,
|
tkthen,
|
||||||
tkthreadvar,
|
tkthreadvar,
|
||||||
@ -298,6 +300,7 @@ const
|
|||||||
'finally',
|
'finally',
|
||||||
'for',
|
'for',
|
||||||
'function',
|
'function',
|
||||||
|
'generic',
|
||||||
'goto',
|
'goto',
|
||||||
'if',
|
'if',
|
||||||
'implementation',
|
'implementation',
|
||||||
@ -329,6 +332,7 @@ const
|
|||||||
'set',
|
'set',
|
||||||
'shl',
|
'shl',
|
||||||
'shr',
|
'shr',
|
||||||
|
'specialize',
|
||||||
// 'string',
|
// 'string',
|
||||||
'then',
|
'then',
|
||||||
'threadvar',
|
'threadvar',
|
||||||
|
Loading…
Reference in New Issue
Block a user