fcl-passrc: fixed parsing type helper() for, fixed parsing record helper: atype end

git-svn-id: trunk@40869 -
This commit is contained in:
Mattias Gaertner 2019-01-14 22:06:50 +00:00
parent 1eccbf34f1
commit 38f158bb69
4 changed files with 75 additions and 46 deletions

View File

@ -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

View File

@ -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,'''');

View File

@ -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');

View File

@ -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