Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2002-2003 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2002-2003 Hartmut Kaiser
|
Chris@16
|
4 http://spirit.sourceforge.net/
|
Chris@16
|
5
|
Chris@16
|
6 Use, modification and distribution is subject to the Boost Software
|
Chris@16
|
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
8 http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 =============================================================================*/
|
Chris@16
|
10 #if !defined(BOOST_SPIRIT_TRAVERSE_IPP)
|
Chris@16
|
11 #define BOOST_SPIRIT_TRAVERSE_IPP
|
Chris@16
|
12
|
Chris@16
|
13 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
14 #include <boost/spirit/home/classic/meta/fundamental.hpp>
|
Chris@16
|
15
|
Chris@16
|
16 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
17 namespace boost { namespace spirit {
|
Chris@16
|
18
|
Chris@16
|
19 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
Chris@16
|
20
|
Chris@16
|
21 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
22 namespace impl
|
Chris@16
|
23 {
|
Chris@16
|
24
|
Chris@16
|
25 template <typename CategoryT>
|
Chris@16
|
26 struct traverse_post_order_return_category;
|
Chris@16
|
27
|
Chris@16
|
28 } // namespace impl
|
Chris@16
|
29
|
Chris@16
|
30 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
31 //
|
Chris@16
|
32 // Environment class for post_order_traversal
|
Chris@16
|
33 //
|
Chris@16
|
34 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
35
|
Chris@16
|
36 template <int Level, int Node, int Index, int LastLeft>
|
Chris@16
|
37 struct traverse_post_order_env {
|
Chris@16
|
38
|
Chris@16
|
39 BOOST_STATIC_CONSTANT(int, level = Level);
|
Chris@16
|
40 BOOST_STATIC_CONSTANT(int, node = Node);
|
Chris@16
|
41 BOOST_STATIC_CONSTANT(int, index = Index);
|
Chris@16
|
42 BOOST_STATIC_CONSTANT(int, lastleft = LastLeft);
|
Chris@16
|
43 };
|
Chris@16
|
44
|
Chris@16
|
45 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
46 //
|
Chris@16
|
47 // traverse_post_order_return template
|
Chris@16
|
48 //
|
Chris@16
|
49 // This template is a helper for dispatching the calculation of a parser
|
Chris@16
|
50 // type result for a traversal level to the corresponding parser_category
|
Chris@16
|
51 // based specialization.
|
Chris@16
|
52 //
|
Chris@16
|
53 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
54
|
Chris@16
|
55 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
56 struct traverse_post_order_return {
|
Chris@16
|
57
|
Chris@16
|
58 typedef typename ParserT::parser_category_t parser_category_t;
|
Chris@16
|
59 typedef typename impl::traverse_post_order_return_category<parser_category_t>
|
Chris@16
|
60 ::template result<MetaT, ParserT, EnvT>::type type;
|
Chris@16
|
61 };
|
Chris@16
|
62
|
Chris@16
|
63 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
64 //
|
Chris@16
|
65 // parser_traversal_..._result templates
|
Chris@16
|
66 //
|
Chris@16
|
67 // These are metafunctions, which calculate the resulting parser type
|
Chris@16
|
68 // for all subparsers and feed these types to the user supplied
|
Chris@16
|
69 // metafunctions to get back the resulting parser type of this traversal
|
Chris@16
|
70 // level.
|
Chris@16
|
71 //
|
Chris@16
|
72 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
73
|
Chris@16
|
74 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
75 struct parser_traversal_plain_result {
|
Chris@16
|
76
|
Chris@16
|
77 typedef typename MetaT::template plain_result<ParserT, EnvT>::type type;
|
Chris@16
|
78 };
|
Chris@16
|
79
|
Chris@16
|
80 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
81 template <typename MetaT, typename UnaryT, typename SubjectT, typename EnvT>
|
Chris@16
|
82 struct parser_traversal_unary_result {
|
Chris@16
|
83
|
Chris@16
|
84 typedef typename MetaT
|
Chris@16
|
85 ::template unary_result<UnaryT, SubjectT, EnvT>::type type;
|
Chris@16
|
86 };
|
Chris@16
|
87
|
Chris@16
|
88 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
89 template <typename MetaT, typename ActionT, typename SubjectT, typename EnvT>
|
Chris@16
|
90 struct parser_traversal_action_result {
|
Chris@16
|
91
|
Chris@16
|
92 typedef typename MetaT
|
Chris@16
|
93 ::template action_result<ActionT, SubjectT, EnvT>::type type;
|
Chris@16
|
94 };
|
Chris@16
|
95
|
Chris@16
|
96 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
97 template <
|
Chris@16
|
98 typename MetaT, typename BinaryT, typename LeftT,
|
Chris@16
|
99 typename RightT, typename EnvT
|
Chris@16
|
100 >
|
Chris@16
|
101 struct parser_traversal_binary_result {
|
Chris@16
|
102
|
Chris@16
|
103 BOOST_STATIC_CONSTANT(int,
|
Chris@16
|
104 thisnum = (node_count<BinaryT>::value + EnvT::lastleft-1));
|
Chris@16
|
105 BOOST_STATIC_CONSTANT(int,
|
Chris@16
|
106 leftnum = (node_count<LeftT>::value + EnvT::lastleft-1));
|
Chris@16
|
107 BOOST_STATIC_CONSTANT(int,
|
Chris@16
|
108 leafnum = (leaf_count<LeftT>::value + EnvT::index));
|
Chris@16
|
109
|
Chris@16
|
110 typedef parser_traversal_binary_result self_t;
|
Chris@16
|
111
|
Chris@16
|
112 // left traversal environment and resulting parser type
|
Chris@16
|
113 typedef traverse_post_order_env<
|
Chris@16
|
114 (EnvT::level+1), (self_t::leftnum), (EnvT::index), (EnvT::lastleft)
|
Chris@16
|
115 > left_sub_env_t;
|
Chris@16
|
116 typedef typename traverse_post_order_return<
|
Chris@16
|
117 MetaT, LeftT, left_sub_env_t
|
Chris@16
|
118 >::type
|
Chris@16
|
119 left_t;
|
Chris@16
|
120
|
Chris@16
|
121 // right traversal environment and resulting parser type
|
Chris@16
|
122 typedef traverse_post_order_env<
|
Chris@16
|
123 (EnvT::level+1), (self_t::thisnum-1), (self_t::leafnum), (self_t::leftnum+1)
|
Chris@16
|
124 > right_sub_env_t;
|
Chris@16
|
125 typedef typename traverse_post_order_return<
|
Chris@16
|
126 MetaT, RightT, right_sub_env_t
|
Chris@16
|
127 >::type
|
Chris@16
|
128 right_t;
|
Chris@16
|
129
|
Chris@16
|
130 typedef typename MetaT::template binary_result<
|
Chris@16
|
131 BinaryT, left_t, right_t, EnvT
|
Chris@16
|
132 >::type
|
Chris@16
|
133 type;
|
Chris@16
|
134 };
|
Chris@16
|
135
|
Chris@16
|
136 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
137 namespace impl
|
Chris@16
|
138 {
|
Chris@16
|
139 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
140 //
|
Chris@16
|
141 // Meta functions, which dispatch the calculation of the return type of
|
Chris@16
|
142 // of the post_order traverse function to the result template of the
|
Chris@16
|
143 // corresponding parser_category based metafunction template.
|
Chris@16
|
144 //
|
Chris@16
|
145 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
146
|
Chris@16
|
147 template <typename CategoryT>
|
Chris@16
|
148 struct traverse_post_order_return_category;
|
Chris@16
|
149
|
Chris@16
|
150 template <>
|
Chris@16
|
151 struct traverse_post_order_return_category<plain_parser_category> {
|
Chris@16
|
152
|
Chris@16
|
153 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
154 struct result {
|
Chris@16
|
155
|
Chris@16
|
156 typedef typename parser_traversal_plain_result<
|
Chris@16
|
157 MetaT, ParserT, EnvT
|
Chris@16
|
158 >::type
|
Chris@16
|
159 type;
|
Chris@16
|
160 };
|
Chris@16
|
161 };
|
Chris@16
|
162
|
Chris@16
|
163 template <>
|
Chris@16
|
164 struct traverse_post_order_return_category<unary_parser_category> {
|
Chris@16
|
165
|
Chris@16
|
166 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
167 struct result {
|
Chris@16
|
168
|
Chris@16
|
169 typedef typename parser_traversal_unary_result<
|
Chris@16
|
170 MetaT, ParserT, typename ParserT::subject_t, EnvT
|
Chris@16
|
171 >::type
|
Chris@16
|
172 type;
|
Chris@16
|
173 };
|
Chris@16
|
174 };
|
Chris@16
|
175
|
Chris@16
|
176 template <>
|
Chris@16
|
177 struct traverse_post_order_return_category<action_parser_category> {
|
Chris@16
|
178
|
Chris@16
|
179 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
180 struct result {
|
Chris@16
|
181
|
Chris@16
|
182 typedef typename parser_traversal_action_result<
|
Chris@16
|
183 MetaT, ParserT, typename ParserT::subject_t, EnvT
|
Chris@16
|
184 >::type
|
Chris@16
|
185 type;
|
Chris@16
|
186 };
|
Chris@16
|
187 };
|
Chris@16
|
188
|
Chris@16
|
189 template <>
|
Chris@16
|
190 struct traverse_post_order_return_category<binary_parser_category> {
|
Chris@16
|
191
|
Chris@16
|
192 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
193 struct result {
|
Chris@16
|
194
|
Chris@16
|
195 typedef typename parser_traversal_binary_result<
|
Chris@16
|
196 MetaT, ParserT, typename ParserT::left_t,
|
Chris@16
|
197 typename ParserT::right_t, EnvT
|
Chris@16
|
198 >::type
|
Chris@16
|
199 type;
|
Chris@16
|
200 };
|
Chris@16
|
201 };
|
Chris@16
|
202
|
Chris@16
|
203 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
204 //
|
Chris@16
|
205 // Post-order parser traversal
|
Chris@16
|
206 //
|
Chris@16
|
207 // The following templates contain the parser_category based code for
|
Chris@16
|
208 //
|
Chris@16
|
209 // - calculating the type of the resulting parser, which is to be
|
Chris@16
|
210 // returned from a level of traversal
|
Chris@16
|
211 // - traversing down the composite parser structure, this traversal
|
Chris@16
|
212 // returnes a new parser object
|
Chris@16
|
213 //
|
Chris@16
|
214 // Both tasks are delegated to the MetaT metafunction supplied by the
|
Chris@16
|
215 // user.
|
Chris@16
|
216 //
|
Chris@16
|
217 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
218
|
Chris@16
|
219 template <typename CategoryT>
|
Chris@16
|
220 struct traverse_post_order;
|
Chris@16
|
221
|
Chris@16
|
222 template <>
|
Chris@16
|
223 struct traverse_post_order<plain_parser_category> {
|
Chris@16
|
224
|
Chris@16
|
225 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
226 struct result {
|
Chris@16
|
227
|
Chris@16
|
228 typedef
|
Chris@16
|
229 typename parser_traversal_plain_result<MetaT, ParserT, EnvT>::type
|
Chris@16
|
230 type;
|
Chris@16
|
231 };
|
Chris@16
|
232
|
Chris@16
|
233 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
234 static
|
Chris@16
|
235 typename parser_traversal_plain_result<MetaT, ParserT, EnvT>::type
|
Chris@16
|
236 generate(MetaT const &meta_, ParserT const &parser_, EnvT const &env)
|
Chris@16
|
237 {
|
Chris@16
|
238 return meta_.generate_plain(parser_, env);
|
Chris@16
|
239 }
|
Chris@16
|
240 };
|
Chris@16
|
241
|
Chris@16
|
242 template <>
|
Chris@16
|
243 struct traverse_post_order<unary_parser_category> {
|
Chris@16
|
244
|
Chris@16
|
245 template <
|
Chris@16
|
246 typename MetaT, typename ParserT, typename SubjectT, typename EnvT
|
Chris@16
|
247 >
|
Chris@16
|
248 struct result {
|
Chris@16
|
249
|
Chris@16
|
250 typedef typename parser_traversal_unary_result<
|
Chris@16
|
251 MetaT, ParserT, SubjectT, EnvT
|
Chris@16
|
252 >::type
|
Chris@16
|
253 type;
|
Chris@16
|
254 };
|
Chris@16
|
255
|
Chris@16
|
256 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
257 static
|
Chris@16
|
258 typename parser_traversal_unary_result<
|
Chris@16
|
259 MetaT, ParserT,
|
Chris@16
|
260 typename traverse_post_order_return<
|
Chris@16
|
261 MetaT, typename ParserT::subject_t, EnvT
|
Chris@16
|
262 >::type,
|
Chris@16
|
263 EnvT
|
Chris@16
|
264 >::type
|
Chris@16
|
265 generate(MetaT const &meta_, ParserT const &unary_, EnvT const &env)
|
Chris@16
|
266 {
|
Chris@16
|
267 typedef typename ParserT::subject_t subject_t;
|
Chris@16
|
268 typedef typename subject_t::parser_category_t subject_category_t;
|
Chris@16
|
269
|
Chris@16
|
270 return meta_.generate_unary(
|
Chris@16
|
271 unary_,
|
Chris@16
|
272 traverse_post_order<subject_category_t>::generate(meta_,
|
Chris@16
|
273 unary_.subject(),
|
Chris@16
|
274 traverse_post_order_env<
|
Chris@16
|
275 EnvT::level+1, EnvT::node-1, EnvT::index, EnvT::lastleft
|
Chris@16
|
276 >()
|
Chris@16
|
277 ),
|
Chris@16
|
278 env
|
Chris@16
|
279 );
|
Chris@16
|
280 }
|
Chris@16
|
281 };
|
Chris@16
|
282
|
Chris@16
|
283 template <>
|
Chris@16
|
284 struct traverse_post_order<action_parser_category> {
|
Chris@16
|
285
|
Chris@16
|
286 template <
|
Chris@16
|
287 typename MetaT, typename ParserT, typename SubjectT, typename EnvT
|
Chris@16
|
288 >
|
Chris@16
|
289 struct result {
|
Chris@16
|
290
|
Chris@16
|
291 typedef typename parser_traversal_action_result<
|
Chris@16
|
292 MetaT, ParserT, SubjectT, EnvT
|
Chris@16
|
293 >::type
|
Chris@16
|
294 type;
|
Chris@16
|
295 };
|
Chris@16
|
296
|
Chris@16
|
297 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
298 static
|
Chris@16
|
299 typename parser_traversal_action_result<
|
Chris@16
|
300 MetaT, ParserT,
|
Chris@16
|
301 typename traverse_post_order_return<
|
Chris@16
|
302 MetaT, typename ParserT::subject_t, EnvT
|
Chris@16
|
303 >::type,
|
Chris@16
|
304 EnvT
|
Chris@16
|
305 >::type
|
Chris@16
|
306 generate(MetaT const &meta_, ParserT const &action_, EnvT const &env)
|
Chris@16
|
307 {
|
Chris@16
|
308 typedef typename ParserT::subject_t subject_t;
|
Chris@16
|
309 typedef typename subject_t::parser_category_t subject_category_t;
|
Chris@16
|
310
|
Chris@16
|
311 return meta_.generate_action(
|
Chris@16
|
312 action_,
|
Chris@16
|
313 traverse_post_order<subject_category_t>::generate(meta_,
|
Chris@16
|
314 action_.subject(),
|
Chris@16
|
315 traverse_post_order_env<
|
Chris@16
|
316 EnvT::level+1, EnvT::node-1, EnvT::index, EnvT::lastleft
|
Chris@16
|
317 >()
|
Chris@16
|
318 ),
|
Chris@16
|
319 env
|
Chris@16
|
320 );
|
Chris@16
|
321 }
|
Chris@16
|
322 };
|
Chris@16
|
323
|
Chris@16
|
324 template <>
|
Chris@16
|
325 struct traverse_post_order<binary_parser_category> {
|
Chris@16
|
326
|
Chris@16
|
327 template <
|
Chris@16
|
328 typename MetaT, typename ParserT, typename LeftT,
|
Chris@16
|
329 typename RightT, typename EnvT
|
Chris@16
|
330 >
|
Chris@16
|
331 struct result {
|
Chris@16
|
332
|
Chris@16
|
333 typedef typename parser_traversal_binary_result<
|
Chris@16
|
334 MetaT, ParserT, LeftT, RightT, EnvT
|
Chris@16
|
335 >::type
|
Chris@16
|
336 type;
|
Chris@16
|
337 };
|
Chris@16
|
338
|
Chris@16
|
339 template <typename MetaT, typename ParserT, typename EnvT>
|
Chris@16
|
340 static
|
Chris@16
|
341 typename parser_traversal_binary_result<
|
Chris@16
|
342 MetaT, ParserT,
|
Chris@16
|
343 typename traverse_post_order_return<
|
Chris@16
|
344 MetaT, typename ParserT::left_t, EnvT
|
Chris@16
|
345 >::type,
|
Chris@16
|
346 typename traverse_post_order_return<
|
Chris@16
|
347 MetaT, typename ParserT::right_t, EnvT
|
Chris@16
|
348 >::type,
|
Chris@16
|
349 EnvT
|
Chris@16
|
350 >::type
|
Chris@16
|
351 generate(MetaT const &meta_, ParserT const &binary_, EnvT const& /*env*/)
|
Chris@16
|
352 {
|
Chris@16
|
353 typedef typename ParserT::left_t left_t;
|
Chris@16
|
354 typedef typename ParserT::right_t right_t;
|
Chris@16
|
355 typedef typename left_t::parser_category_t left_category_t;
|
Chris@16
|
356 typedef typename right_t::parser_category_t right_category_t;
|
Chris@16
|
357
|
Chris@16
|
358 enum {
|
Chris@16
|
359 leftnum = (node_count<left_t>::value + EnvT::lastleft-1),
|
Chris@16
|
360 thisnum = (node_count<ParserT>::value + EnvT::lastleft-1),
|
Chris@16
|
361 rightnum = (thisnum-1),
|
Chris@16
|
362 leafnum = (leaf_count<left_t>::value + EnvT::index)
|
Chris@16
|
363 };
|
Chris@16
|
364
|
Chris@16
|
365 return meta_.generate_binary(
|
Chris@16
|
366 binary_,
|
Chris@16
|
367 traverse_post_order<left_category_t>::generate(
|
Chris@16
|
368 meta_, binary_.left(),
|
Chris@16
|
369 traverse_post_order_env<
|
Chris@16
|
370 EnvT::level+1, leftnum, EnvT::index, EnvT::lastleft
|
Chris@16
|
371 >()
|
Chris@16
|
372 ),
|
Chris@16
|
373 traverse_post_order<right_category_t>::generate(
|
Chris@16
|
374 meta_, binary_.right(),
|
Chris@16
|
375 traverse_post_order_env<
|
Chris@16
|
376 EnvT::level+1, rightnum, leafnum, leftnum+1
|
Chris@16
|
377 >()
|
Chris@16
|
378 ),
|
Chris@16
|
379 traverse_post_order_env<
|
Chris@16
|
380 EnvT::level, thisnum, EnvT::index, EnvT::lastleft
|
Chris@16
|
381 >()
|
Chris@16
|
382 );
|
Chris@16
|
383 }
|
Chris@16
|
384 };
|
Chris@16
|
385
|
Chris@16
|
386 } // namespace impl
|
Chris@16
|
387
|
Chris@16
|
388 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
389 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
Chris@16
|
390
|
Chris@16
|
391 }} // namespace boost::spirit
|
Chris@16
|
392
|
Chris@16
|
393 #endif // !defined(BOOST_SPIRIT_TRAVERSE_IPP)
|