mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-14 10:11:10 +01:00
codetools: parse delphi generic inside generic
git-svn-id: trunk@56510 -
This commit is contained in:
parent
c1d0ee32a3
commit
60dce6d601
@ -146,7 +146,7 @@ type
|
|||||||
function GetExtraction(InUpperCase: boolean): string;
|
function GetExtraction(InUpperCase: boolean): string;
|
||||||
function ExtractStreamEndIsIdentChar: boolean;
|
function ExtractStreamEndIsIdentChar: boolean;
|
||||||
procedure ExtractNextAtom(AddAtom: boolean; Attr: TProcHeadAttributes);
|
procedure ExtractNextAtom(AddAtom: boolean; Attr: TProcHeadAttributes);
|
||||||
procedure CheckOperatorProc(IsOperator: boolean; var IsFunction: boolean); inline;
|
procedure CheckOperatorProc(var ParseAttr: TParseProcHeadAttributes); inline;
|
||||||
protected
|
protected
|
||||||
// parsing
|
// parsing
|
||||||
FLastCompilerMode: TCompilerMode;
|
FLastCompilerMode: TCompilerMode;
|
||||||
@ -172,7 +172,7 @@ type
|
|||||||
procedure ReadConstExpr;
|
procedure ReadConstExpr;
|
||||||
// types
|
// types
|
||||||
procedure ReadTypeNameAndDefinition;
|
procedure ReadTypeNameAndDefinition;
|
||||||
procedure ReadGenericParamList(Must: boolean);
|
procedure ReadGenericParamList(Must, AllowConstraints: boolean);
|
||||||
procedure ReadAttribute;
|
procedure ReadAttribute;
|
||||||
procedure FixLastAttributes;
|
procedure FixLastAttributes;
|
||||||
procedure ReadTypeReference(CreateNodes: boolean);
|
procedure ReadTypeReference(CreateNodes: boolean);
|
||||||
@ -345,13 +345,16 @@ end;
|
|||||||
{ TPascalParserTool }
|
{ TPascalParserTool }
|
||||||
|
|
||||||
// inline
|
// inline
|
||||||
procedure TPascalParserTool.CheckOperatorProc(IsOperator: boolean;
|
procedure TPascalParserTool.CheckOperatorProc(
|
||||||
var IsFunction: boolean);
|
var ParseAttr: TParseProcHeadAttributes);
|
||||||
begin
|
begin
|
||||||
if IsOperator then begin
|
if pphIsOperator in ParseAttr then begin
|
||||||
AtomIsCustomOperator(true,true,true);
|
AtomIsCustomOperator(true,true,true);
|
||||||
IsFunction:=not (UpAtomIs('INITIALIZE') or UpAtomIs('FINALIZE')
|
if (UpAtomIs('INITIALIZE') or UpAtomIs('FINALIZE')
|
||||||
or UpAtomIs('ADDREF') or UpAtomIs('COPY'));
|
or UpAtomIs('ADDREF') or UpAtomIs('COPY')) then
|
||||||
|
Exclude(ParseAttr,pphIsFunction)
|
||||||
|
else
|
||||||
|
Include(ParseAttr,pphIsFunction);
|
||||||
end else
|
end else
|
||||||
AtomIsIdentifierSaveE;
|
AtomIsIdentifierSaveE;
|
||||||
end;
|
end;
|
||||||
@ -1283,9 +1286,9 @@ function TPascalParserTool.KeyWordFuncClassMethod: boolean;
|
|||||||
enumerator <id>
|
enumerator <id>
|
||||||
compilerproc[:name]
|
compilerproc[:name]
|
||||||
}
|
}
|
||||||
var IsFunction, HasForwardModifier: boolean;
|
var
|
||||||
|
HasForwardModifier: boolean;
|
||||||
ParseAttr: TParseProcHeadAttributes;
|
ParseAttr: TParseProcHeadAttributes;
|
||||||
IsOperator: Boolean;
|
|
||||||
begin
|
begin
|
||||||
if (CurNode.Desc in AllClassSubSections)
|
if (CurNode.Desc in AllClassSubSections)
|
||||||
and (CurNode.Parent.Desc in (AllClassBaseSections+AllClassInterfaces)) then begin
|
and (CurNode.Parent.Desc in (AllClassBaseSections+AllClassInterfaces)) then begin
|
||||||
@ -1298,6 +1301,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
HasForwardModifier:=false;
|
HasForwardModifier:=false;
|
||||||
|
ParseAttr:=[pphIsMethodDecl,pphCreateNodes];
|
||||||
// create class method node
|
// create class method node
|
||||||
CreateChildNode;
|
CreateChildNode;
|
||||||
CurNode.Desc:=ctnProcedure;
|
CurNode.Desc:=ctnProcedure;
|
||||||
@ -1312,21 +1316,21 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
// read procedure head
|
// read procedure head
|
||||||
IsFunction:=UpAtomIs('FUNCTION');
|
if UpAtomIs('FUNCTION') then
|
||||||
IsOperator:=(not IsFunction) and UpAtomIs('OPERATOR');
|
Include(ParseAttr,pphIsFunction)
|
||||||
|
else if UpAtomIs('OPERATOR') then
|
||||||
|
Include(ParseAttr,pphIsOperator);
|
||||||
// read name
|
// read name
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
CheckOperatorProc(IsOperator,IsFunction);
|
|
||||||
// create node for procedure head
|
// create node for procedure head
|
||||||
CreateChildNode;
|
CreateChildNode;
|
||||||
CurNode.Desc:=ctnProcedureHead;
|
CurNode.Desc:=ctnProcedureHead;
|
||||||
|
CheckOperatorProc(ParseAttr);
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
|
if Scanner.CompilerMode=cmDELPHI then
|
||||||
|
ReadGenericParamList(false,true);
|
||||||
if (CurPos.Flag<>cafPoint) then begin
|
if (CurPos.Flag<>cafPoint) then begin
|
||||||
// read rest
|
// read rest
|
||||||
CurNode.SubDesc:=ctnsNeedJITParsing;
|
|
||||||
ParseAttr:=[pphIsMethodDecl];
|
|
||||||
if IsFunction then Include(ParseAttr,pphIsFunction);
|
|
||||||
if IsOperator then Include(ParseAttr,pphIsOperator);
|
|
||||||
ReadTilProcedureHeadEnd(ParseAttr,HasForwardModifier);
|
ReadTilProcedureHeadEnd(ParseAttr,HasForwardModifier);
|
||||||
end else begin
|
end else begin
|
||||||
// Method resolution clause (e.g. function Intf.Method = Method_Name)
|
// Method resolution clause (e.g. function Intf.Method = Method_Name)
|
||||||
@ -1742,8 +1746,6 @@ begin
|
|||||||
Result:=true;
|
Result:=true;
|
||||||
HasForwardModifier:=false;
|
HasForwardModifier:=false;
|
||||||
|
|
||||||
ReadGenericParamList(pphIsGeneric in ParseAttr);
|
|
||||||
|
|
||||||
if CurPos.Flag=cafRoundBracketOpen then begin
|
if CurPos.Flag=cafRoundBracketOpen then begin
|
||||||
Attr:=[];
|
Attr:=[];
|
||||||
if pphCreateNodes in ParseAttr then
|
if pphCreateNodes in ParseAttr then
|
||||||
@ -2719,17 +2721,15 @@ function TPascalParserTool.KeyWordFuncProc: boolean;
|
|||||||
// class function/procedure
|
// class function/procedure
|
||||||
// generic function/procedure
|
// generic function/procedure
|
||||||
var
|
var
|
||||||
ChildCreated: boolean;
|
HasForwardModifier, IsClassProc: boolean;
|
||||||
IsFunction, HasForwardModifier, IsClassProc, IsOperator, IsMethod,
|
|
||||||
IsGeneric: boolean;
|
|
||||||
ProcNode: TCodeTreeNode;
|
ProcNode: TCodeTreeNode;
|
||||||
ParseAttr: TParseProcHeadAttributes;
|
ParseAttr: TParseProcHeadAttributes;
|
||||||
begin
|
begin
|
||||||
|
ParseAttr:=[pphCreateNodes];
|
||||||
if UpAtomIs('GENERIC') then begin
|
if UpAtomIs('GENERIC') then begin
|
||||||
IsGeneric:=true;
|
Include(ParseAttr,pphIsGeneric);
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
end else
|
end;
|
||||||
IsGeneric:=false;
|
|
||||||
if UpAtomIs('CLASS') then begin
|
if UpAtomIs('CLASS') then begin
|
||||||
if not (CurSection in [ctnImplementation]+AllSourceTypes) then
|
if not (CurSection in [ctnImplementation]+AllSourceTypes) then
|
||||||
SaveRaiseStringExpectedButAtomFound(20170421195603,ctsIdentifier);
|
SaveRaiseStringExpectedButAtomFound(20170421195603,ctsIdentifier);
|
||||||
@ -2742,54 +2742,44 @@ begin
|
|||||||
ctsProcedureOrFunctionOrConstructorOrDestructor);
|
ctsProcedureOrFunctionOrConstructorOrDestructor);
|
||||||
end else
|
end else
|
||||||
IsClassProc:=false;
|
IsClassProc:=false;
|
||||||
ChildCreated:=true;
|
// create node for procedure
|
||||||
if ChildCreated then begin
|
CreateChildNode;
|
||||||
// create node for procedure
|
if IsClassProc then
|
||||||
CreateChildNode;
|
CurNode.StartPos:=LastAtoms.GetPriorAtom.StartPos;
|
||||||
if IsClassProc then
|
ProcNode:=CurNode;
|
||||||
CurNode.StartPos:=LastAtoms.GetPriorAtom.StartPos;
|
ProcNode.Desc:=ctnProcedure;
|
||||||
ProcNode:=CurNode;
|
if CurSection=ctnInterface then
|
||||||
ProcNode.Desc:=ctnProcedure;
|
ProcNode.SubDesc:=ctnsForwardDeclaration;
|
||||||
if CurSection=ctnInterface then
|
if UpAtomIs('FUNCTION') then
|
||||||
ProcNode.SubDesc:=ctnsForwardDeclaration;
|
Include(ParseAttr,pphIsFunction)
|
||||||
end;
|
else if UpAtomIs('OPERATOR') then
|
||||||
IsFunction:=UpAtomIs('FUNCTION');
|
Include(ParseAttr,pphIsOperator);
|
||||||
IsOperator:=(not IsFunction) and UpAtomIs('OPERATOR');
|
|
||||||
IsMethod:=False;
|
|
||||||
ReadNextAtom;// read first atom of head (= name/operator + parameterlist + resulttype;)
|
ReadNextAtom;// read first atom of head (= name/operator + parameterlist + resulttype;)
|
||||||
CheckOperatorProc(IsOperator,IsFunction);
|
// create node for procedure head
|
||||||
if ChildCreated then begin
|
CreateChildNode;
|
||||||
// create node for procedure head
|
CurNode.Desc:=ctnProcedureHead;
|
||||||
CreateChildNode;
|
CheckOperatorProc(ParseAttr);
|
||||||
CurNode.Desc:=ctnProcedureHead;
|
|
||||||
CurNode.SubDesc:=ctnsNeedJITParsing;
|
|
||||||
end;
|
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
|
ReadGenericParamList(false,true);
|
||||||
if (CurSection<>ctnInterface) then begin
|
if (CurSection<>ctnInterface) then begin
|
||||||
while (CurPos.Flag=cafPoint) do begin
|
while (CurPos.Flag=cafPoint) do begin
|
||||||
// read procedure name of a class method (the name after the . )
|
// read procedure name of a class method (the name after the . )
|
||||||
IsMethod:=True;
|
Include(ParseAttr,pphIsMethodBody);
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
CheckOperatorProc(IsOperator,IsFunction);
|
CheckOperatorProc(ParseAttr);
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
|
ReadGenericParamList(false,true);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
// read rest of procedure head
|
// read rest of procedure head
|
||||||
HasForwardModifier:=false;
|
HasForwardModifier:=false;
|
||||||
ParseAttr:=[];
|
|
||||||
if IsFunction then Include(ParseAttr,pphIsFunction);
|
|
||||||
if IsOperator then Include(ParseAttr,pphIsOperator);
|
|
||||||
if IsMethod then Include(ParseAttr,pphIsMethodBody);
|
|
||||||
if IsGeneric then Include(ParseAttr,pphIsGeneric);
|
|
||||||
ReadTilProcedureHeadEnd(ParseAttr,HasForwardModifier);
|
ReadTilProcedureHeadEnd(ParseAttr,HasForwardModifier);
|
||||||
if ChildCreated then begin
|
if HasForwardModifier then
|
||||||
if HasForwardModifier then
|
ProcNode.SubDesc:=ctnsForwardDeclaration;
|
||||||
ProcNode.SubDesc:=ctnsForwardDeclaration;
|
// close head
|
||||||
// close head
|
CurNode.EndPos:=CurPos.EndPos;
|
||||||
CurNode.EndPos:=CurPos.EndPos;
|
EndChildNode;
|
||||||
EndChildNode;
|
if ((ProcNode.SubDesc and ctnsForwardDeclaration)>0) then
|
||||||
end;
|
|
||||||
if ChildCreated and ((ProcNode.SubDesc and ctnsForwardDeclaration)>0) then
|
|
||||||
begin
|
begin
|
||||||
// close method
|
// close method
|
||||||
CurNode.EndPos:=CurPos.EndPos;
|
CurNode.EndPos:=CurPos.EndPos;
|
||||||
@ -4081,7 +4071,7 @@ begin
|
|||||||
//debugln(['TPascalParserTool.ReadTypeNameAndDefinition Name="',copy(Src,NamePos.StartPos,NamePos.EndPos-NamePos.StartPos),'"']);
|
//debugln(['TPascalParserTool.ReadTypeNameAndDefinition Name="',copy(Src,NamePos.StartPos,NamePos.EndPos-NamePos.StartPos),'"']);
|
||||||
EndChildNode;
|
EndChildNode;
|
||||||
// read generic parameter list
|
// read generic parameter list
|
||||||
ReadGenericParamList(IsGeneric);
|
ReadGenericParamList(IsGeneric,true);
|
||||||
end;
|
end;
|
||||||
// read =
|
// read =
|
||||||
if (CurPos.Flag<>cafEqual) then
|
if (CurPos.Flag<>cafEqual) then
|
||||||
@ -4100,7 +4090,7 @@ begin
|
|||||||
EndChildNode;
|
EndChildNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPascalParserTool.ReadGenericParamList(Must: boolean);
|
procedure TPascalParserTool.ReadGenericParamList(Must, AllowConstraints: boolean);
|
||||||
{ At start cursor is on <
|
{ At start cursor is on <
|
||||||
At end cursor is on atom after >
|
At end cursor is on atom after >
|
||||||
|
|
||||||
@ -4144,7 +4134,7 @@ begin
|
|||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
end else if AtomIsChar('>') then begin
|
end else if AtomIsChar('>') then begin
|
||||||
break;
|
break;
|
||||||
end else if CurPos.Flag=cafColon then begin
|
end else if AllowConstraints and (CurPos.Flag=cafColon) then begin
|
||||||
// read constraints
|
// read constraints
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if CurPos.Flag<>cafNone then begin
|
if CurPos.Flag<>cafNone then begin
|
||||||
@ -4183,9 +4173,11 @@ begin
|
|||||||
// close ctnGenericParameter
|
// close ctnGenericParameter
|
||||||
EndChildNode;
|
EndChildNode;
|
||||||
end else begin
|
end else begin
|
||||||
if AtomIs('>=') then
|
if AtomIs('>=') then begin
|
||||||
// this is the rare case where >= are two separate atoms
|
// this is the rare case where >= are two separate atoms
|
||||||
dec(CurPos.EndPos);
|
dec(CurPos.EndPos);
|
||||||
|
LastAtoms.SetCurrent(CurPos);
|
||||||
|
end;
|
||||||
if not AtomIsChar('>') then
|
if not AtomIsChar('>') then
|
||||||
SaveRaiseCharExpectedButAtomFound(20170421195745,'>');
|
SaveRaiseCharExpectedButAtomFound(20170421195745,'>');
|
||||||
end;
|
end;
|
||||||
@ -6020,9 +6012,8 @@ end;
|
|||||||
|
|
||||||
procedure TPascalParserTool.BuildSubTreeForProcHead(ProcNode: TCodeTreeNode);
|
procedure TPascalParserTool.BuildSubTreeForProcHead(ProcNode: TCodeTreeNode);
|
||||||
var
|
var
|
||||||
HasForwardModifier, IsFunction, IsOperator, IsMethod: boolean;
|
HasForwardModifier, IsFunction: boolean;
|
||||||
ParseAttr: TParseProcHeadAttributes;
|
ParseAttr: TParseProcHeadAttributes;
|
||||||
IsProcType, IsGeneric: Boolean;
|
|
||||||
ProcHeadNode: TCodeTreeNode;
|
ProcHeadNode: TCodeTreeNode;
|
||||||
begin
|
begin
|
||||||
if ProcNode.Desc=ctnProcedureHead then ProcNode:=ProcNode.Parent;
|
if ProcNode.Desc=ctnProcedureHead then ProcNode:=ProcNode.Parent;
|
||||||
@ -6053,48 +6044,49 @@ begin
|
|||||||
RaiseNodeParserError(ProcHeadNode);
|
RaiseNodeParserError(ProcHeadNode);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
ParseAttr:=[pphCreateNodes];
|
||||||
try
|
try
|
||||||
IsMethod:=(ProcNode.Parent<>nil) and (ProcNode.Parent.Desc in (AllClasses+AllClassSections));
|
if (ProcNode.Parent<>nil) and (ProcNode.Parent.Desc in (AllClasses+AllClassSections)) then
|
||||||
|
Include(ParseAttr,pphIsMethodDecl);
|
||||||
MoveCursorToNodeStart(ProcNode);
|
MoveCursorToNodeStart(ProcNode);
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if (Scanner.CompilerMode in [cmOBJFPC,cmFPC]) and UpAtomIs('GENERIC') then begin
|
if (Scanner.CompilerMode in [cmOBJFPC,cmFPC]) and UpAtomIs('GENERIC') then begin
|
||||||
IsGeneric:=true;
|
Include(ParseAttr,pphIsGeneric);
|
||||||
CurNode.Desc:=ctnGenericType;
|
CurNode.Desc:=ctnGenericType;
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
end else
|
end;
|
||||||
IsGeneric:=false;
|
|
||||||
if UpAtomIs('CLASS') then
|
if UpAtomIs('CLASS') then
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
IsFunction:=UpAtomIs('FUNCTION');
|
if UpAtomIs('FUNCTION') then begin
|
||||||
IsOperator:=(not IsFunction) and UpAtomIs('OPERATOR');
|
IsFunction:=true;
|
||||||
IsProcType:=ProcNode.Desc=ctnProcedureType;
|
Include(ParseAttr,pphIsFunction);
|
||||||
|
end else
|
||||||
|
IsFunction:=false;
|
||||||
|
if (not IsFunction) and UpAtomIs('OPERATOR') then
|
||||||
|
Include(ParseAttr,pphIsOperator);
|
||||||
|
if ProcNode.Desc=ctnProcedureType then
|
||||||
|
Include(ParseAttr,pphIsType);
|
||||||
// read procedure head (= [name[<parameters>]] + parameterlist + resulttype;)
|
// read procedure head (= [name[<parameters>]] + parameterlist + resulttype;)
|
||||||
ReadNextAtom;// read first atom of head
|
ReadNextAtom;// read first atom of head
|
||||||
CurNode:=ProcHeadNode;
|
CurNode:=ProcHeadNode;
|
||||||
if CurNode=nil then
|
if CurNode=nil then
|
||||||
if IsProcType then
|
if pphIsType in ParseAttr then
|
||||||
SaveRaiseCharExpectedButAtomFound(20170421195925,';')
|
SaveRaiseCharExpectedButAtomFound(20170421195925,';')
|
||||||
else
|
else
|
||||||
SaveRaiseStringExpectedButAtomFound(20170421195928,'identifier');
|
SaveRaiseStringExpectedButAtomFound(20170421195928,'identifier');
|
||||||
ProcHeadNode.SubDesc:=ProcHeadNode.SubDesc and (not ctnsNeedJITParsing);
|
ProcHeadNode.SubDesc:=ProcHeadNode.SubDesc and (not ctnsNeedJITParsing);
|
||||||
|
|
||||||
if not IsProcType then begin
|
if not (pphIsType in ParseAttr) then begin
|
||||||
// read procedure name of a class method (the name after the . )
|
// read procedure name of a class method (the name after the . )
|
||||||
repeat
|
repeat
|
||||||
CheckOperatorProc(IsOperator,IsFunction);
|
CheckOperatorProc(ParseAttr);
|
||||||
ReadNextAtom;
|
ReadGenericParamList(false,false);
|
||||||
if CurPos.Flag<>cafPoint then break;
|
if CurPos.Flag<>cafPoint then break;
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
until false;
|
until false;
|
||||||
end;
|
end;
|
||||||
// read rest of procedure head and build nodes
|
// read rest of procedure head and build nodes
|
||||||
HasForwardModifier:=false;
|
HasForwardModifier:=false;
|
||||||
ParseAttr:=[pphCreateNodes];
|
|
||||||
if IsMethod then Include(ParseAttr,pphIsMethodDecl);
|
|
||||||
if IsFunction then Include(ParseAttr,pphIsFunction);
|
|
||||||
if IsOperator then Include(ParseAttr,pphIsOperator);
|
|
||||||
if IsProcType then Include(ParseAttr,pphIsType);
|
|
||||||
if IsGeneric then Include(ParseAttr,pphIsGeneric);
|
|
||||||
ReadTilProcedureHeadEnd(ParseAttr,HasForwardModifier);
|
ReadTilProcedureHeadEnd(ParseAttr,HasForwardModifier);
|
||||||
except
|
except
|
||||||
{$IFDEF ShowIgnoreErrorAfter}
|
{$IFDEF ShowIgnoreErrorAfter}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user