1
-------------------------------------------------------------------------------
3
-- This unit is part of the @Asis2@ ASIS secondary library.
5
-- <STRONG>Copyright (c) 2003 by Thomas Wolf.</STRONG>
7
-- AdaBrowse is free software; you can redistribute it and/or modify it
8
-- under the terms of the GNU General Public License as published by the
9
-- Free Software Foundation; either version 2, or (at your option) any
10
-- later version. AdaBrowse is distributed in the hope that it will be
11
-- useful, but <EM>without any warranty</EM>; without even the implied
12
-- warranty of <EM>merchantability or fitness for a particular purpose.</EM>
13
-- See the GNU General Public License for more details. You should have
14
-- received a copy of the GNU General Public License with this distribution,
15
-- see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
16
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20
-- As a special exception from the GPL, if other files instantiate generics
21
-- from this unit, or you link this unit with other files to produce an
22
-- executable, this unit does not by itself cause the resulting executable
23
-- to be covered by the GPL. This exception does not however invalidate any
24
-- other reasons why the executable file might be covered by the GPL.
28
-- Thomas Wolf (TW) <E_MAIL>
32
-- An analogue to @Asis.Iterator.Traverse_Element@ that ensures that
33
-- @Post_Operation@s are called for "open" @Pre_Operation@s.
37
-- 11-JUL-2003 TW Initial version.
38
-- 14-JUL-2003 TW Added @Traverse_Levels@, @Traverse_List@,
39
-- @Traverse_Unit@, and @Traverse_Unit_Elements@.
41
-------------------------------------------------------------------------------
43
pragma License (Modified_GPL);
47
package Asis2.Iterators is
49
pragma Elaborate_Body;
51
type Control_Traversal is
52
(Continue_Traversal, -- = Asis.Continue.
53
Terminate_Current, -- = Asis.Abandon_Children.
54
Skip_Children, -- = Asis.Abandon_Children + Post.
55
Terminate_Current_And_Siblings, -- = Asis.Abandon_Siblings.
56
Skip_Siblings, -- = Asis.Abandon_Siblings + Post.
57
Unwind_Traversal, -- = "sticky" Skip_Siblings.
58
Stop_Traversal, -- = Asis.Terminate_Immediately + Post.
59
Terminate_Traversal -- = Asis.Terminate_Immediately.
61
-- The names of these enumeration values have been chosen deliberately
62
-- such that they do not clash with the literals declared for the type
63
-- @Asis.Traverse_Control@.
66
-- <DT>@Continue_Traversal@
67
-- <DD>Like @Asis.Continue@. Keep going with normal depth-first
70
-- <DT>@Terminate_Current@
71
-- <DD>Exactly like @Asis.Abandon_Children@, i.e. if set in the
72
-- @Pre_Operation@, the corresponding @Post_Operation@ is
73
-- <STRONG><EM>not</EM></STRONG> called!
75
-- <DT>@Skip_Children@
76
-- <DD>Similar to @Asis.Abandon_Children@. If set in a @Pre_Operation@,
77
-- skips the children of the current element and then invokes the
78
-- @Post_Operation@ of the current element with @Control@ =
81
-- If @Control@ is @Skip_Siblings@ after a @Post_Operation@,
82
-- this is equivalent to @Continue_Traversal@.
84
-- <DT>@Terminate_Current_And_Siblings@
85
-- <DD>Exactly like @Asis.Abandon_Siblings@, i.e. if set in the
86
-- @Pre_Operation@, the corresponding @Post_Operation@ is
87
-- <STRONG><EM>not</EM></STRONG> called!
89
-- <DT>@Skip_Siblings@
90
-- <DD>Similar to @Asis.Abandon_Siblings@. If set in a @Pre_Operation@,
91
-- skips the children of the current element and then invokes the
92
-- @Post_Operation@ of the current element with @Control@ =
95
-- If @Control@ is @Skip_Siblings@ after a @Post_Operation@,
96
-- traversal skips the remaining sibling elements and picks up
97
-- again at the @Post_Operation@ of the parent element with
98
-- @Control@ = @Continue_Traversal@.
100
-- <DT>@Unwind_Traversal@
101
-- <DD>Stops traversing and unwinds, calling all the @Post_Operations@
102
-- for which the corresponding @Pre_Operations@ had already been
103
-- called (and the corresponding @Post_Operation@ has <EM>not</EM>
106
-- If set in @Pre_Operation@, skips the children of the current
107
-- element and then invokes the @Post_Operation@ of the current
108
-- element with @Control@ = @Unwind_Traversal@.
110
-- If @Control@ is @Unwind_Traversal@ after a @Post_Operation@,
111
-- traversal skips the remaining sibling elements and picks up
112
-- again at the @Post_Operation@ of the parent element with
113
-- @Control@ = @Unwind_Traversal@.
115
-- (@Unwind_Traversal@ is a "sticky" @Skip_Siblings@.)
117
-- <DT>@Stop_Traversal@
118
-- <DD>Similar to @Asis.Terminate_Immediately@, but if called in a
119
-- @Pre_Operation@, skips the current element's children and then
120
-- <EM>does</EM> call the corresponding @Post_Operation@ with
121
-- @Control@ = @Stop_Traversal@.
123
-- If @Control@ is @Stop_Traversal@ after a @Post_Operation@,
124
-- this is equivalent to @Terminate_Traversal@.
126
-- This is like @Terminate_Traversal@, but using the corresponding
127
-- @Post_Operation@ as a "last rites" handler that may override
128
-- the decision to stop traversing.
130
-- Setting @Stop_Traversal@ in a @Pre_Operation@ is a short-hand
131
-- for setting @Unwind_Traversal@ in the @Pre_Operation@ and then
132
-- setting @Terminate_Traversal@ in the corresponding
135
-- <DT>@Terminate_Traversal@
136
-- <DD>Like @Asis.Terminate_Immediately@. Immediately and irrevokably
137
-- stops traversing. No operation will be called anymore.
140
-- The difference to the standard ASIS iterator scheme is that this
141
-- iterator will always call the @Post_Operation@ if the corresponding
142
-- @Pre_Operation@ has been called (unless @Control@ = @Stop_Traversal@),
143
-- whereas the standard iterator does <EM>not</EM> call the
144
-- @Post_Operation@ of an element if @Control@ is set in that
145
-- element's @Pre_Operation@ to @Abandon_Children@ or @Abandon_Siblings@.
147
-- Using @Terminate_Current@ or @Terminate_Current_And_Siblings@, the
148
-- original behavior of the standard @Asis.Iterator.Traverse_Element@ is
152
type State_Information (<>) is limited private;
154
with procedure Pre_Operation
155
(Element : in Asis.Element;
156
Control : in out Control_Traversal;
157
State : in out State_Information) is <>;
159
with procedure Post_Operation
160
(Element : in Asis.Element;
161
Control : in out Control_Traversal;
162
State : in out State_Information) is <>;
164
procedure Traverse_Element
165
(Element : in Asis.Element;
166
Control : in out Control_Traversal;
167
State : in out State_Information);
168
-- Does a depth-first traversal of the element tree rooted at @Element@.
169
-- Calls the @Pre_Operation@ for each element in the tree before
170
-- descending further, and the @Post_Operation@ after having processed
173
-- Traversal can be fine-tuned by setting @Control@ as appropriate.
175
-- The @State@ is passed on untouched to the @Pre_Operation@s and the
176
-- @Post_Operations@.
178
-- Note that you can instantiate this iterator for any type, even an
179
-- unconstrained type.
181
-- Upon return, @Control@ is one of @Continue_Traversal@, @Skip_Siblings@,
182
-- @Unwind_Traversal@, or @Terminate_Traversal@. (Especially
183
-- @Skip_Siblings@ is useful when traversing an element list explicitly.)
185
-- The @Pre_Operation@ is always called with @Control@ =
186
-- @Continue_Traversal@.
188
-- The @Post_Operation@ is called with @Control@ one of
189
-- @Continue_Traversal@, @Skip_Children@, @Skip_Siblings@,
190
-- @Unwind_Traversal@, or @Stop_Traversal@.
193
type State_Information (<>) is limited private;
195
with procedure Pre_Operation
196
(Element : in Asis.Element;
197
Depth : in Asis.ASIS_Positive;
198
Control : in out Control_Traversal;
199
State : in out State_Information) is <>;
201
with procedure Post_Operation
202
(Element : in Asis.Element;
203
Depth : in Asis.ASIS_Positive;
204
Control : in out Control_Traversal;
205
State : in out State_Information) is <>;
207
procedure Traverse_Levels
208
(Element : in Asis.Element;
209
Control : in out Control_Traversal;
210
State : in out State_Information);
211
-- Like @Traverse_Element@, but also maintains a depth count.
212
-- @Depth@ = @1@ signifies top-level, i.e. the invocations of
213
-- @Pre_Operation@ or @Post_Operation@ for the actual parameter
217
type State_Information (<>) is limited private;
219
with procedure Process_Element
220
(Element : in Asis.Element;
221
Control : in out Control_Traversal;
222
State : in out State_Information) is <>;
224
procedure Traverse_List
225
(Elements : in Asis.Element_List;
226
Control : in out Control_Traversal;
227
State : in out State_Information);
228
-- Equivalent to the code
230
-- for I in Elements'Range loop
231
-- Process_Element (Elements (I), Control, State);
232
-- exit when Control /= Continue_Traversal;
236
-- Note that setting @Control@ to @Skip_Siblings@ or
237
-- @Terminate_Current_And_Siblings@ on an element skips the remaining
238
-- elements in the list.
241
type State_Information (<>) is limited private;
243
with procedure Pre_Operation
244
(Element : in Asis.Element;
245
Control : in out Control_Traversal;
246
State : in out State_Information) is <>;
248
with procedure Post_Operation
249
(Element : in Asis.Element;
250
Control : in out Control_Traversal;
251
State : in out State_Information) is <>;
253
procedure Traverse_Unit
254
(Element : in Asis.Compilation_Unit;
255
Control : in out Control_Traversal;
256
State : in out State_Information;
257
Include_Pragmas : in Boolean := False);
258
-- Slightly generalized version of @Traverse_Element@. Traverses the
259
-- <EM>unit</EM>, i.e. the configuration pragmas, compilation pragmas,
260
-- context clauses (and pragmas), and then the unit declaration (in that
261
-- order). The semantics of @Control@ is as for @Traverse_Element@.
263
-- Setting @Control@ to @Skip_Siblings@ in the @Pre_Operation@ or the
264
-- @Post_Operation@ of a configuration pragmas makes @Traverse_Unit@
265
-- skip the remaining configuration pragmas and continue with the first
266
-- compilation pragma. Setting @Skip_Siblings@ on a compilation pragma
267
-- skips the remaining compilation pragmas and continues with the first
268
-- context clause; and setting it on a context clause skips the remaining
269
-- context clauses and continues with the unit declaration element.
271
-- If @Include_Pragmas@ is @False@, configuration and compilation pragmas
272
-- are not traversed at all, only the context clauses and the unit element
273
-- are. If @Include_Pragmas@ is @True@, the pragmas <EM>are</EM> traversed.
274
-- Pragmas within the context clauses always are included in the traversal.
277
type State_Information (<>) is limited private;
279
with procedure Process_Element
280
(Element : in Asis.Element;
281
Control : in out Control_Traversal;
282
State : in out State_Information) is <>;
284
procedure Traverse_Unit_Elements
285
(Element : in Asis.Compilation_Unit;
286
Control : in out Control_Traversal;
287
State : in out State_Information;
288
Include_Pragmas : in Boolean := False);
289
-- Like @Traverse_Unit@, but using @Process_Element@ (which could e.g. be
290
-- an instantiation of @Traverse_Element@ of @Traverse_Levels@) to process
291
-- the child elements of the unit.