MG: find declaration of class ancestor, result type, default property, array, indexed pointer

git-svn-id: trunk@602 -
This commit is contained in:
lazarus 2002-01-16 17:22:11 +00:00
parent eb66cd1363
commit 147fbd54ee
4 changed files with 317 additions and 97 deletions

View File

@ -52,55 +52,56 @@ const
// CodeTreeNodeDescriptors // CodeTreeNodeDescriptors
ctnNone = 0; ctnNone = 0;
ctnClass = 1; ctnProgram = 1;
ctnClassPublished = 2; ctnPackage = 2;
ctnClassPrivate = 3; ctnLibrary = 3;
ctnClassProtected = 4; ctnUnit = 4;
ctnClassPublic = 5; ctnInterface = 5;
ctnImplementation = 6;
ctnInitialization = 7;
ctnFinalization = 8;
ctnProcedure = 10; ctnTypeSection = 10;
ctnProcedureHead = 11; ctnVarSection = 11;
ctnParameterList = 12; ctnConstSection = 12;
ctnResStrSection = 13;
ctnUsesSection = 14;
ctnBeginBlock = 20; ctnTypeDefinition = 20;
ctnAsmBlock = 21; ctnVarDefinition = 21;
ctnConstDefinition = 22;
ctnProgram = 30; ctnClass = 30;
ctnPackage = 31; ctnClassPublished = 31;
ctnLibrary = 32; ctnClassPrivate = 32;
ctnUnit = 33; ctnClassProtected = 33;
ctnInterface = 34; ctnClassPublic = 34;
ctnImplementation = 35;
ctnInitialization = 36;
ctnFinalization = 37;
ctnTypeSection = 40; ctnProperty = 40;
ctnVarSection = 41;
ctnConstSection = 42;
ctnResStrSection = 43;
ctnUsesSection = 44;
ctnTypeDefinition = 50;
ctnVarDefinition = 51;
ctnConstDefinition = 52;
ctnProperty = 60;
ctnIdentifier = 70; ctnProcedure = 50;
ctnArrayType = 71; ctnProcedureHead = 51;
ctnRecordType = 72; ctnParameterList = 52;
ctnRecordCase = 73;
ctnRecordVariant = 74; ctnIdentifier = 60;
ctnProcedureType = 75; ctnArrayType = 61;
ctnSetType = 76; ctnOfConstType = 62;
ctnRangeType = 77; ctnRecordType = 63;
ctnEnumType = 78; ctnRecordCase = 64;
ctnLabelType = 79; ctnRecordVariant = 65;
ctnTypeType = 80; ctnProcedureType = 66;
ctnFileType = 81; ctnSetType = 67;
ctnPointerType = 82; ctnRangeType = 68;
ctnClassOfType = 83; ctnEnumType = 69;
ctnLabelType = 70;
ctnTypeType = 71;
ctnFileType = 72;
ctnPointerType = 73;
ctnClassOfType = 74;
ctnBeginBlock = 80;
ctnAsmBlock = 81;
ctnWithVariable = 90; ctnWithVariable = 90;
ctnWithStatement = 91; ctnWithStatement = 91;
@ -123,8 +124,9 @@ const
// CodeTreeNodeSubDescriptors // CodeTreeNodeSubDescriptors
ctnsNone = 0; ctnsNone = 0;
ctnsForwardDeclaration = 1; ctnsForwardDeclaration = 1;
ctnsProcHeadNodesCreated = 2;
type type
TCodeTreeNode = class TCodeTreeNode = class
@ -548,7 +550,7 @@ begin
FCount:=0; FCount:=0;
FAllocatedNodes:=0; FAllocatedNodes:=0;
FFreedNodes:=0; FFreedNodes:=0;
FMinFree:=10000; FMinFree:=100000;
FMaxFreeRatio:=8; // 1:1 FMaxFreeRatio:=8; // 1:1
end; end;
@ -626,7 +628,7 @@ begin
FFirstFree:=nil; FFirstFree:=nil;
FFreeCount:=0; FFreeCount:=0;
FCount:=0; FCount:=0;
FMinFree:=10000; FMinFree:=20000;
FMaxFreeRatio:=8; // 1:1 FMaxFreeRatio:=8; // 1:1
end; end;

