xref: /aosp_15_r20/external/antlr/runtime/Delphi/Sources/Antlr3.Runtime/Antlr.Runtime.Collections.pas (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot unit Antlr.Runtime.Collections;
2*16467b97STreehugger Robot (*
3*16467b97STreehugger Robot [The "BSD licence"]
4*16467b97STreehugger Robot Copyright (c) 2008 Erik van Bilsen
5*16467b97STreehugger Robot Copyright (c) 2005-2007 Kunle Odutola
6*16467b97STreehugger Robot All rights reserved.
7*16467b97STreehugger Robot 
8*16467b97STreehugger Robot Redistribution and use in source and binary forms, with or without
9*16467b97STreehugger Robot modification, are permitted provided that the following conditions
10*16467b97STreehugger Robot are met:
11*16467b97STreehugger Robot 1. Redistributions of source code MUST RETAIN the above copyright
12*16467b97STreehugger Robot    notice, this list of conditions and the following disclaimer.
13*16467b97STreehugger Robot 2. Redistributions in binary form MUST REPRODUCE the above copyright
14*16467b97STreehugger Robot    notice, this list of conditions and the following disclaimer in
15*16467b97STreehugger Robot    the documentation and/or other materials provided with the
16*16467b97STreehugger Robot    distribution.
17*16467b97STreehugger Robot 3. The name of the author may not be used to endorse or promote products
18*16467b97STreehugger Robot    derived from this software without specific prior WRITTEN permission.
19*16467b97STreehugger Robot 4. Unless explicitly state otherwise, any contribution intentionally
20*16467b97STreehugger Robot    submitted for inclusion in this work to the copyright owner or licensor
21*16467b97STreehugger Robot    shall be under the terms and conditions of this license, without any
22*16467b97STreehugger Robot    additional terms or conditions.
23*16467b97STreehugger Robot 
24*16467b97STreehugger Robot THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25*16467b97STreehugger Robot IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26*16467b97STreehugger Robot OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27*16467b97STreehugger Robot IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28*16467b97STreehugger Robot INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29*16467b97STreehugger Robot NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30*16467b97STreehugger Robot DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31*16467b97STreehugger Robot THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*16467b97STreehugger Robot (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33*16467b97STreehugger Robot THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*16467b97STreehugger Robot *)
35*16467b97STreehugger Robot 
36*16467b97STreehugger Robot interface
37*16467b97STreehugger Robot 
38*16467b97STreehugger Robot {$IF CompilerVersion < 20}
39*16467b97STreehugger Robot {$MESSAGE ERROR 'You need Delphi 2009 or higher to use the Antlr runtime'}
40*16467b97STreehugger Robot {$IFEND}
41*16467b97STreehugger Robot 
42*16467b97STreehugger Robot uses
43*16467b97STreehugger Robot   Generics.Collections,
44*16467b97STreehugger Robot   Antlr.Runtime.Tools;
45*16467b97STreehugger Robot 
46*16467b97STreehugger Robot type
47*16467b97STreehugger Robot   /// <summary>
48*16467b97STreehugger Robot   /// An Hashtable-backed dictionary that enumerates Keys and Values in
49*16467b97STreehugger Robot   /// insertion order.
50*16467b97STreehugger Robot   /// </summary>
51*16467b97STreehugger Robot   IHashList<TKey, TValue> = interface(IDictionary<TKey, TValue>)
52*16467b97STreehugger Robot   end;
53*16467b97STreehugger Robot 
54*16467b97STreehugger Robot   /// <summary>
55*16467b97STreehugger Robot   /// Stack abstraction that also supports the IList interface
56*16467b97STreehugger Robot   /// </summary>
57*16467b97STreehugger Robot   IStackList<T> = interface(IList<T>)
58*16467b97STreehugger Robot     { Methods }
59*16467b97STreehugger Robot 
60*16467b97STreehugger Robot     /// <summary>
61*16467b97STreehugger Robot     /// Adds an element to the top of the stack list.
62*16467b97STreehugger Robot     /// </summary>
63*16467b97STreehugger Robot     procedure Push(const Item: T);
64*16467b97STreehugger Robot 
65*16467b97STreehugger Robot     /// <summary>
66*16467b97STreehugger Robot     /// Removes the element at the top of the stack list and returns it.
67*16467b97STreehugger Robot     /// </summary>
68*16467b97STreehugger Robot     /// <returns>The element at the top of the stack.</returns>
Pop()69*16467b97STreehugger Robot     function Pop: T;
70*16467b97STreehugger Robot 
71*16467b97STreehugger Robot     /// <summary>
72*16467b97STreehugger Robot     /// Removes the element at the top of the stack list without removing it.
73*16467b97STreehugger Robot     /// </summary>
74*16467b97STreehugger Robot     /// <returns>The element at the top of the stack.</returns>
Peek()75*16467b97STreehugger Robot     function Peek: T;
76*16467b97STreehugger Robot   end;
77*16467b97STreehugger Robot 
78*16467b97STreehugger Robot type
79*16467b97STreehugger Robot   THashList<TKey, TValue> = class(TANTLRObject, IHashList<TKey, TValue>)
80*16467b97STreehugger Robot   strict private
81*16467b97STreehugger Robot     type
82*16467b97STreehugger Robot       TPairEnumerator = class(TEnumerator<TPair<TKey, TValue>>)
83*16467b97STreehugger Robot       private
84*16467b97STreehugger Robot         FHashList: THashList<TKey, TValue>;
85*16467b97STreehugger Robot         FOrderList: IList<TKey>;
86*16467b97STreehugger Robot         FIndex: Integer;
87*16467b97STreehugger Robot         FVersion: Integer;
88*16467b97STreehugger Robot         FPair: TPair<TKey, TValue>;
GetCurrent()89*16467b97STreehugger Robot         function GetCurrent: TPair<TKey, TValue>;
90*16467b97STreehugger Robot       protected
DoGetCurrent()91*16467b97STreehugger Robot         function DoGetCurrent: TPair<TKey, TValue>; override;
DoMoveNext()92*16467b97STreehugger Robot         function DoMoveNext: Boolean; override;
93*16467b97STreehugger Robot       public
94*16467b97STreehugger Robot         constructor Create(const AHashList: THashList<TKey, TValue>);
MoveNext()95*16467b97STreehugger Robot         function MoveNext: Boolean;
96*16467b97STreehugger Robot         property Current: TPair<TKey, TValue> read GetCurrent;
97*16467b97STreehugger Robot       end;
98*16467b97STreehugger Robot   private
99*16467b97STreehugger Robot     FDictionary: IDictionary<TKey, TValue>;
100*16467b97STreehugger Robot     FInsertionOrderList: IList<TKey>;
101*16467b97STreehugger Robot     FVersion: Integer;
102*16467b97STreehugger Robot   protected
103*16467b97STreehugger Robot     { IDictionary<TKey, TValue> }
GetItem(const Key: TKey)104*16467b97STreehugger Robot     function GetItem(const Key: TKey): TValue;
105*16467b97STreehugger Robot     procedure SetItem(const Key: TKey; const Value: TValue);
GetCount()106*16467b97STreehugger Robot     function GetCount: Integer;
107*16467b97STreehugger Robot 
108*16467b97STreehugger Robot     procedure Add(const Key: TKey; const Value: TValue);
109*16467b97STreehugger Robot     procedure Remove(const Key: TKey);
110*16467b97STreehugger Robot     procedure Clear;
111*16467b97STreehugger Robot     procedure TrimExcess;
TryGetValue(const Key: TKey; out Value: TValue)112*16467b97STreehugger Robot     function TryGetValue(const Key: TKey; out Value: TValue): Boolean;
113*16467b97STreehugger Robot     procedure AddOrSetValue(const Key: TKey; const Value: TValue);
ContainsKey(const Key: TKey)114*16467b97STreehugger Robot     function ContainsKey(const Key: TKey): Boolean;
ContainsValue(const Value: TValue)115*16467b97STreehugger Robot     function ContainsValue(const Value: TValue): Boolean;
116*16467b97STreehugger Robot   public
117*16467b97STreehugger Robot     constructor Create; overload;
118*16467b97STreehugger Robot     constructor Create(const ACapacity: Integer); overload;
GetEnumerator()119*16467b97STreehugger Robot     function GetEnumerator: TEnumerator<TPair<TKey, TValue>>;
120*16467b97STreehugger Robot 
121*16467b97STreehugger Robot     property Items[const Key: TKey]: TValue read GetItem write SetItem; default;
122*16467b97STreehugger Robot   end;
123*16467b97STreehugger Robot 
124*16467b97STreehugger Robot   TStackList<T> = class(TList<T>, IStackList<T>)
125*16467b97STreehugger Robot   protected
126*16467b97STreehugger Robot     { IStackList<T> }
127*16467b97STreehugger Robot     procedure Push(const Item: T);
Pop()128*16467b97STreehugger Robot     function Pop: T;
Peek()129*16467b97STreehugger Robot     function Peek: T;
130*16467b97STreehugger Robot   end;
131*16467b97STreehugger Robot 
132*16467b97STreehugger Robot   TCollectionUtils = class
133*16467b97STreehugger Robot   public
134*16467b97STreehugger Robot     /// <summary>
135*16467b97STreehugger Robot     /// Returns a string representation of this IDictionary.
136*16467b97STreehugger Robot     /// </summary>
137*16467b97STreehugger Robot     /// <remarks>
138*16467b97STreehugger Robot     /// The string representation is a list of the collection's elements in the order
139*16467b97STreehugger Robot     /// they are returned by its enumerator, enclosed in curly brackets ("{}").
140*16467b97STreehugger Robot     /// The separator is a comma followed by a space i.e. ", ".
141*16467b97STreehugger Robot     /// </remarks>
142*16467b97STreehugger Robot     /// <param name="dict">Dictionary whose string representation will be returned</param>
143*16467b97STreehugger Robot     /// <returns>A string representation of the specified dictionary or "null"</returns>
DictionaryToString(const Dict: IDictionary<Integer, IList<IANTLRInterface>>)144*16467b97STreehugger Robot     class function DictionaryToString(const Dict: IDictionary<Integer, IList<IANTLRInterface>>): String; static;
145*16467b97STreehugger Robot 
146*16467b97STreehugger Robot     /// <summary>
147*16467b97STreehugger Robot     /// Returns a string representation of this IList.
148*16467b97STreehugger Robot     /// </summary>
149*16467b97STreehugger Robot     /// <remarks>
150*16467b97STreehugger Robot     /// The string representation is a list of the collection's elements in the order
151*16467b97STreehugger Robot     /// they are returned by its enumerator, enclosed in square brackets ("[]").
152*16467b97STreehugger Robot     /// The separator is a comma followed by a space i.e. ", ".
153*16467b97STreehugger Robot     /// </remarks>
154*16467b97STreehugger Robot     /// <param name="coll">Collection whose string representation will be returned</param>
155*16467b97STreehugger Robot     /// <returns>A string representation of the specified collection or "null"</returns>
ListToString(const Coll: IList<IANTLRInterface>)156*16467b97STreehugger Robot     class function ListToString(const Coll: IList<IANTLRInterface>): String; overload; static;
ListToString(const Coll: IList<String>)157*16467b97STreehugger Robot     class function ListToString(const Coll: IList<String>): String; overload; static;
158*16467b97STreehugger Robot   end;
159*16467b97STreehugger Robot 
160*16467b97STreehugger Robot implementation
161*16467b97STreehugger Robot 
162*16467b97STreehugger Robot uses
163*16467b97STreehugger Robot   Classes,
164*16467b97STreehugger Robot   SysUtils;
165*16467b97STreehugger Robot 
166*16467b97STreehugger Robot { THashList<TKey, TValue> }
167*16467b97STreehugger Robot 
168*16467b97STreehugger Robot procedure THashList<TKey, TValue>.Add(const Key: TKey; const Value: TValue);
169*16467b97STreehugger Robot begin
170*16467b97STreehugger Robot   FDictionary.Add(Key, Value);
171*16467b97STreehugger Robot   FInsertionOrderList.Add(Key);
172*16467b97STreehugger Robot   Inc(FVersion);
173*16467b97STreehugger Robot end;
174*16467b97STreehugger Robot 
175*16467b97STreehugger Robot procedure THashList<TKey, TValue>.AddOrSetValue(const Key: TKey;
176*16467b97STreehugger Robot   const Value: TValue);
177*16467b97STreehugger Robot begin
178*16467b97STreehugger Robot   if FDictionary.ContainsKey(Key) then
179*16467b97STreehugger Robot     SetItem(Key, Value)
180*16467b97STreehugger Robot   else
181*16467b97STreehugger Robot     Add(Key, Value);
182*16467b97STreehugger Robot end;
183*16467b97STreehugger Robot 
184*16467b97STreehugger Robot procedure THashList<TKey, TValue>.Clear;
185*16467b97STreehugger Robot begin
186*16467b97STreehugger Robot   FDictionary.Clear;
187*16467b97STreehugger Robot   FInsertionOrderList.Clear;
188*16467b97STreehugger Robot   Inc(FVersion);
189*16467b97STreehugger Robot end;
190*16467b97STreehugger Robot 
THashList(const Key: TKey)191*16467b97STreehugger Robot function THashList<TKey, TValue>.ContainsKey(const Key: TKey): Boolean;
192*16467b97STreehugger Robot begin
193*16467b97STreehugger Robot   Result := FDictionary.ContainsKey(Key);
194*16467b97STreehugger Robot end;
195*16467b97STreehugger Robot 
THashList(const Value: TValue)196*16467b97STreehugger Robot function THashList<TKey, TValue>.ContainsValue(const Value: TValue): Boolean;
197*16467b97STreehugger Robot begin
198*16467b97STreehugger Robot   Result := FDictionary.ContainsValue(Value);
199*16467b97STreehugger Robot end;
200*16467b97STreehugger Robot 
201*16467b97STreehugger Robot constructor THashList<TKey, TValue>.Create;
202*16467b97STreehugger Robot begin
203*16467b97STreehugger Robot   Create(-1);
204*16467b97STreehugger Robot end;
205*16467b97STreehugger Robot 
206*16467b97STreehugger Robot constructor THashList<TKey, TValue>.Create(const ACapacity: Integer);
207*16467b97STreehugger Robot begin
208*16467b97STreehugger Robot   inherited Create;
209*16467b97STreehugger Robot   if (ACapacity < 0) then
210*16467b97STreehugger Robot   begin
211*16467b97STreehugger Robot     FDictionary := TDictionary<TKey, TValue>.Create;
212*16467b97STreehugger Robot     FInsertionOrderList := TList<TKey>.Create;
213*16467b97STreehugger Robot   end
214*16467b97STreehugger Robot   else
215*16467b97STreehugger Robot   begin
216*16467b97STreehugger Robot     FDictionary := TDictionary<TKey, TValue>.Create(ACapacity);
217*16467b97STreehugger Robot     FInsertionOrderList := TList<TKey>.Create;
218*16467b97STreehugger Robot     FInsertionOrderList.Capacity := ACapacity;
219*16467b97STreehugger Robot   end;
220*16467b97STreehugger Robot end;
221*16467b97STreehugger Robot 
THashList()222*16467b97STreehugger Robot function THashList<TKey, TValue>.GetCount: Integer;
223*16467b97STreehugger Robot begin
224*16467b97STreehugger Robot   Result := FDictionary.Count;
225*16467b97STreehugger Robot end;
226*16467b97STreehugger Robot 
THashList()227*16467b97STreehugger Robot function THashList<TKey, TValue>.GetEnumerator: TEnumerator<TPair<TKey, TValue>>;
228*16467b97STreehugger Robot begin
229*16467b97STreehugger Robot   Result := TPairEnumerator.Create(Self);
230*16467b97STreehugger Robot end;
231*16467b97STreehugger Robot 
GetItemnull232*16467b97STreehugger Robot function THashList<TKey, TValue>.GetItem(const Key: TKey): TValue;
233*16467b97STreehugger Robot begin
234*16467b97STreehugger Robot   Result := FDictionary[Key];
235*16467b97STreehugger Robot end;
236*16467b97STreehugger Robot 
237*16467b97STreehugger Robot procedure THashList<TKey, TValue>.Remove(const Key: TKey);
238*16467b97STreehugger Robot begin
239*16467b97STreehugger Robot   FDictionary.Remove(Key);
240*16467b97STreehugger Robot   FInsertionOrderList.Remove(Key);
241*16467b97STreehugger Robot   Inc(FVersion);
242*16467b97STreehugger Robot end;
243*16467b97STreehugger Robot 
244*16467b97STreehugger Robot procedure THashList<TKey, TValue>.SetItem(const Key: TKey; const Value: TValue);
245*16467b97STreehugger Robot var
246*16467b97STreehugger Robot   IsNewEntry: Boolean;
247*16467b97STreehugger Robot begin
248*16467b97STreehugger Robot   IsNewEntry := (not FDictionary.ContainsKey(Key));
249*16467b97STreehugger Robot   FDictionary[Key] := Value;
250*16467b97STreehugger Robot   if (IsNewEntry) then
251*16467b97STreehugger Robot     FInsertionOrderList.Add(Key);
252*16467b97STreehugger Robot   Inc(FVersion);
253*16467b97STreehugger Robot end;
254*16467b97STreehugger Robot 
255*16467b97STreehugger Robot procedure THashList<TKey, TValue>.TrimExcess;
256*16467b97STreehugger Robot begin
257*16467b97STreehugger Robot   FDictionary.TrimExcess;
258*16467b97STreehugger Robot   FInsertionOrderList.Capacity := FDictionary.Count;
259*16467b97STreehugger Robot end;
260*16467b97STreehugger Robot 
THashList(const Key: TKey;261*16467b97STreehugger Robot function THashList<TKey, TValue>.TryGetValue(const Key: TKey;
262*16467b97STreehugger Robot   out Value: TValue): Boolean;
263*16467b97STreehugger Robot begin
264*16467b97STreehugger Robot   Result := FDictionary.TryGetValue(Key,Value);
265*16467b97STreehugger Robot end;
266*16467b97STreehugger Robot 
267*16467b97STreehugger Robot { THashList<TKey, TValue>.TPairEnumerator }
268*16467b97STreehugger Robot 
269*16467b97STreehugger Robot constructor THashList<TKey, TValue>.TPairEnumerator.Create(
270*16467b97STreehugger Robot   const AHashList: THashList<TKey, TValue>);
271*16467b97STreehugger Robot begin
272*16467b97STreehugger Robot   inherited Create;
273*16467b97STreehugger Robot   FHashList := AHashList;
274*16467b97STreehugger Robot   FVersion := FHashList.FVersion;
275*16467b97STreehugger Robot   FOrderList := FHashList.FInsertionOrderList;
276*16467b97STreehugger Robot end;
277*16467b97STreehugger Robot 
THashList()278*16467b97STreehugger Robot function THashList<TKey, TValue>.TPairEnumerator.DoGetCurrent: TPair<TKey, TValue>;
279*16467b97STreehugger Robot begin
280*16467b97STreehugger Robot   Result := GetCurrent;
281*16467b97STreehugger Robot end;
282*16467b97STreehugger Robot 
THashList()283*16467b97STreehugger Robot function THashList<TKey, TValue>.TPairEnumerator.DoMoveNext: Boolean;
284*16467b97STreehugger Robot begin
285*16467b97STreehugger Robot   Result := MoveNext;
286*16467b97STreehugger Robot end;
287*16467b97STreehugger Robot 
THashList()288*16467b97STreehugger Robot function THashList<TKey, TValue>.TPairEnumerator.GetCurrent: TPair<TKey, TValue>;
289*16467b97STreehugger Robot begin
290*16467b97STreehugger Robot   Result := FPair;
291*16467b97STreehugger Robot end;
292*16467b97STreehugger Robot 
THashList()293*16467b97STreehugger Robot function THashList<TKey, TValue>.TPairEnumerator.MoveNext: Boolean;
294*16467b97STreehugger Robot begin
295*16467b97STreehugger Robot   if (FVersion <> FHashList.FVersion) then
296*16467b97STreehugger Robot     raise EInvalidOperation.Create('Collection was modified; enumeration operation may not execute.');
297*16467b97STreehugger Robot   if (FIndex < FOrderList.Count) then
298*16467b97STreehugger Robot   begin
299*16467b97STreehugger Robot     FPair.Key := FOrderList[FIndex];
300*16467b97STreehugger Robot     FPair.Value := FHashList[FPair.Key];
301*16467b97STreehugger Robot     Inc(FIndex);
302*16467b97STreehugger Robot     Result := True;
303*16467b97STreehugger Robot   end
304*16467b97STreehugger Robot   else
305*16467b97STreehugger Robot   begin
306*16467b97STreehugger Robot     FPair.Key := Default(TKey);
307*16467b97STreehugger Robot     FPair.Value := Default(TValue);
308*16467b97STreehugger Robot     Result := False;
309*16467b97STreehugger Robot   end;
310*16467b97STreehugger Robot end;
311*16467b97STreehugger Robot 
312*16467b97STreehugger Robot { TStackList<T> }
313*16467b97STreehugger Robot 
TStackList()314*16467b97STreehugger Robot function TStackList<T>.Peek: T;
315*16467b97STreehugger Robot begin
316*16467b97STreehugger Robot   Result := GetItem(GetCount - 1);
317*16467b97STreehugger Robot end;
318*16467b97STreehugger Robot 
Popnull319*16467b97STreehugger Robot function TStackList<T>.Pop: T;
320*16467b97STreehugger Robot var
321*16467b97STreehugger Robot   I: Integer;
322*16467b97STreehugger Robot begin
323*16467b97STreehugger Robot   I := GetCount - 1;
324*16467b97STreehugger Robot   Result := GetItem(I);
325*16467b97STreehugger Robot   Delete(I);
326*16467b97STreehugger Robot end;
327*16467b97STreehugger Robot 
328*16467b97STreehugger Robot procedure TStackList<T>.Push(const Item: T);
329*16467b97STreehugger Robot begin
330*16467b97STreehugger Robot   Add(Item);
331*16467b97STreehugger Robot end;
332*16467b97STreehugger Robot 
333*16467b97STreehugger Robot { TCollectionUtils }
334*16467b97STreehugger Robot 
TCollectionUtils.DictionaryToString(335*16467b97STreehugger Robot class function TCollectionUtils.DictionaryToString(
336*16467b97STreehugger Robot   const Dict: IDictionary<Integer, IList<IANTLRInterface>>): String;
337*16467b97STreehugger Robot var
338*16467b97STreehugger Robot   SB: TStringBuilder;
339*16467b97STreehugger Robot   I: Integer;
340*16467b97STreehugger Robot   E: TPair<Integer, IList<IANTLRInterface>>;
341*16467b97STreehugger Robot begin
342*16467b97STreehugger Robot   SB := TStringBuilder.Create;
343*16467b97STreehugger Robot   try
344*16467b97STreehugger Robot     if Assigned(Dict) then
345*16467b97STreehugger Robot     begin
346*16467b97STreehugger Robot       SB.Append('{');
347*16467b97STreehugger Robot       I := 0;
348*16467b97STreehugger Robot       for E in Dict do
349*16467b97STreehugger Robot       begin
350*16467b97STreehugger Robot         if (I > 0) then
351*16467b97STreehugger Robot           SB.Append(', ');
352*16467b97STreehugger Robot         SB.AppendFormat('%d=%s', [E.Key, ListToString(E.Value)]);
353*16467b97STreehugger Robot         Inc(I);
354*16467b97STreehugger Robot       end;
355*16467b97STreehugger Robot       SB.Append('}');
356*16467b97STreehugger Robot     end
357*16467b97STreehugger Robot     else
358*16467b97STreehugger Robot       SB.Insert(0, 'null');
359*16467b97STreehugger Robot     Result := SB.ToString;
360*16467b97STreehugger Robot   finally
361*16467b97STreehugger Robot     SB.Free;
362*16467b97STreehugger Robot   end;
363*16467b97STreehugger Robot end;
364*16467b97STreehugger Robot 
TCollectionUtils.ListToString(365*16467b97STreehugger Robot class function TCollectionUtils.ListToString(
366*16467b97STreehugger Robot   const Coll: IList<IANTLRInterface>): String;
367*16467b97STreehugger Robot var
368*16467b97STreehugger Robot   SB: TStringBuilder;
369*16467b97STreehugger Robot   I: Integer;
370*16467b97STreehugger Robot   Element: IANTLRInterface;
371*16467b97STreehugger Robot   Dict: IDictionary<Integer, IList<IANTLRInterface>>;
372*16467b97STreehugger Robot   List: IList<IANTLRInterface>;
373*16467b97STreehugger Robot begin
374*16467b97STreehugger Robot   SB := TStringBuilder.Create;
375*16467b97STreehugger Robot   try
376*16467b97STreehugger Robot     if (Coll <> nil) then
377*16467b97STreehugger Robot     begin
378*16467b97STreehugger Robot       SB.Append('[');
379*16467b97STreehugger Robot       for I := 0 to Coll.Count - 1 do
380*16467b97STreehugger Robot       begin
381*16467b97STreehugger Robot         if (I > 0) then
382*16467b97STreehugger Robot           SB.Append(', ');
383*16467b97STreehugger Robot         Element := Coll[I];
384*16467b97STreehugger Robot         if (Element = nil) then
385*16467b97STreehugger Robot           SB.Append('null')
386*16467b97STreehugger Robot         else
387*16467b97STreehugger Robot         if Supports(Element, IDictionary<Integer, IList<IANTLRInterface>>, Dict) then
388*16467b97STreehugger Robot           SB.Append(DictionaryToString(Dict))
389*16467b97STreehugger Robot         else
390*16467b97STreehugger Robot         if Supports(Element, IList<IANTLRInterface>, List) then
391*16467b97STreehugger Robot           SB.Append(ListToString(List))
392*16467b97STreehugger Robot         else
393*16467b97STreehugger Robot           SB.Append(Element.ToString);
394*16467b97STreehugger Robot       end;
395*16467b97STreehugger Robot       SB.Append(']');
396*16467b97STreehugger Robot     end
397*16467b97STreehugger Robot     else
398*16467b97STreehugger Robot       SB.Insert(0, 'null');
399*16467b97STreehugger Robot     Result := SB.ToString;
400*16467b97STreehugger Robot   finally
401*16467b97STreehugger Robot     SB.Free;
402*16467b97STreehugger Robot   end;
403*16467b97STreehugger Robot end;
404*16467b97STreehugger Robot 
TCollectionUtils.ListToString(const Coll: IList<String>)405*16467b97STreehugger Robot class function TCollectionUtils.ListToString(const Coll: IList<String>): String;
406*16467b97STreehugger Robot var
407*16467b97STreehugger Robot   SB: TStringBuilder;
408*16467b97STreehugger Robot   I: Integer;
409*16467b97STreehugger Robot begin
410*16467b97STreehugger Robot   SB := TStringBuilder.Create;
411*16467b97STreehugger Robot   try
412*16467b97STreehugger Robot     if (Coll <> nil) then
413*16467b97STreehugger Robot     begin
414*16467b97STreehugger Robot       SB.Append('[');
415*16467b97STreehugger Robot       for I := 0 to Coll.Count - 1 do
416*16467b97STreehugger Robot       begin
417*16467b97STreehugger Robot         if (I > 0) then
418*16467b97STreehugger Robot           SB.Append(', ');
419*16467b97STreehugger Robot         SB.Append(Coll[I]);
420*16467b97STreehugger Robot       end;
421*16467b97STreehugger Robot       SB.Append(']');
422*16467b97STreehugger Robot     end
423*16467b97STreehugger Robot     else
424*16467b97STreehugger Robot       SB.Insert(0, 'null');
425*16467b97STreehugger Robot     Result := SB.ToString;
426*16467b97STreehugger Robot   finally
427*16467b97STreehugger Robot     SB.Free;
428*16467b97STreehugger Robot   end;
429*16467b97STreehugger Robot end;
430*16467b97STreehugger Robot 
431*16467b97STreehugger Robot end.
432