mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-25 02:20:40 +02:00
MG: started find declaration for identifiers
git-svn-id: trunk@589 -
This commit is contained in:
parent
95234d77e0
commit
48e8bf1d18
@ -102,6 +102,8 @@ const
|
|||||||
ctnPointerType = 82;
|
ctnPointerType = 82;
|
||||||
ctnClassOfType = 83;
|
ctnClassOfType = 83;
|
||||||
|
|
||||||
|
ctnWithVariable = 90;
|
||||||
|
ctnWithStatement = 91;
|
||||||
|
|
||||||
|
|
||||||
// combined values
|
// combined values
|
||||||
@ -278,6 +280,9 @@ begin
|
|||||||
ctnPointerType: Result:='Pointer ''^'' Type';
|
ctnPointerType: Result:='Pointer ''^'' Type';
|
||||||
ctnClassOfType: Result:='Class Of Type';
|
ctnClassOfType: Result:='Class Of Type';
|
||||||
|
|
||||||
|
ctnWithVariable: Result:='With Variable';
|
||||||
|
ctnWithStatement: Result:='With Statement'
|
||||||
|
|
||||||
else
|
else
|
||||||
Result:='invalid descriptor';
|
Result:='invalid descriptor';
|
||||||
end;
|
end;
|
||||||
|
@ -91,14 +91,14 @@ type
|
|||||||
|
|
||||||
function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean;
|
function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean;
|
||||||
procedure BeginParsing(DeleteNodes, OnlyInterfaceNeeded: boolean); virtual;
|
procedure BeginParsing(DeleteNodes, OnlyInterfaceNeeded: boolean); virtual;
|
||||||
procedure MoveCursorToNodeStart(ANode: TCodeTreeNode); virtual;
|
procedure MoveCursorToNodeStart(ANode: TCodeTreeNode);
|
||||||
procedure MoveCursorToCleanPos(ACleanPos: integer); virtual;
|
procedure MoveCursorToCleanPos(ACleanPos: integer);
|
||||||
function ReadTilSection(SectionType: TCodeTreeNodeDesc): boolean;
|
function ReadTilSection(SectionType: TCodeTreeNodeDesc): boolean;
|
||||||
function ReadTilBracketClose(ExceptionOnNotFound: boolean): boolean;
|
function ReadTilBracketClose(ExceptionOnNotFound: boolean): boolean;
|
||||||
function ReadBackTilBracketClose(ExceptionOnNotFound: boolean): boolean;
|
function ReadBackTilBracketClose(ExceptionOnNotFound: boolean): boolean;
|
||||||
function DoAtom: boolean; virtual;
|
function DoAtom: boolean; virtual;
|
||||||
procedure ReadNextAtom; virtual;
|
procedure ReadNextAtom;
|
||||||
procedure UndoReadNextAtom; virtual;
|
procedure UndoReadNextAtom;
|
||||||
function AtomIs(const AnAtom: shortstring): boolean;
|
function AtomIs(const AnAtom: shortstring): boolean;
|
||||||
function UpAtomIs(const AnAtom: shortstring): boolean;
|
function UpAtomIs(const AnAtom: shortstring): boolean;
|
||||||
function ReadNextAtomIs(const AnAtom: shortstring): boolean;
|
function ReadNextAtomIs(const AnAtom: shortstring): boolean;
|
||||||
@ -120,10 +120,10 @@ type
|
|||||||
const ASource: string): integer;
|
const ASource: string): integer;
|
||||||
function CompareNodeUpSrc(ANode: TCodeTreeNode;
|
function CompareNodeUpSrc(ANode: TCodeTreeNode;
|
||||||
const ASource: string): integer;
|
const ASource: string): integer;
|
||||||
procedure ReadPriorAtom; virtual;
|
procedure ReadPriorAtom;
|
||||||
|
|
||||||
procedure CreateChildNode; virtual;
|
procedure CreateChildNode;
|
||||||
procedure EndChildNode; virtual;
|
procedure EndChildNode;
|
||||||
|
|
||||||
procedure Clear; virtual;
|
procedure Clear; virtual;
|
||||||
function NodeDescToStr(Desc: integer): string;
|
function NodeDescToStr(Desc: integer): string;
|
||||||
|
@ -55,6 +55,13 @@ type
|
|||||||
var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
||||||
function IsIncludeDirectiveAtPos(CleanPos, CleanCodePosInFront: integer;
|
function IsIncludeDirectiveAtPos(CleanPos, CleanCodePosInFront: integer;
|
||||||
var IncludeCode: TCodeBuffer): boolean;
|
var IncludeCode: TCodeBuffer): boolean;
|
||||||
|
function FindDeclarationOfIdentifier(DeepestNode: TCodeTreeNode;
|
||||||
|
IdentifierStartPos, IdentifierEndPos: integer;
|
||||||
|
var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
||||||
|
function FindIdentifierInContext(IdentifierStartPos,
|
||||||
|
IdentifierEndPos: integer; ContextNode: TCodeTreeNode;
|
||||||
|
SearchInParentNodes: boolean;
|
||||||
|
var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
||||||
public
|
public
|
||||||
function FindDeclaration(CursorPos: TCodeXYPosition;
|
function FindDeclaration(CursorPos: TCodeXYPosition;
|
||||||
var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
||||||
@ -97,16 +104,27 @@ writeln('TFindDeclarationTool.FindDeclaration C CleanCursorPos=',CleanCursorPos)
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if CursorNode.Desc=ctnUsesSection then begin
|
if CursorNode.Desc=ctnUsesSection then begin
|
||||||
|
// find used unit
|
||||||
Result:=FindDeclarationInUsesSection(CursorNode,CleanCursorPos,
|
Result:=FindDeclarationInUsesSection(CursorNode,CleanCursorPos,
|
||||||
NewPos,NewTopLine);
|
NewPos,NewTopLine);
|
||||||
end else begin
|
end else begin
|
||||||
{ ToDo:
|
if CursorNode.Desc=ctnBeginBlock then
|
||||||
1. if in begin..end block then parse for with and case statements
|
BuildSubTreeForBeginBlock(CursorNode);
|
||||||
2. search recursively and create/fill caches
|
MoveCursorToCleanPos(CleanCursorPos);
|
||||||
3. if possible use ppu files
|
while (CurPos.StartPos>=1) and (IsIdentChar[Src[CurPos.StartPos]]) do
|
||||||
4. save visible identifiers for identifier completion
|
dec(CurPos.StartPos);
|
||||||
...
|
if (CurPos.StartPos>=1) and (IsIdentStartChar[Src[CurPos.StartPos]]) then
|
||||||
}
|
begin
|
||||||
|
CurPos.EndPos:=CurPos.StartPos;
|
||||||
|
while (CurPos.EndPos<=SrcLen) and IsIdentChar[Src[CurPos.EndPos]] do
|
||||||
|
inc(CurPos.EndPos);
|
||||||
|
// find declaration of identifier
|
||||||
|
Result:=FindDeclarationOfIdentifier(CursorNode,
|
||||||
|
CurPos.StartPos,CurPos.EndPos,NewPos,NewTopLine);
|
||||||
|
end else begin
|
||||||
|
// find declaration of not identifier
|
||||||
|
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -362,6 +380,88 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFindDeclarationTool.FindDeclarationOfIdentifier(
|
||||||
|
DeepestNode: TCodeTreeNode; IdentifierStartPos, IdentifierEndPos: integer;
|
||||||
|
var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
||||||
|
{ searches an identifier in clean code, parses code in front of identifier
|
||||||
|
For example:
|
||||||
|
A^.B().C[].Identifier
|
||||||
|
}
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
MoveCursorToCleanPos(IdentifierStartPos);
|
||||||
|
ReadPriorAtom;
|
||||||
|
if AtomIsChar('.') then begin
|
||||||
|
// first search context, then search in context
|
||||||
|
|
||||||
|
// ToDo
|
||||||
|
|
||||||
|
end else if UpAtomIs('INHERITED') then begin
|
||||||
|
// first search ancestor, then search in ancestor
|
||||||
|
|
||||||
|
// ToDo
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
// context is DeepestNode
|
||||||
|
Result:=FindIdentifierInContext(IdentifierStartPos,IdentifierEndPos,
|
||||||
|
DeepestNode,true,NewPos,NewTopLine);
|
||||||
|
end;
|
||||||
|
{ ToDo:
|
||||||
|
|
||||||
|
- Difficulties:
|
||||||
|
1. Searching recursively
|
||||||
|
- ParentNodes
|
||||||
|
- Ancestor Classes/Objects/Interfaces
|
||||||
|
- with statements
|
||||||
|
- operators: '.', '()', 'A()', '^', 'inherited'
|
||||||
|
2. Searching enums must be searched in sub nodes
|
||||||
|
-> all classes node trees must be built
|
||||||
|
3. Searching in used units (interface USES and implementation USES)
|
||||||
|
4. Searching forward for pointer types e.g. ^Tralala
|
||||||
|
5. Mass Search: searching a compatible proc will result
|
||||||
|
in searching every parameter type of every reachable proc
|
||||||
|
(implementation section + interface section
|
||||||
|
+ used interface sections + class and ancestor methods)
|
||||||
|
How can this be achieved in good time?
|
||||||
|
-> Caching
|
||||||
|
- Caching:
|
||||||
|
Where:
|
||||||
|
For each section node (Interface, Implementation, ...)
|
||||||
|
For each BeginBlock
|
||||||
|
Entries: (What, Declaration Pos)
|
||||||
|
What: Identifier -> Ansistring (to reduce memory usage,
|
||||||
|
maintain a list of all identifier ansistrings)
|
||||||
|
Pos: Code+SrcPos
|
||||||
|
1. Source: TCodeTreeNode
|
||||||
|
2. PPU, PPW, DFU, ...:
|
||||||
|
}
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFindDeclarationTool.FindIdentifierInContext(IdentifierStartPos,
|
||||||
|
IdentifierEndPos: integer; ContextNode: TCodeTreeNode;
|
||||||
|
SearchInParentNodes: boolean; var NewPos: TCodeXYPosition;
|
||||||
|
var NewTopLine: integer): boolean;
|
||||||
|
{ searches an identifier in context node
|
||||||
|
It does not care about code in front
|
||||||
|
}
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
if ContextNode<>nil then begin
|
||||||
|
case ContextNode.Desc of
|
||||||
|
ctnBeginBlock:
|
||||||
|
begin
|
||||||
|
if not SearchInParentNodes then exit;
|
||||||
|
|
||||||
|
// ToDo
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
// DeepestNode=nil
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
ToDo:
|
ToDo:
|
||||||
- ReadBackTilBlockEnd: case could also be in a record, then it should not
|
- ReadBackTilBlockEnd: case could also be in a record, then it should not
|
||||||
close the block
|
close the block
|
||||||
|
- BuildSubTreeForBeginBlock: building case statement nodes
|
||||||
|
|
||||||
}
|
}
|
||||||
unit PascalParserTool;
|
unit PascalParserTool;
|
||||||
@ -88,6 +89,7 @@ type
|
|||||||
PackedTypesKeyWordFuncList: TKeyWordFunctionList;
|
PackedTypesKeyWordFuncList: TKeyWordFunctionList;
|
||||||
InnerClassKeyWordFuncList: TKeyWordFunctionList;
|
InnerClassKeyWordFuncList: TKeyWordFunctionList;
|
||||||
ClassVarTypeKeyWordFuncList: TKeyWordFunctionList;
|
ClassVarTypeKeyWordFuncList: TKeyWordFunctionList;
|
||||||
|
BlockStatementStartKeyWordFuncList: TKeyWordFunctionList;
|
||||||
ExtractMemStream: TMemoryStream;
|
ExtractMemStream: TMemoryStream;
|
||||||
ExtractSearchPos: integer;
|
ExtractSearchPos: integer;
|
||||||
ExtractFoundPos: integer;
|
ExtractFoundPos: integer;
|
||||||
@ -138,6 +140,7 @@ type
|
|||||||
procedure BuildPackedTypesKeyWordFunctions; virtual;
|
procedure BuildPackedTypesKeyWordFunctions; virtual;
|
||||||
procedure BuildInnerClassKeyWordFunctions; virtual;
|
procedure BuildInnerClassKeyWordFunctions; virtual;
|
||||||
procedure BuildClassVarTypeKeyWordFunctions; virtual;
|
procedure BuildClassVarTypeKeyWordFunctions; 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: boolean;
|
||||||
@ -150,8 +153,14 @@ type
|
|||||||
Attr: TProcHeadAttributes): boolean;
|
Attr: TProcHeadAttributes): boolean;
|
||||||
function ReadUsesSection(ExceptionOnError: boolean): boolean;
|
function ReadUsesSection(ExceptionOnError: boolean): boolean;
|
||||||
function ReadSubRange(ExceptionOnError: boolean): boolean;
|
function ReadSubRange(ExceptionOnError: boolean): boolean;
|
||||||
function ReadTilBlockEnd(StopOnBlockMiddlePart: boolean): boolean;
|
function ReadTilBlockEnd(StopOnBlockMiddlePart,
|
||||||
|
CreateNodes: boolean): boolean;
|
||||||
function ReadBackTilBlockEnd(StopOnBlockMiddlePart: boolean): boolean;
|
function ReadBackTilBlockEnd(StopOnBlockMiddlePart: boolean): boolean;
|
||||||
|
function ReadTilVariableEnd(ExceptionOnError: boolean): boolean;
|
||||||
|
function ReadTilStatementEnd(ExceptionOnError,
|
||||||
|
CreateNodes: boolean): boolean;
|
||||||
|
function ReadWithStatement(ExceptionOnError,
|
||||||
|
CreateNodes: boolean): boolean;
|
||||||
public
|
public
|
||||||
CurSection: TCodeTreeNodeDesc;
|
CurSection: TCodeTreeNodeDesc;
|
||||||
|
|
||||||
@ -162,9 +171,10 @@ type
|
|||||||
function CleanPosIsInComment(CleanPos, CleanCodePosInFront: integer;
|
function CleanPosIsInComment(CleanPos, CleanCodePosInFront: integer;
|
||||||
var CommentStart, CommentEnd: integer): boolean;
|
var CommentStart, CommentEnd: integer): boolean;
|
||||||
procedure BuildTree(OnlyInterfaceNeeded: boolean); virtual;
|
procedure BuildTree(OnlyInterfaceNeeded: boolean); virtual;
|
||||||
procedure BuildSubTreeForClass(ClassNode: TCodeTreeNode); virtual;
|
|
||||||
procedure BuildTreeAndGetCleanPos(OnlyInterfaceNeeded: boolean;
|
procedure BuildTreeAndGetCleanPos(OnlyInterfaceNeeded: boolean;
|
||||||
CursorPos: TCodeXYPosition; var CleanCursorPos: integer);
|
CursorPos: TCodeXYPosition; var CleanCursorPos: integer);
|
||||||
|
procedure BuildSubTreeForClass(ClassNode: TCodeTreeNode); virtual;
|
||||||
|
procedure BuildSubTreeForBeginBlock(BeginNode: TCodeTreeNode); virtual;
|
||||||
function DoAtom: boolean; override;
|
function DoAtom: boolean; override;
|
||||||
function ExtractPropName(PropNode: TCodeTreeNode;
|
function ExtractPropName(PropNode: TCodeTreeNode;
|
||||||
InUpperCase: boolean): string;
|
InUpperCase: boolean): string;
|
||||||
@ -293,6 +303,10 @@ begin
|
|||||||
ClassVarTypeKeyWordFuncList:=TKeyWordFunctionList.Create;
|
ClassVarTypeKeyWordFuncList:=TKeyWordFunctionList.Create;
|
||||||
BuildClassVarTypeKeyWordFunctions;
|
BuildClassVarTypeKeyWordFunctions;
|
||||||
AddKeyWordFuncList(ClassVarTypeKeyWordFuncList);
|
AddKeyWordFuncList(ClassVarTypeKeyWordFuncList);
|
||||||
|
// keywords for statements
|
||||||
|
BlockStatementStartKeyWordFuncList:=TKeyWordFunctionList.Create;
|
||||||
|
BuildBlockStatementStartKeyWordFuncList;
|
||||||
|
AddKeyWordFuncList(BlockStatementStartKeyWordFuncList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TPascalParserTool.Destroy;
|
destructor TPascalParserTool.Destroy;
|
||||||
@ -425,6 +439,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPascalParserTool.BuildBlockStatementStartKeyWordFuncList;
|
||||||
|
begin
|
||||||
|
with BlockStatementStartKeyWordFuncList do begin
|
||||||
|
Add('BEGIN' ,{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
|
Add('REPEAT',{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
|
Add('TRY' ,{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
|
Add('ASM' ,{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
|
Add('CASE' ,{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPascalParserTool.UnexpectedKeyWord: boolean;
|
function TPascalParserTool.UnexpectedKeyWord: boolean;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
@ -570,6 +595,38 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPascalParserTool.BuildSubTreeForBeginBlock(BeginNode: TCodeTreeNode);
|
||||||
|
// reparse a quick parsed begin..end block and build the child nodes
|
||||||
|
// create nodes for 'with' and 'case' statements
|
||||||
|
var MaxPos: integer;
|
||||||
|
begin
|
||||||
|
if BeginNode=nil then
|
||||||
|
RaiseException(
|
||||||
|
'TPascalParserTool.BuildSubTreeForBeginBlock: BeginNode=nil');
|
||||||
|
if BeginNode.FirstChild<>nil then
|
||||||
|
// block already parsed
|
||||||
|
exit;
|
||||||
|
// set CursorPos on 'begin'
|
||||||
|
MoveCursorToNodeStart(BeginNode);
|
||||||
|
ReadNextAtom;
|
||||||
|
if not UpAtomIs('BEGIN') then
|
||||||
|
RaiseException(
|
||||||
|
'TPascalParserTool.BuildSubTreeForBeginBlock: begin expected, but '
|
||||||
|
+GetAtom+' found');
|
||||||
|
if BeginNode.EndPos<SrcLen then
|
||||||
|
Maxpos:=BeginNode.EndPos
|
||||||
|
else
|
||||||
|
MaxPos:=SrcLen;
|
||||||
|
repeat
|
||||||
|
ReadNextAtom;
|
||||||
|
if UpAtomIs('WITH') then
|
||||||
|
ReadWithStatement(true,true);
|
||||||
|
if UpAtomIs('CASE') then begin
|
||||||
|
// ToDo
|
||||||
|
end;
|
||||||
|
until (CurPos.StartPos>=MaxPos);
|
||||||
|
end;
|
||||||
|
|
||||||
function TPascalParserTool.GetSourceType: TCodeTreeNodeDesc;
|
function TPascalParserTool.GetSourceType: TCodeTreeNodeDesc;
|
||||||
begin
|
begin
|
||||||
if Tree.Root<>nil then
|
if Tree.Root<>nil then
|
||||||
@ -1485,7 +1542,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TPascalParserTool.ReadTilBlockEnd(
|
function TPascalParserTool.ReadTilBlockEnd(
|
||||||
StopOnBlockMiddlePart: boolean): boolean;
|
StopOnBlockMiddlePart, CreateNodes: boolean): boolean;
|
||||||
|
// after reading cursor will be on the keyword ending the block (e.g. 'end')
|
||||||
var BlockType: TEndBlockType;
|
var BlockType: TEndBlockType;
|
||||||
TryType: TTryType;
|
TryType: TTryType;
|
||||||
begin
|
begin
|
||||||
@ -1525,7 +1583,7 @@ begin
|
|||||||
if BlockType=ebtAsm then
|
if BlockType=ebtAsm then
|
||||||
RaiseException('syntax error: unexpected keyword "'+GetAtom+'" found');
|
RaiseException('syntax error: unexpected keyword "'+GetAtom+'" found');
|
||||||
if (BlockType<>ebtRecord) or (not UpAtomIs('CASE')) then
|
if (BlockType<>ebtRecord) or (not UpAtomIs('CASE')) then
|
||||||
ReadTilBlockEnd(false);
|
ReadTilBlockEnd(false,CreateNodes);
|
||||||
end else if UpAtomIs('UNTIL') then begin
|
end else if UpAtomIs('UNTIL') then begin
|
||||||
if BlockType=ebtRepeat then
|
if BlockType=ebtRepeat then
|
||||||
break;
|
break;
|
||||||
@ -1545,6 +1603,8 @@ begin
|
|||||||
end else
|
end else
|
||||||
RaiseException(
|
RaiseException(
|
||||||
'syntax error: "end" expected, but "'+GetAtom+'" found');
|
'syntax error: "end" expected, but "'+GetAtom+'" found');
|
||||||
|
end else if CreateNodes and UpAtomIs('WITH') then begin
|
||||||
|
ReadWithStatement(true,CreateNodes);
|
||||||
end;
|
end;
|
||||||
until false;
|
until false;
|
||||||
end;
|
end;
|
||||||
@ -1617,6 +1677,105 @@ begin
|
|||||||
until false;
|
until false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPascalParserTool.ReadTilVariableEnd(
|
||||||
|
ExceptionOnError: boolean): boolean;
|
||||||
|
{ Examples:
|
||||||
|
A
|
||||||
|
A.B^.C[...].D(...).E
|
||||||
|
(...).A
|
||||||
|
@B
|
||||||
|
|
||||||
|
}
|
||||||
|
begin
|
||||||
|
while AtomIsChar('@') do
|
||||||
|
ReadNextAtom;
|
||||||
|
while UpAtomIs('INHERITED') do
|
||||||
|
ReadNextAtom;
|
||||||
|
Result:=(AtomIsIdentifier(false) or AtomIsChar('(') or AtomIsChar('['));
|
||||||
|
if not Result then exit;
|
||||||
|
repeat
|
||||||
|
if AtomIsIdentifier(false) then
|
||||||
|
ReadNextAtom;
|
||||||
|
if AtomIsChar('(') or AtomIsChar('[') then begin
|
||||||
|
Result:=ReadTilBracketClose(ExceptionOnError);
|
||||||
|
if not Result then exit;
|
||||||
|
end;
|
||||||
|
if AtomIsChar('.') then
|
||||||
|
ReadNextAtom
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
until false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPascalParserTool.ReadTilStatementEnd(ExceptionOnError,
|
||||||
|
CreateNodes: boolean): boolean;
|
||||||
|
// after reading the current atom will be on the last atom of the statement
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
if BlockStatementStartKeyWordFuncList.DoItUppercase(UpperSrc,CurPos.StartPos,
|
||||||
|
CurPos.EndPos-CurPos.StartPos) then
|
||||||
|
begin
|
||||||
|
if not ReadTilBlockEnd(ExceptionOnError,CreateNodes) then exit;
|
||||||
|
ReadNextAtom;
|
||||||
|
if not AtomIsChar(';') then UndoReadNextAtom;
|
||||||
|
end else if UpAtomIs('WITH') then begin
|
||||||
|
if not ReadWithStatement(ExceptionOnError,CreateNodes) then exit;
|
||||||
|
end else begin
|
||||||
|
// read till semicolon or 'end'
|
||||||
|
while (not AtomIsChar(';')) do begin
|
||||||
|
ReadNextAtom;
|
||||||
|
if UpAtomIs('END') then begin
|
||||||
|
UndoReadNextAtom;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPascalParserTool.ReadWithStatement(ExceptionOnError,
|
||||||
|
CreateNodes: boolean): boolean;
|
||||||
|
begin
|
||||||
|
ReadNextAtom;
|
||||||
|
if CreateNodes then begin
|
||||||
|
CreateChildNode;
|
||||||
|
CurNode.Desc:=ctnWithVariable
|
||||||
|
end;
|
||||||
|
ReadTilVariableEnd(true);
|
||||||
|
while AtomIsChar(',') do begin
|
||||||
|
CurNode.EndPos:=LastAtoms.GetValueAt(0).EndPos;
|
||||||
|
if CreateNodes then
|
||||||
|
EndChildNode;
|
||||||
|
ReadNextAtom;
|
||||||
|
if CreateNodes then begin
|
||||||
|
CreateChildNode;
|
||||||
|
CurNode.Desc:=ctnWithVariable
|
||||||
|
end;
|
||||||
|
ReadTilVariableEnd(true);
|
||||||
|
end;
|
||||||
|
if not UpAtomIs('DO') then begin
|
||||||
|
if ExceptionOnError then
|
||||||
|
RaiseException('syntax error: do expected, but '+GetAtom+' found')
|
||||||
|
else begin
|
||||||
|
Result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
ReadNextAtom;
|
||||||
|
if CreateNodes then begin
|
||||||
|
CreateChildNode;
|
||||||
|
CurNode.Desc:=ctnWithStatement;
|
||||||
|
end;
|
||||||
|
ReadTilStatementEnd(true,CreateNodes);
|
||||||
|
if CreateNodes then begin
|
||||||
|
CurNode.EndPos:=CurPos.StartPos;
|
||||||
|
EndChildNode; // ctnWithStatement
|
||||||
|
CurNode.EndPos:=CurPos.StartPos;
|
||||||
|
EndChildNode; // ctnWithVariable
|
||||||
|
end;
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPascalParserTool.KeyWordFuncBeginEnd: boolean;
|
function TPascalParserTool.KeyWordFuncBeginEnd: boolean;
|
||||||
// Keyword: begin, asm
|
// Keyword: begin, asm
|
||||||
var BeginKeyWord: shortstring;
|
var BeginKeyWord: shortstring;
|
||||||
@ -1632,7 +1791,7 @@ begin
|
|||||||
CurNode.Desc:=ctnAsmBlock;
|
CurNode.Desc:=ctnAsmBlock;
|
||||||
end;
|
end;
|
||||||
// search "end"
|
// search "end"
|
||||||
ReadTilBlockEnd(false);
|
ReadTilBlockEnd(false,false);
|
||||||
// close node
|
// close node
|
||||||
if ChildNodeCreated then begin
|
if ChildNodeCreated then begin
|
||||||
CurNode.EndPos:=CurPos.EndPos;
|
CurNode.EndPos:=CurPos.EndPos;
|
||||||
|
@ -1008,7 +1008,7 @@ writeln('TStandardCodeTool.FindBlockCounterPart C Word=',GetAtom);
|
|||||||
if UpAtomIs('BEGIN') or UpAtomIs('CASE') or UpAtomIs('ASM')
|
if UpAtomIs('BEGIN') or UpAtomIs('CASE') or UpAtomIs('ASM')
|
||||||
or UpAtomIs('RECORD') or UpAtomIs('TRY') or UpAtomIs('REPEAT') then begin
|
or UpAtomIs('RECORD') or UpAtomIs('TRY') or UpAtomIs('REPEAT') then begin
|
||||||
// read forward till END, FINALLY, EXCEPT
|
// read forward till END, FINALLY, EXCEPT
|
||||||
ReadTilBlockEnd(true);
|
ReadTilBlockEnd(true,false);
|
||||||
end else if UpAtomIs('END') or UpAtomIs('FINALLY') or UpAtomIs('EXCEPT')
|
end else if UpAtomIs('END') or UpAtomIs('FINALLY') or UpAtomIs('EXCEPT')
|
||||||
or UpAtomIs('UNTIL') then
|
or UpAtomIs('UNTIL') then
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user