1 {
2  ***************************************************************************
3  *                                                                         *
4  *   This source is free software; you can redistribute it and/or modify   *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This code is distributed in the hope that it will be useful, but      *
10  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
12  *   General Public License for more details.                              *
13  *                                                                         *
14  *   A copy of the GNU General Public License is available on the World    *
15  *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
16  *   obtain it by writing to the Free Software Foundation,                 *
17  *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
18  *                                                                         *
19  ***************************************************************************
20 
21   Author: Mattias Gaertner
22 
23   Abstract:
24     - tree storing identifiers of other languages (e.g. javascript)
25     - identifier completion for other languages
26 }
27 unit OtherIdentifierTree;
28 
29 {$mode objfpc}{$H+}
30 
31 interface
32 
33 uses
34   Classes, SysUtils, FileProcs, CodeTree;
35 
36 type
37 
38   { TOtherIdentifierTreeNode }
39 
40   TOtherIdentifierTreeNode = class
41   public
42     Desc: TCodeTreeNodeDesc;
43     SubDesc: TCodeTreeNodeSubDesc;
44     Parent: TOtherIdentifierTreeNode;
45     NextSibling, PrevSibling: TOtherIdentifierTreeNode;
46     FirstChild, LastChild: TOtherIdentifierTreeNode;
47     constructor Create; virtual;
48     destructor Destroy; override;
49     procedure ClearChilds;
50     procedure AddLastChild(Child: TOtherIdentifierTreeNode); virtual;
51     procedure RemoveChild(Child: TOtherIdentifierTreeNode); virtual;
Nextnull52     function Next: TOtherIdentifierTreeNode;
NextSkipChildsnull53     function NextSkipChilds: TOtherIdentifierTreeNode;
Prevnull54     function Prev: TOtherIdentifierTreeNode;
PrevSkipChildsnull55     function PrevSkipChilds: TOtherIdentifierTreeNode;
HasAsParentnull56     function HasAsParent(Node: TOtherIdentifierTreeNode): boolean;
HasAsChildnull57     function HasAsChild(Node: TOtherIdentifierTreeNode): boolean;
HasParentOfTypenull58     function HasParentOfType(ParentDesc: TCodeTreeNodeDesc): boolean;
HasAsRootnull59     function HasAsRoot(RootNode: TOtherIdentifierTreeNode): boolean;
GetRootNodenull60     function GetRootNode: TOtherIdentifierTreeNode;
GetParentOfTypenull61     function GetParentOfType(ADesc: TCodeTreeNodeDesc): TOtherIdentifierTreeNode;
GetParentOfTypesnull62     function GetParentOfTypes(Descriptors: array of TCodeTreeNodeDesc): TOtherIdentifierTreeNode;
ChildCountnull63     function ChildCount: integer; virtual;
AsStringnull64     function AsString: string; virtual;
65     procedure ConsistencyCheck; virtual;
66     procedure WriteDebugReport(const Prefix: string; WithChilds: boolean); virtual;
67   end;
68 
69   TOtherIdentifierTree = class
70   public
71     Root: TOtherIdentifierTreeNode;
72     constructor Create;
73     destructor Destroy; override;
74     procedure ClearNodes;
75   end;
76 
77 implementation
78 
79 { TOtherIdentifierTreeNode }
80 
81 procedure TOtherIdentifierTreeNode.AddLastChild(Child: TOtherIdentifierTreeNode);
82 begin
83   Child.Parent:=Self;
84   if LastChild<>nil then
85     LastChild.NextSibling:=Child;
86   Child.PrevSibling:=LastChild;
87   LastChild:=Child;
88   if FirstChild=nil then FirstChild:=Child;
89 end;
90 
91 procedure TOtherIdentifierTreeNode.RemoveChild(Child: TOtherIdentifierTreeNode);
92 begin
93   if FirstChild=Child then FirstChild:=Child.NextSibling;
94   if LastChild=Child then LastChild:=Child.PrevSibling;
95   Child.Parent:=nil;
96 end;
97 
98 constructor TOtherIdentifierTreeNode.Create;
99 begin
100 
101 end;
102 
103 destructor TOtherIdentifierTreeNode.Destroy;
104 begin
105   ClearChilds;
106   if Parent<>nil then Parent.RemoveChild(Self);
107   if NextSibling<>nil then NextSibling.PrevSibling:=PrevSibling;
108   if PrevSibling<>nil then PrevSibling.NextSibling:=NextSibling;
109   PrevSibling:=nil;
110   NextSibling:=nil;
111   inherited Destroy;
112 end;
113 
114 procedure TOtherIdentifierTreeNode.ClearChilds;
115 begin
116   while LastChild<>nil do LastChild.Free;
117 end;
118 
Nextnull119 function TOtherIdentifierTreeNode.Next: TOtherIdentifierTreeNode;
120 begin
121   Result:=FirstChild;
122   if Result<>nil then exit;
123   Result:=NextSkipChilds;
124 end;
125 
NextSkipChildsnull126 function TOtherIdentifierTreeNode.NextSkipChilds: TOtherIdentifierTreeNode;
127 begin
128   Result:=Self;
129   while (Result<>nil) do begin
130     if Result.NextSibling<>nil then
131       exit(Result.NextSibling);
132     Result:=Result.Parent;
133   end;
134 end;
135 
Prevnull136 function TOtherIdentifierTreeNode.Prev: TOtherIdentifierTreeNode;
137 begin
138   if PrevSibling=nil then
139     Result:=Parent
140   else begin
141     Result:=PrevSibling;
142     while Result.LastChild<>nil do Result:=Result.LastChild;
143   end;
144 end;
145 
TOtherIdentifierTreeNode.PrevSkipChildsnull146 function TOtherIdentifierTreeNode.PrevSkipChilds: TOtherIdentifierTreeNode;
147 begin
148   if PrevSibling<>nil then
149     Result:=PrevSibling
150   else
151     Result:=Parent;
152 end;
153 
TOtherIdentifierTreeNode.HasAsParentnull154 function TOtherIdentifierTreeNode.HasAsParent(Node: TOtherIdentifierTreeNode
155   ): boolean;
156 var
157   CurNode: TOtherIdentifierTreeNode;
158 begin
159   CurNode:=Parent;
160   while CurNode<>nil do begin
161     if CurNode=Node then exit(true);
162     CurNode:=CurNode.Parent;
163   end;
164   Result:=false;
165 end;
166 
HasAsChildnull167 function TOtherIdentifierTreeNode.HasAsChild(Node: TOtherIdentifierTreeNode
168   ): boolean;
169 begin
170   Result:=(Node<>nil) and Node.HasAsParent(Self);
171 end;
172 
HasParentOfTypenull173 function TOtherIdentifierTreeNode.HasParentOfType(ParentDesc: TCodeTreeNodeDesc
174   ): boolean;
175 begin
176   Result:=GetParentOfType(ParentDesc)<>nil;
177 end;
178 
HasAsRootnull179 function TOtherIdentifierTreeNode.HasAsRoot(RootNode: TOtherIdentifierTreeNode
180   ): boolean;
181 begin
182   Result:=GetRootNode=RootNode;
183 end;
184 
GetRootNodenull185 function TOtherIdentifierTreeNode.GetRootNode: TOtherIdentifierTreeNode;
186 begin
187   Result:=Self;
188   while Result.Parent<>nil do Result:=Result.Parent;
189 end;
190 
GetParentOfTypenull191 function TOtherIdentifierTreeNode.GetParentOfType(ADesc: TCodeTreeNodeDesc
192   ): TOtherIdentifierTreeNode;
193 begin
194   Result:=Parent;
195   while (Result<>nil) do begin
196     if Result.Desc=ADesc then exit;
197     Result:=Result.Parent;
198   end;
199 end;
200 
TOtherIdentifierTreeNode.GetParentOfTypesnull201 function TOtherIdentifierTreeNode.GetParentOfTypes(
202   Descriptors: array of TCodeTreeNodeDesc): TOtherIdentifierTreeNode;
203 var
204   i: Integer;
205 begin
206   Result:=Parent;
207   while (Result<>nil) do begin
208     for i:=low(Descriptors) to high(Descriptors) do
209       if Result.Desc=Descriptors[i] then exit;
210     Result:=Result.Parent;
211   end;
212 end;
213 
TOtherIdentifierTreeNode.ChildCountnull214 function TOtherIdentifierTreeNode.ChildCount: integer;
215 var
216   Node: TOtherIdentifierTreeNode;
217 begin
218   Result:=0;
219   Node:=FirstChild;
220   while Node<>nil do begin
221     inc(Result);
222     Node:=Node.NextSibling;
223   end;
224 end;
225 
AsStringnull226 function TOtherIdentifierTreeNode.AsString: string;
227 begin
228   Result:=IntToStr(Desc);
229 end;
230 
231 procedure TOtherIdentifierTreeNode.ConsistencyCheck;
232 var
233   Node: TOtherIdentifierTreeNode;
234 begin
235   if (NextSibling=Self) then
236     raise Exception.Create('');
237   if (PrevSibling=Self) then
238     raise Exception.Create('');
239   if (NextSibling<>nil) and (NextSibling.PrevSibling<>Self) then
240     raise Exception.Create('');
241   if (PrevSibling<>nil) and (PrevSibling.NextSibling<>Self) then
242     raise Exception.Create('');
243   if Parent=Self then
244     raise Exception.Create('');
245 
246   if (FirstChild=nil)<>(LastChild=nil) then
247     raise Exception.Create('');
248   Node:=FirstChild;
249   while Node<>nil do begin
250     if Node.Parent<>Self then
251       raise Exception.Create('');
252     if (Node=FirstChild) and (Node.PrevSibling<>nil) then
253       raise Exception.Create('');
254     if (Node=LastChild) and (Node.NextSibling<>nil) then
255       raise Exception.Create('');
256     Node.ConsistencyCheck;
257     Node:=Node.NextSibling;
258   end;
259 end;
260 
261 procedure TOtherIdentifierTreeNode.WriteDebugReport(const Prefix: string;
262   WithChilds: boolean);
263 begin
264   writeln(Prefix,AsString);
265   if WithChilds then
266     WriteDebugReport(Prefix+'  ',true);
267 end;
268 
269 { TOtherIdentifierTree }
270 
271 constructor TOtherIdentifierTree.Create;
272 begin
273 
274 end;
275 
276 destructor TOtherIdentifierTree.Destroy;
277 begin
278   ClearNodes;
279   inherited Destroy;
280 end;
281 
282 procedure TOtherIdentifierTree.ClearNodes;
283 begin
284   FreeAndNil(Root);
285 end;
286 
287 end.
288 
289