mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-22 05:29:26 +02:00
fcl-passrc: fixed parsing type helper() for, fixed parsing record helper: atype end
git-svn-id: trunk@40869 -
This commit is contained in:
parent
1eccbf34f1
commit
38f158bb69
@ -733,7 +733,8 @@ type
|
|||||||
TPasGenericTemplateType = Class(TPasType);
|
TPasGenericTemplateType = Class(TPasType);
|
||||||
|
|
||||||
TPasObjKind = (
|
TPasObjKind = (
|
||||||
okObject, okClass, okInterface, okGeneric,
|
okObject, okClass, okInterface,
|
||||||
|
okGeneric, // MG: what is okGeneric?
|
||||||
// okSpecialize removed in FPC 3.1.1
|
// okSpecialize removed in FPC 3.1.1
|
||||||
okClassHelper,okRecordHelper,okTypeHelper,
|
okClassHelper,okRecordHelper,okTypeHelper,
|
||||||
okDispInterface);
|
okDispInterface);
|
||||||
@ -758,7 +759,7 @@ type
|
|||||||
ObjKind: TPasObjKind;
|
ObjKind: TPasObjKind;
|
||||||
AncestorType: TPasType; // TPasClassType or TPasUnresolvedTypeRef or TPasAliasType or TPasTypeAliasType
|
AncestorType: TPasType; // TPasClassType or TPasUnresolvedTypeRef or TPasAliasType or TPasTypeAliasType
|
||||||
// Note: AncestorType can be nil even though it has a default ancestor
|
// Note: AncestorType can be nil even though it has a default ancestor
|
||||||
HelperForType: TPasType; // TPasClassType or TPasUnresolvedTypeRef
|
HelperForType: TPasType; // any type, except helper
|
||||||
IsForward: Boolean;
|
IsForward: Boolean;
|
||||||
IsExternal : Boolean;
|
IsExternal : Boolean;
|
||||||
IsShortDefinition: Boolean;//class(anchestor); without end
|
IsShortDefinition: Boolean;//class(anchestor); without end
|
||||||
|
@ -72,7 +72,7 @@ const
|
|||||||
nParserNotAProcToken = 2026;
|
nParserNotAProcToken = 2026;
|
||||||
nRangeExpressionExpected = 2027;
|
nRangeExpressionExpected = 2027;
|
||||||
nParserExpectCase = 2028;
|
nParserExpectCase = 2028;
|
||||||
nParserHelperNotAllowed = 2029;
|
// free 2029;
|
||||||
nLogStartImplementation = 2030;
|
nLogStartImplementation = 2030;
|
||||||
nLogStartInterface = 2031;
|
nLogStartInterface = 2031;
|
||||||
nParserNoConstructorAllowed = 2032;
|
nParserNoConstructorAllowed = 2032;
|
||||||
@ -132,7 +132,7 @@ resourcestring
|
|||||||
SParserNotAProcToken = 'Not a procedure or function token';
|
SParserNotAProcToken = 'Not a procedure or function token';
|
||||||
SRangeExpressionExpected = 'Range expression expected';
|
SRangeExpressionExpected = 'Range expression expected';
|
||||||
SParserExpectCase = 'Case label expression expected';
|
SParserExpectCase = 'Case label expression expected';
|
||||||
SParserHelperNotAllowed = 'Helper objects not allowed for "%s"';
|
// free for 2029
|
||||||
SLogStartImplementation = 'Start parsing implementation section.';
|
SLogStartImplementation = 'Start parsing implementation section.';
|
||||||
SLogStartInterface = 'Start parsing interface section';
|
SLogStartInterface = 'Start parsing interface section';
|
||||||
SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Record helpers';
|
SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Record helpers';
|
||||||
@ -1735,12 +1735,40 @@ begin
|
|||||||
tkInterface:
|
tkInterface:
|
||||||
Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface);
|
Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface);
|
||||||
tkSpecialize: Result:=ParseSpecializeType(Parent,TypeName);
|
tkSpecialize: Result:=ParseSpecializeType(Parent,TypeName);
|
||||||
tkClass: Result := ParseClassDecl(Parent, NamePos, TypeName, okClass, PM, GenericArgs);
|
tkClass:
|
||||||
|
begin
|
||||||
|
isHelper:=false;
|
||||||
|
NextToken;
|
||||||
|
if CurTokenIsIdentifier('Helper') then
|
||||||
|
begin
|
||||||
|
// class helper: atype end;
|
||||||
|
// class helper for atype end;
|
||||||
|
NextToken;
|
||||||
|
isHelper:=CurToken in [tkfor,tkBraceOpen];
|
||||||
|
UnGetToken;
|
||||||
|
end;
|
||||||
|
UngetToken;
|
||||||
|
if isHelper then
|
||||||
|
Result:=ParseClassDecl(Parent,NamePos,TypeName,okClassHelper,PM, GenericArgs)
|
||||||
|
else
|
||||||
|
Result:=ParseClassDecl(Parent, NamePos, TypeName, okClass, PM, GenericArgs);
|
||||||
|
end;
|
||||||
tkType:
|
tkType:
|
||||||
|
begin
|
||||||
|
isHelper:=false;
|
||||||
|
if msTypeHelpers in Scanner.CurrentModeSwitches then
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
isHelper:=CurTokenIsIdentifier('helper');
|
if CurTokenIsIdentifier('helper') then
|
||||||
|
begin
|
||||||
|
// atype = type helper;
|
||||||
|
// atype = type helper for atype end;
|
||||||
|
NextToken;
|
||||||
|
isHelper:=CurToken in [tkfor,tkBraceOpen];
|
||||||
UnGetToken;
|
UnGetToken;
|
||||||
|
end;
|
||||||
|
UnGetToken;
|
||||||
|
end;
|
||||||
if isHelper then
|
if isHelper then
|
||||||
Result:=ParseClassDecl(Parent,NamePos,TypeName,okTypeHelper,PM)
|
Result:=ParseClassDecl(Parent,NamePos,TypeName,okTypeHelper,PM)
|
||||||
else
|
else
|
||||||
@ -1769,16 +1797,20 @@ begin
|
|||||||
tkRecord:
|
tkRecord:
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
|
isHelper:=false;
|
||||||
if CurTokenIsIdentifier('Helper') then
|
if CurTokenIsIdentifier('Helper') then
|
||||||
begin
|
begin
|
||||||
|
// record helper: atype end;
|
||||||
|
// record helper for atype end;
|
||||||
|
NextToken;
|
||||||
|
isHelper:=CurToken in [tkfor,tkBraceOpen];
|
||||||
UnGetToken;
|
UnGetToken;
|
||||||
Result:=ParseClassDecl(Parent,NamePos,TypeName,okRecordHelper,PM);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
UnGetToken;
|
|
||||||
Result := ParseRecordDecl(Parent,NamePos,TypeName,PM);
|
|
||||||
end;
|
end;
|
||||||
|
UngetToken;
|
||||||
|
if isHelper then
|
||||||
|
Result:=ParseClassDecl(Parent,NamePos,TypeName,okRecordHelper,PM)
|
||||||
|
else
|
||||||
|
Result:=ParseRecordDecl(Parent,NamePos,TypeName,PM);
|
||||||
end;
|
end;
|
||||||
tkNumber,tkMinus,tkChar:
|
tkNumber,tkMinus,tkChar:
|
||||||
begin
|
begin
|
||||||
@ -6797,8 +6829,13 @@ begin
|
|||||||
if (CurToken=tkBraceOpen) then
|
if (CurToken=tkBraceOpen) then
|
||||||
begin
|
begin
|
||||||
// read ancestor and interfaces
|
// read ancestor and interfaces
|
||||||
|
if (AType.ObjKind=okRecordHelper)
|
||||||
|
and ([msTypeHelpers,msDelphi]*Scanner.CurrentModeSwitches=[msDelphi]) then
|
||||||
|
// Delphi does not support ancestors in record helpers
|
||||||
|
CheckToken(tkend);
|
||||||
NextToken;
|
NextToken;
|
||||||
AType.AncestorType := ParseTypeReference(AType,false,Expr);
|
AType.AncestorType := ParseTypeReference(AType,false,Expr);
|
||||||
|
if AType.ObjKind in [okClass,okGeneric] then
|
||||||
while CurToken=tkComma do
|
while CurToken=tkComma do
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
@ -6808,7 +6845,7 @@ begin
|
|||||||
NextToken;
|
NextToken;
|
||||||
AType.IsShortDefinition:=(CurToken=tkSemicolon);
|
AType.IsShortDefinition:=(CurToken=tkSemicolon);
|
||||||
end;
|
end;
|
||||||
if (AType.ObjKind in [okClassHelper,okRecordHelper]) then
|
if (AType.ObjKind in [okClassHelper,okRecordHelper,okTypeHelper]) then
|
||||||
begin
|
begin
|
||||||
CheckToken(tkfor);
|
CheckToken(tkfor);
|
||||||
NextToken;
|
NextToken;
|
||||||
@ -6837,12 +6874,10 @@ function TPasParser.ParseClassDecl(Parent: TPasElement;
|
|||||||
|
|
||||||
Var
|
Var
|
||||||
ok: Boolean;
|
ok: Boolean;
|
||||||
FT : TPasType;
|
|
||||||
AExternalNameSpace,AExternalName : String;
|
AExternalNameSpace,AExternalName : String;
|
||||||
PCT:TPasClassType;
|
PCT:TPasClassType;
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
FT:=Nil;
|
|
||||||
if (AObjKind = okClass) and (CurToken = tkOf) then
|
if (AObjKind = okClass) and (CurToken = tkOf) then
|
||||||
begin
|
begin
|
||||||
Result := TPasClassOfType(CreateElement(TPasClassOfType, AClassName,
|
Result := TPasClassOfType(CreateElement(TPasClassOfType, AClassName,
|
||||||
@ -6860,7 +6895,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if ((AObjKind in [okClass,OKInterface]) and (msExternalClass in CurrentModeswitches)
|
if ((AObjKind in [okClass,okInterface]) and (msExternalClass in CurrentModeswitches)
|
||||||
and CurTokenIsIdentifier('external')) then
|
and CurTokenIsIdentifier('external')) then
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
@ -6882,19 +6917,10 @@ begin
|
|||||||
AExternalNameSpace:='';
|
AExternalNameSpace:='';
|
||||||
AExternalName:='';
|
AExternalName:='';
|
||||||
end;
|
end;
|
||||||
if (CurTokenIsIdentifier('Helper')) then
|
if AObjKind in [okClassHelper,okRecordHelper,okTypeHelper] then
|
||||||
begin
|
begin
|
||||||
if Not (AObjKind in [okClass,okTypeHelper,okRecordHelper]) then
|
if not CurTokenIsIdentifier('Helper') then
|
||||||
ParseExc(nParserHelperNotAllowed,SParserHelperNotAllowed,[ObjKindNames[AObjKind]]);
|
ParseExcSyntaxError;
|
||||||
Case AObjKind of
|
|
||||||
okClass:
|
|
||||||
AObjKind:=okClassHelper;
|
|
||||||
okTypeHelper:
|
|
||||||
begin
|
|
||||||
ExpectToken(tkFor);
|
|
||||||
FT:=ParseType(Parent,CurSourcePos,'',False);
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
NextToken;
|
NextToken;
|
||||||
end;
|
end;
|
||||||
PCT := TPasClassType(CreateElement(TPasClassType, AClassName,
|
PCT := TPasClassType(CreateElement(TPasClassType, AClassName,
|
||||||
@ -6902,7 +6928,7 @@ begin
|
|||||||
Result:=PCT;
|
Result:=PCT;
|
||||||
ok:=false;
|
ok:=false;
|
||||||
try
|
try
|
||||||
PCT.HelperForType:=FT;
|
PCT.HelperForType:=nil;
|
||||||
PCT.IsExternal:=(AExternalName<>'');
|
PCT.IsExternal:=(AExternalName<>'');
|
||||||
if AExternalName<>'' then
|
if AExternalName<>'' then
|
||||||
PCT.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
|
PCT.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
|
||||||
|
@ -165,6 +165,7 @@ type
|
|||||||
Procedure TestReferencePointer;
|
Procedure TestReferencePointer;
|
||||||
Procedure TestInvalidColon;
|
Procedure TestInvalidColon;
|
||||||
Procedure TestTypeHelper;
|
Procedure TestTypeHelper;
|
||||||
|
Procedure TestTypeHelperWithParent;
|
||||||
procedure TestPointerReference;
|
procedure TestPointerReference;
|
||||||
Procedure TestPointerKeyWord;
|
Procedure TestPointerKeyWord;
|
||||||
end;
|
end;
|
||||||
@ -3562,9 +3563,16 @@ end;
|
|||||||
|
|
||||||
procedure TTestTypeParser.TestTypeHelper;
|
procedure TTestTypeParser.TestTypeHelper;
|
||||||
begin
|
begin
|
||||||
|
Scanner.CurrentModeSwitches:=Scanner.CurrentModeSwitches+[msTypeHelpers];
|
||||||
ParseType('Type Helper for AnsiString end',TPasClassType,'');
|
ParseType('Type Helper for AnsiString end',TPasClassType,'');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestTypeParser.TestTypeHelperWithParent;
|
||||||
|
begin
|
||||||
|
Scanner.CurrentModeSwitches:=Scanner.CurrentModeSwitches+[msTypeHelpers];
|
||||||
|
ParseType('Type Helper(TOtherHelper) for AnsiString end',TPasClassType,'');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestTypeParser.TestPointerReference;
|
procedure TTestTypeParser.TestPointerReference;
|
||||||
begin
|
begin
|
||||||
Add('Type');
|
Add('Type');
|
||||||
|
@ -86,7 +86,7 @@ Works:
|
|||||||
- array of record-const
|
- array of record-const
|
||||||
- skip clone record of new record
|
- skip clone record of new record
|
||||||
- use rtl.recNewT to create a record type
|
- use rtl.recNewT to create a record type
|
||||||
- use TRec.$new to instantiate records
|
- use TRec.$new to instantiate records, using Object.create to instantiate
|
||||||
- advanced records:
|
- advanced records:
|
||||||
- public, private, strict private
|
- public, private, strict private
|
||||||
- class var
|
- class var
|
||||||
@ -94,6 +94,8 @@ Works:
|
|||||||
- sub types
|
- sub types
|
||||||
- functions
|
- functions
|
||||||
- properties
|
- properties
|
||||||
|
- class properties
|
||||||
|
- default property
|
||||||
- rtti
|
- rtti
|
||||||
- constructor
|
- constructor
|
||||||
- assign: copy values, do not create new JS object, needed by ^record
|
- assign: copy values, do not create new JS object, needed by ^record
|
||||||
@ -376,16 +378,9 @@ Works:
|
|||||||
- move all local types to global
|
- move all local types to global
|
||||||
|
|
||||||
ToDos:
|
ToDos:
|
||||||
|
- class helpers, type helpers, record helpers, array helpers
|
||||||
- cmd line param to set modeswitch
|
- cmd line param to set modeswitch
|
||||||
- Result:=inherited;
|
- Result:=inherited;
|
||||||
- move local types to unit scope
|
|
||||||
- records:
|
|
||||||
- use Object.create to instantiate simple records
|
|
||||||
- advanced records:
|
|
||||||
- class properties
|
|
||||||
- default property
|
|
||||||
- constructor
|
|
||||||
- rtti
|
|
||||||
- bug: DoIt(typeinfo(i)) where DoIt is in another unit and has TTypeInfo
|
- bug: DoIt(typeinfo(i)) where DoIt is in another unit and has TTypeInfo
|
||||||
- $OPTIMIZATION ON|OFF
|
- $OPTIMIZATION ON|OFF
|
||||||
- $optimization REMOVEEMPTYPROCS
|
- $optimization REMOVEEMPTYPROCS
|
||||||
@ -445,7 +440,6 @@ ToDos:
|
|||||||
-O2 CSE
|
-O2 CSE
|
||||||
-O3 DFA
|
-O3 DFA
|
||||||
- objects
|
- objects
|
||||||
- class helpers, type helpers, record helpers, array helpers
|
|
||||||
- generics
|
- generics
|
||||||
- operator overloading
|
- operator overloading
|
||||||
- operator enumerator
|
- operator enumerator
|
||||||
|
Loading…
Reference in New Issue
Block a user