View File

@ -224,6 +224,10 @@ begin
// CodeTreeNodeSubDescriptors // CodeTreeNodeSubDescriptors
ctnsForwardDeclaration : Result:='Forward'; ctnsForwardDeclaration : Result:='Forward';
end; end;
ctnProcedureHead:
case SubDesc of
ctnsProcHeadNodesCreated: Result:='Nodes Created';
end;
end; end;
end; end;

View File

@ -596,13 +596,21 @@ if (ContextNode.Desc=ctnClass) then
ctnInterface, ctnImplementation, ctnInterface, ctnImplementation,
ctnClassPublic, ctnClassPrivate, ctnClassProtected, ctnClassPublished, ctnClassPublic, ctnClassPrivate, ctnClassProtected, ctnClassPublished,
ctnClass, ctnClass,
ctnRecordType, ctnRecordCase, ctnRecordVariant: ctnRecordType, ctnRecordCase, ctnRecordVariant,
ctnParameterList:
if (ContextNode.LastChild<>nil) then begin if (ContextNode.LastChild<>nil) then begin
if not (fdfSearchForward in Params.Flags) then if not (fdfSearchForward in Params.Flags) then
ContextNode:=ContextNode.LastChild ContextNode:=ContextNode.LastChild
else else
ContextNode:=ContextNode.FirstChild; ContextNode:=ContextNode.FirstChild;
end; end;
ctnProcedureHead:
begin
BuildSubTreeForProcHead(ContextNode);
if ContextNode.FirstChild<>nil then
ContextNode:=ContextNode.FirstChild;
end;
ctnTypeDefinition, ctnVarDefinition, ctnConstDefinition, ctnEnumType: ctnTypeDefinition, ctnVarDefinition, ctnConstDefinition, ctnEnumType:
begin begin
@ -645,15 +653,21 @@ writeln(' Definition Identifier found=',copy(Src,ContextNode.StartPos,Params.Id
ctnProperty: ctnProperty:
begin begin
MoveCursorToNodeStart(ContextNode); if (Src[Params.IdentifierStartPos]<>'[') then begin
ReadNextAtom; // read keyword 'property' MoveCursorToNodeStart(ContextNode);
ReadNextAtom; // read name ReadNextAtom; // read keyword 'property'
if CompareSrcIdentifiers(Params.IdentifierStartPos,CurPos.StartPos) ReadNextAtom; // read name
then begin if CompareSrcIdentifiers(Params.IdentifierStartPos,CurPos.StartPos)
// identifier found then begin
Result:=true; // identifier found
Params.SetResult(Self,ContextNode,CurPos.StartPos); Result:=true;
exit; Params.SetResult(Self,ContextNode,CurPos.StartPos);
exit;
end;
end else begin
// the default property is searched
Result:=PropertyIsDefault(ContextNode);
if Result then exit;
end; end;
end; end;
@ -752,7 +766,8 @@ writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in Parent Con
ctnTypeSection, ctnVarSection, ctnConstSection, ctnResStrSection, ctnTypeSection, ctnVarSection, ctnConstSection, ctnResStrSection,
ctnInterface, ctnImplementation, ctnInterface, ctnImplementation,
ctnClassPublished,ctnClassPublic,ctnClassProtected, ctnClassPrivate, ctnClassPublished,ctnClassPublic,ctnClassProtected, ctnClassPrivate,
ctnRecordCase, ctnRecordVariant: ctnRecordCase, ctnRecordVariant,
ctnProcedureHead, ctnParameterList:
// these codetreenodes build a parent-child-relationship, but // these codetreenodes build a parent-child-relationship, but
// for pascal it is only a range, hence after searching in the // for pascal it is only a range, hence after searching in the
// childs of the last node, it must be searched next in the childs // childs of the last node, it must be searched next in the childs
@ -900,12 +915,17 @@ begin
ReadPriorAtom; ReadPriorAtom;
CurAtom:=CurPos; CurAtom:=CurPos;
CurAtomType:=GetCurrentAtomType; CurAtomType:=GetCurrentAtomType;
if CurAtomType=atNone then begin if CurAtomType in [atNone,atSpace,atINHERITED,atRoundBracketOpen,
atEdgedBracketOpen,atRoundBracketClose] then begin
// no special context found -> the context node is the deepest node at // no special context found -> the context node is the deepest node at
// cursor, and this should already be in Params.ContextNode // cursor, and this should already be in Params.ContextNode
Result:=Params.ContextNode; Result:=Params.ContextNode;
exit; exit;
end; end;
if (CurAtomType in [atRoundBracketClose,atEdgedBracketClose]) then begin
ReadBackTilBracketClose(true);
CurAtom.StartPos:=CurPos.StartPos;
end;
Result:=FindContextNodeAtCursor(Params); Result:=FindContextNodeAtCursor(Params);
if Result=nil then exit; if Result=nil then exit;
@ -934,20 +954,42 @@ writeln('');
MoveCursorToCleanPos(NextAtom.StartPos); MoveCursorToCleanPos(NextAtom.StartPos);
RaiseException('syntax error: "'+GetAtom+'" found'); RaiseException('syntax error: "'+GetAtom+'" found');
end; end;
if (Result=Params.ContextNode) if (Result=Params.ContextNode) then begin
and (CompareSrcIdentifier(CurAtom.StartPos,'SELF')) then begin if CompareSrcIdentifier(CurAtom.StartPos,'SELF') then begin
// SELF in a method is the object itself // SELF in a method is the object itself
// -> check if in a proc // -> check if in a proc
ProcNode:=Params.ContextNode; ProcNode:=Params.ContextNode;
while (ProcNode<>nil) do begin while (ProcNode<>nil) do begin
if (ProcNode.Desc=ctnProcedure) then begin if (ProcNode.Desc=ctnProcedure) then begin
// in a proc -> find the class context // in a proc -> find the class context
if FindClassOfMethod(ProcNode,Params,true) then begin if FindClassOfMethod(ProcNode,Params,true) then begin
Result:=Params.NewNode; Result:=Params.NewNode;
exit; exit;
end;
end; end;
ProcNode:=ProcNode.Parent;
end;
end else if CompareSrcIdentifier(CurAtom.StartPos,'RESULT') then begin
// RESULT has a special meaning in a function
// -> check if in a function
ProcNode:=Params.ContextNode;
while (ProcNode<>nil) do begin
if (ProcNode.Desc=ctnProcedure) then begin
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if UpAtomIs('CLASS') then ReadNextAtom;
if UpAtomIs('FUNCTION') then begin;
// in a function -> find the result type
BuildSubTreeForProcHead(ProcNode);
ProcNode:=ProcNode.FirstChild.FirstChild;
if Result.Desc=ctnParameterList then
Result:=Result.NextBrother;
FindBaseTypeOfNode(Params,Result);
exit;
end;
end;
ProcNode:=ProcNode.Parent;
end; end;
ProcNode:=ProcNode.Parent;
end; end;
end; end;
// find identifier // find identifier
@ -970,6 +1012,7 @@ writeln('');
finally finally
Params.Load(OldInput); Params.Load(OldInput);
end; end;
Result:=FindBaseTypeOfNode(Params,Result);
end; end;
atPoint: atPoint:
@ -1013,17 +1056,56 @@ writeln('');
MoveCursorToCleanPos(CurAtom.StartPos); MoveCursorToCleanPos(CurAtom.StartPos);
RaiseException('illegal qualifier ^'); RaiseException('illegal qualifier ^');
end; end;
Result:=Result.FirstChild; Result:=FindBaseTypeOfNode(Params,Result.FirstChild);
end else if NodeHasParentOfType(Result,ctnPointerType) then begin end else if NodeHasParentOfType(Result,ctnPointerType) then begin
// this is a pointer type definition // this is a pointer type definition
// -> the default context is ok // -> the default context is ok
end; end;
end; end;
atEdgedBracketClose:
begin
// for example: a[]
// this could be:
// 1. ranged array
// 2. dynamic array
// 3. indexed pointer
// 4. default property
if Result<>Params.ContextNode then begin
case Result.Desc of
ctnArrayType:
// the array type is the last child node
Result:=FindBaseTypeOfNode(Params,Result.LastChild);
// ToDo: atINHERITED, atRoundBracketClose, atEdgedBracketClose ctnPointerType:
// the pointer type is the only child node
Result:=FindBaseTypeOfNode(Params,Result.FirstChild);
ctnClass:
begin
Params.Save(OldInput);
Params.Flags:=[fdfSearchInAncestors,fdfExceptionOnNotFound]
+fdfGlobals*Params.Flags;
Params.IdentifierStartPos:=CurAtom.StartPos;
Params.IdentifierEndPos:=CurAtom.StartPos+1;
Params.ContextNode:=Result;
FindIdentifierInContext(Params);
Result:=FindBaseTypeOfNode(Params,Params.NewNode);
Params.Load(OldInput);
end;
else
MoveCursorToCleanPos(CurAtom.StartPos);
RaiseException('illegal qualifier');
end;
end;
end;
// ToDo: atINHERITED, atRoundBracketClose
else else
// expression start found
begin begin
if (not (NextAtomType in [atSpace,atIdentifier,atRoundBracketOpen, if (not (NextAtomType in [atSpace,atIdentifier,atRoundBracketOpen,
atEdgedBracketOpen])) then atEdgedBracketOpen])) then
@ -1036,9 +1118,6 @@ writeln('');
end; end;
end; end;
// try to get the base type of the found context
Result:=FindBaseTypeOfNode(Params,Result);
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
write('[TFindDeclarationTool.FindContextNodeAtCursor] END ', write('[TFindDeclarationTool.FindContextNodeAtCursor] END ',
Params.ContextNode.DescAsString,' CurAtom=',AtomTypeNames[CurAtomType], Params.ContextNode.DescAsString,' CurAtom=',AtomTypeNames[CurAtomType],
@ -1088,11 +1167,6 @@ begin
Params.Load(OldInput); Params.Load(OldInput);
end; end;
end else end else
if (Result.Desc=ctnTypeType) then begin
// a TypeType is for example 'MyInt = type integer;'
// the context is not the 'type' keyword, but the identifier after it.
Result:=Result.FirstChild;
end else
if (Result.Desc=ctnIdentifier) then begin if (Result.Desc=ctnIdentifier) then begin
// this type is just an alias for another type // this type is just an alias for another type
// -> search the basic type // -> search the basic type
@ -1113,6 +1187,30 @@ begin
finally finally
Params.Load(OldInput); Params.Load(OldInput);
end; end;
end else
if (Result.Desc=ctnProperty) then begin
// this is a property -> search the type definition of the property
ReadTilTypeOfProperty(Result);
Params.Save(OldInput);
try
Params.IdentifierStartPos:=CurPos.StartPos;
Params.IdentifierEndPos:=CurPos.EndPos;
Params.Flags:=[fdfSearchInParentNodes,fdfExceptionOnNotFound]
+(fdfGlobals*Params.Flags);
Params.ContextNode:=Result.Parent;
FindIdentifierInContext(Params);
if Result.HasAsParent(Params.NewNode) then
break
else
Result:=Params.NewNode;
finally
Params.Load(OldInput);
end;
end else
if (Result.Desc=ctnTypeType) then begin
// a TypeType is for example 'MyInt = type integer;'
// the context is not the 'type' keyword, but the identifier after it.
Result:=Result.FirstChild;
end else end else
break; break;
end; end;
@ -1139,6 +1237,8 @@ var
ClassContextNode: TCodeTreeNode; ClassContextNode: TCodeTreeNode;
begin begin
Result:=false; Result:=false;
// if proc is a method, search in class
// -> find class name
MoveCursorToNodeStart(ProcContextNode); MoveCursorToNodeStart(ProcContextNode);
ReadNextAtom; // read keyword ReadNextAtom; // read keyword
ReadNextAtom; // read classname ReadNextAtom; // read classname

View File

@ -76,7 +76,8 @@ type
phpWithoutName, phpWithVarModifiers, phpWithParameterNames, phpWithoutName, phpWithVarModifiers, phpWithParameterNames,
phpWithDefaultValues, phpWithResultType, phpWithComments, phpInUpperCase, phpWithDefaultValues, phpWithResultType, phpWithComments, phpInUpperCase,
phpWithoutBrackets, phpIgnoreForwards, phpIgnoreProcsWithBody, phpWithoutBrackets, phpIgnoreForwards, phpIgnoreProcsWithBody,
phpOnlyWithClassname, phpFindCleanPosition, phpWithoutParamList); phpOnlyWithClassname, phpFindCleanPosition, phpWithoutParamList,
phpCreateNodes);
TProcHeadAttributes = set of TProcHeadAttribute; TProcHeadAttributes = set of TProcHeadAttribute;
TProcHeadExtractPos = (phepNone, phepStart, phepName, phepParamList); TProcHeadExtractPos = (phepNone, phepStart, phepName, phepParamList);
@ -143,7 +144,8 @@ type
procedure BuildBlockStatementStartKeyWordFuncList; virtual; procedure BuildBlockStatementStartKeyWordFuncList; virtual;
function UnexpectedKeyWord: boolean; function UnexpectedKeyWord: boolean;
// read functions // read functions
function ReadTilProcedureHeadEnd(IsMethod, IsFunction, IsType: boolean; function ReadTilProcedureHeadEnd(IsMethod, IsFunction, IsType,
CreateNodes: boolean;
var HasForwardModifier: boolean): boolean; var HasForwardModifier: boolean): boolean;
function ReadConstant(ExceptionOnError, Extract: boolean; function ReadConstant(ExceptionOnError, Extract: boolean;
Attr: TProcHeadAttributes): boolean; Attr: TProcHeadAttributes): boolean;
@ -162,6 +164,7 @@ type
function ReadWithStatement(ExceptionOnError, function ReadWithStatement(ExceptionOnError,
CreateNodes: boolean): boolean; CreateNodes: boolean): boolean;
procedure ReadVariableType; procedure ReadVariableType;
procedure ReadTilTypeOfProperty(PropertyNode: TCodeTreeNode);
public public
CurSection: TCodeTreeNodeDesc; CurSection: TCodeTreeNodeDesc;
@ -176,6 +179,7 @@ type
CursorPos: TCodeXYPosition; var CleanCursorPos: integer); CursorPos: TCodeXYPosition; var CleanCursorPos: integer);
procedure BuildSubTreeForClass(ClassNode: TCodeTreeNode); virtual; procedure BuildSubTreeForClass(ClassNode: TCodeTreeNode); virtual;
procedure BuildSubTreeForBeginBlock(BeginNode: TCodeTreeNode); virtual; procedure BuildSubTreeForBeginBlock(BeginNode: TCodeTreeNode); virtual;
procedure BuildSubTreeForProcHead(ProcNode: TCodeTreeNode); virtual;
function DoAtom: boolean; override; function DoAtom: boolean; override;
function ExtractPropName(PropNode: TCodeTreeNode; function ExtractPropName(PropNode: TCodeTreeNode;
InUpperCase: boolean): string; InUpperCase: boolean): string;
@ -208,6 +212,7 @@ type
function GetSourceType: TCodeTreeNodeDesc; function GetSourceType: TCodeTreeNodeDesc;
function NodeHasParentOfType(ANode: TCodeTreeNode; function NodeHasParentOfType(ANode: TCodeTreeNode;
NodeDesc: TCodeTreeNodeDesc): boolean; NodeDesc: TCodeTreeNodeDesc): boolean;
function PropertyIsDefault(PropertyNode: TCodeTreeNode): boolean;
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
end; end;
@ -851,7 +856,7 @@ begin
IsFunction:=UpAtomIs('FUNCTION'); IsFunction:=UpAtomIs('FUNCTION');
ReadNextAtom; ReadNextAtom;
HasForwardModifier:=false; HasForwardModifier:=false;
ReadTilProcedureHeadEnd(true,IsFunction,true,HasForwardModifier); ReadTilProcedureHeadEnd(true,IsFunction,true,false,HasForwardModifier);
Result:=true; Result:=true;
end; end;
@ -930,7 +935,7 @@ begin
CurNode.Desc:=ctnProcedureHead; CurNode.Desc:=ctnProcedureHead;
// read rest // read rest
ReadNextAtom; ReadNextAtom;
ReadTilProcedureHeadEnd(true,IsFunction,false,HasForwardModifier); ReadTilProcedureHeadEnd(true,IsFunction,false,false,HasForwardModifier);
// close procedure header // close procedure header
CurNode.EndPos:=CurPos.EndPos; CurNode.EndPos:=CurPos.EndPos;
EndChildNode; EndChildNode;
@ -943,6 +948,7 @@ end;
function TPascalParserTool.ReadParamList(ExceptionOnError, Extract: boolean; function TPascalParserTool.ReadParamList(ExceptionOnError, Extract: boolean;
Attr: TProcHeadAttributes): boolean; Attr: TProcHeadAttributes): boolean;
var CloseBracket: char; var CloseBracket: char;
Desc: TCodeTreeNodeDesc;
begin begin
Result:=false; Result:=false;
if AtomIsChar('(') or AtomIsChar('[') then begin if AtomIsChar('(') or AtomIsChar('[') then begin
@ -950,6 +956,10 @@ begin
CloseBracket:=')' CloseBracket:=')'
else else
CloseBracket:=']'; CloseBracket:=']';
if (phpCreateNodes in Attr) then begin
CreateChildNode;
CurNode.Desc:=ctnParameterList;
end;
if not Extract then if not Extract then
ReadNextAtom ReadNextAtom
else else
@ -958,25 +968,37 @@ begin
CloseBracket:=#0; CloseBracket:=#0;
repeat repeat
// read parameter prefix modifier // read parameter prefix modifier
if (UpAtomIs('VAR')) or (UpAtomIs('CONST')) or (UpAtomIs('OUT')) then if (UpAtomIs('VAR')) or (UpAtomIs('CONST')) or (UpAtomIs('OUT')) then begin
Desc:=ctnVarDefinition;
if not Extract then if not Extract then
ReadNextAtom ReadNextAtom
else else
ExtractNextAtom(phpWithVarModifiers in Attr,Attr); ExtractNextAtom(phpWithVarModifiers in Attr,Attr);
end else
Desc:=ctnVarDefinition;
// read parameter name(s) // read parameter name(s)
repeat repeat
AtomIsIdentifier(ExceptionOnError); if not AtomIsIdentifier(ExceptionOnError) then exit;
if (phpCreateNodes in Attr) then begin
CreateChildNode;
CurNode.Desc:=Desc;
end;
if not Extract then if not Extract then
ReadNextAtom ReadNextAtom
else else
ExtractNextAtom(phpWithParameterNames in Attr,Attr); ExtractNextAtom(phpWithParameterNames in Attr,Attr);
if not AtomIsChar(',') then if not AtomIsChar(',') then
break break
else else begin
if (phpCreateNodes in Attr) then begin
CurNode.EndPos:=LastAtoms.GetValueAt(0).EndPos;
EndChildNode;
end;
if not Extract then if not Extract then
ReadNextAtom ReadNextAtom
else else
ExtractNextAtom(not (phpWithoutParamList in Attr),Attr); ExtractNextAtom(not (phpWithoutParamList in Attr),Attr);
end;
until false; until false;
// read type // read type
if (AtomIsChar(':')) then begin if (AtomIsChar(':')) then begin
@ -995,6 +1017,10 @@ begin
Extract and (phpWithDefaultValues in Attr),Attr); Extract and (phpWithDefaultValues in Attr),Attr);
end; end;
end; end;
if (phpCreateNodes in Attr) then begin
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
end;
// read next parameter // read next parameter
if (CurPos.StartPos>SrcLen) then if (CurPos.StartPos>SrcLen) then
if ExceptionOnError then if ExceptionOnError then
@ -1018,6 +1044,10 @@ begin
RaiseException( RaiseException(
'syntax error: '+CloseBracket+' expected, but '+GetAtom+' found') 'syntax error: '+CloseBracket+' expected, but '+GetAtom+' found')
else exit; else exit;
if (phpCreateNodes in Attr) then begin
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
end;
if not Extract then if not Extract then
ReadNextAtom ReadNextAtom
else else
@ -1032,6 +1062,10 @@ begin
Result:=false; Result:=false;
if AtomIsWord then begin if AtomIsWord then begin
if UpAtomIs('ARRAY') then begin if UpAtomIs('ARRAY') then begin
if (phpCreateNodes in Attr) then begin
CreateChildNode;
CurNode.Desc:=ctnArrayType;
end;
if not Extract then ReadNextAtom else ExtractNextAtom(true,Attr); if not Extract then ReadNextAtom else ExtractNextAtom(true,Attr);
if not UpAtomIs('OF') then if not UpAtomIs('OF') then
if ExceptionOnError then if ExceptionOnError then
@ -1039,6 +1073,12 @@ begin
else exit; else exit;
ReadNextAtom; ReadNextAtom;
if UpAtomIs('CONST') then begin if UpAtomIs('CONST') then begin
if (phpCreateNodes in Attr) then begin
CreateChildNode;
CurNode.Desc:=ctnArrayType;
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
end;
if not Extract then if not Extract then
ReadNextAtom ReadNextAtom
else else
@ -1048,6 +1088,12 @@ begin
end; end;
end; end;
if not AtomIsIdentifier(ExceptionOnError) then exit; if not AtomIsIdentifier(ExceptionOnError) then exit;
if (phpCreateNodes in Attr) then begin
CreateChildNode;
CurNode.Desc:=ctnIdentifier;
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
end;
if not Extract then if not Extract then
ReadNextAtom ReadNextAtom
else else
@ -1062,7 +1108,7 @@ begin
end; end;
function TPascalParserTool.ReadTilProcedureHeadEnd( function TPascalParserTool.ReadTilProcedureHeadEnd(
IsMethod, IsFunction, IsType: boolean; IsMethod, IsFunction, IsType, CreateNodes: boolean;
var HasForwardModifier: boolean): boolean; var HasForwardModifier: boolean): boolean;
{ parse parameter list, result type, of object, method specifiers { parse parameter list, result type, of object, method specifiers
@ -1087,23 +1133,30 @@ function TPascalParserTool.ReadTilProcedureHeadEnd(
[alias: <string constant>] [alias: <string constant>]
} }
var IsSpecifier: boolean; var IsSpecifier: boolean;
Attr: TProcHeadAttributes;
begin begin
//writeln('[TPascalParserTool.ReadTilProcedureHeadEnd] ', //writeln('[TPascalParserTool.ReadTilProcedureHeadEnd] ',
//'Method=',IsMethod,', Function=',IsFunction,', Type=',IsType); //'Method=',IsMethod,', Function=',IsFunction,', Type=',IsType);
Result:=true; Result:=true;
HasForwardModifier:=false; HasForwardModifier:=false;
if AtomIsChar('(') then if AtomIsChar('(') then begin
ReadParamList(true,false,[]); Attr:=[];
if CreateNodes then
Include(Attr,phpCreateNodes);
ReadParamList(true,false,Attr);
end;
if IsFunction then begin if IsFunction then begin
// read function result type // read function result type
if not AtomIsChar(':') then if not AtomIsChar(':') then
RaiseException('syntax error: : expected, but '+GetAtom+' found'); RaiseException('syntax error: : expected, but '+GetAtom+' found');
ReadNextAtom; ReadNextAtom;
if (CurPos.StartPos>SrcLen) AtomIsIdentifier(true);
or (not (UpperSrc[CurPos.StartPos] in ['A'..'Z','_'])) if CreateNodes then begin
then CreateChildNode;
RaiseException( CurNode.Desc:=ctnIdentifier;
'syntax error: method result type expected but '+GetAtom+' found'); CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
end;
ReadNextAtom; ReadNextAtom;
end; end;
if UpAtomIs('OF') then begin if UpAtomIs('OF') then begin
@ -1537,7 +1590,7 @@ begin
end; end;
// read rest of procedure head // read rest of procedure head
HasForwardModifier:=false; HasForwardModifier:=false;
ReadTilProcedureHeadEnd(false,IsFunction,false,HasForwardModifier); ReadTilProcedureHeadEnd(false,IsFunction,false,false,HasForwardModifier);
if ChildCreated then begin if ChildCreated then begin
if HasForwardModifier then if HasForwardModifier then
ProcNode.SubDesc:=ctnsForwardDeclaration; ProcNode.SubDesc:=ctnsForwardDeclaration;
@ -3059,6 +3112,67 @@ begin
end; end;
end; end;
procedure TPascalParserTool.ReadTilTypeOfProperty(PropertyNode: TCodeTreeNode);
begin
MoveCursorToNodeStart(PropertyNode);
ReadNextAtom; // read keyword 'property'
ReadNextAtom; // read property name
AtomIsIdentifier(true);
ReadNextAtom;
if AtomIsChar('[') then begin
// read parameter list
ReadTilBracketClose(true);
ReadNextAtom;
end;
if not AtomIsChar(':') then
RaiseException('syntax error: : expected, but '+GetAtom+' found');
ReadNextAtom; // read type
AtomIsIdentifier(true);
end;
function TPascalParserTool.PropertyIsDefault(PropertyNode: TCodeTreeNode
): boolean;
begin
Result:=false;
if (PropertyNode=nil) or (PropertyNode.Desc<>ctnProperty) then exit;
MoveCursorToCleanPos(PropertyNode.EndPos);
ReadPriorAtom;
if (not AtomIsChar(';')) then exit;
ReadPriorAtom;
Result:=UpAtomIs('DEFAULT');
end;
procedure TPascalParserTool.BuildSubTreeForProcHead(ProcNode: TCodeTreeNode);
var HasForwardModifier, IsFunction: boolean;
begin
if ProcNode.Desc=ctnProcedureHead then ProcNode:=ProcNode.Parent;
if (ProcNode=nil) or (ProcNode.Desc<>ctnProcedure)
or (ProcNode.FirstChild=nil) then
RaiseException('[TPascalParserTool.BuildSubTreeForProcHead] '
+'internal error: invalid ProcNode');
if ProcNode.FirstChild.SubDesc=ctnsProcHeadNodesCreated then exit;
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if UpAtomIs('CLASS') then
ReadNextAtom;
IsFunction:=UpAtomIs('FUNCTION');
// read procedure head (= name + parameterlist + resulttype;)
CurNode:=ProcNode.FirstChild;
ReadNextAtom;// read first atom of head
AtomIsIdentifier(true);
ReadNextAtom;
if AtomIsChar('.') then begin
// read procedure name of a class method (the name after the . )
ReadNextAtom;
AtomIsIdentifier(true);
ReadNextAtom;
end;
// read rest of procedure head and build nodes
HasForwardModifier:=false;
ReadTilProcedureHeadEnd(false,IsFunction,false,true,HasForwardModifier);
ProcNode.FirstChild.SubDesc:=ctnsProcHeadNodesCreated;
end;
end. end.