1 | /*=============================================================================
|
---|
2 | Copyright (c) 2003 Hartmut Kaiser
|
---|
3 | http://spirit.sourceforge.net/
|
---|
4 |
|
---|
5 | Use, modification and distribution is subject to the Boost Software
|
---|
6 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
---|
7 | http://www.boost.org/LICENSE_1_0.txt)
|
---|
8 | =============================================================================*/
|
---|
9 | #ifndef BOOST_SPIRIT_SWITCH_IPP
|
---|
10 | #define BOOST_SPIRIT_SWITCH_IPP
|
---|
11 |
|
---|
12 | #include <boost/mpl/if.hpp>
|
---|
13 | #include <boost/type_traits/is_same.hpp>
|
---|
14 | #include <boost/static_assert.hpp>
|
---|
15 |
|
---|
16 | #include <boost/preprocessor/cat.hpp>
|
---|
17 | #include <boost/preprocessor/inc.hpp>
|
---|
18 | #include <boost/preprocessor/repeat.hpp>
|
---|
19 | #include <boost/preprocessor/repeat_from_to.hpp>
|
---|
20 |
|
---|
21 | #include <boost/spirit/core/parser.hpp>
|
---|
22 | #include <boost/spirit/core/primitives/primitives.hpp>
|
---|
23 | #include <boost/spirit/core/composite/composite.hpp>
|
---|
24 | #include <boost/spirit/meta/as_parser.hpp>
|
---|
25 |
|
---|
26 | #include <boost/spirit/phoenix/actor.hpp>
|
---|
27 | #include <boost/spirit/phoenix/tuples.hpp>
|
---|
28 |
|
---|
29 | ///////////////////////////////////////////////////////////////////////////////
|
---|
30 | namespace boost { namespace spirit {
|
---|
31 |
|
---|
32 | // forward declaration
|
---|
33 | template <int N, typename ParserT, bool IsDefault> struct case_parser;
|
---|
34 |
|
---|
35 | ///////////////////////////////////////////////////////////////////////////////
|
---|
36 | namespace impl {
|
---|
37 |
|
---|
38 | ///////////////////////////////////////////////////////////////////////////////
|
---|
39 | // parse helper functions
|
---|
40 | template <typename ParserT, typename ScannerT>
|
---|
41 | inline typename parser_result<ParserT, ScannerT>::type
|
---|
42 | delegate_parse(ParserT const &p, ScannerT const &scan,
|
---|
43 | typename ScannerT::iterator_t const save)
|
---|
44 | {
|
---|
45 | typedef typename parser_result<ParserT, ScannerT>::type result_t;
|
---|
46 |
|
---|
47 | result_t result (p.subject().parse(scan));
|
---|
48 | if (!result)
|
---|
49 | scan.first = save;
|
---|
50 | return result;
|
---|
51 | }
|
---|
52 |
|
---|
53 | ///////////////////////////////////////////////////////////////////////////////
|
---|
54 | // General default case handling (no default_p case branch given).
|
---|
55 | // First try to match the current parser node (if the condition value is
|
---|
56 | // matched) and, if that fails, return a no_match
|
---|
57 | template <int N, bool IsDefault, bool HasDefault>
|
---|
58 | struct default_delegate_parse {
|
---|
59 |
|
---|
60 | template <
|
---|
61 | typename ParserT, typename DefaultT,
|
---|
62 | typename ValueT, typename ScannerT
|
---|
63 | >
|
---|
64 | static typename parser_result<ParserT, ScannerT>::type
|
---|
65 | parse (ValueT const &value, ParserT const &p, DefaultT const &,
|
---|
66 | ScannerT const &scan, typename ScannerT::iterator_t const save)
|
---|
67 | {
|
---|
68 | if (value == N)
|
---|
69 | return delegate_parse(p, scan, save);
|
---|
70 | return scan.no_match();
|
---|
71 | }
|
---|
72 | };
|
---|
73 |
|
---|
74 | // The current case parser node is the default parser.
|
---|
75 | // Ignore the given case value and try to match the given default parser.
|
---|
76 | template <int N, bool HasDefault>
|
---|
77 | struct default_delegate_parse<N, true, HasDefault> {
|
---|
78 |
|
---|
79 | template <
|
---|
80 | typename ParserT, typename DefaultT,
|
---|
81 | typename ValueT, typename ScannerT
|
---|
82 | >
|
---|
83 | static typename parser_result<ParserT, ScannerT>::type
|
---|
84 | parse (ValueT const& /*value*/, ParserT const &, DefaultT const &d,
|
---|
85 | ScannerT const &scan, typename ScannerT::iterator_t const save)
|
---|
86 | {
|
---|
87 | // Since there is a default_p case branch defined, the corresponding
|
---|
88 | // parser shouldn't be the nothing_parser
|
---|
89 | BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
|
---|
90 | return delegate_parse(d, scan, save);
|
---|
91 | }
|
---|
92 | };
|
---|
93 |
|
---|
94 | // The current case parser node is not the default parser, but there is a
|
---|
95 | // default_p branch given inside the switch_p parser.
|
---|
96 | // First try to match the current parser node (if the condition value is
|
---|
97 | // matched) and, if that fails, match the given default_p parser.
|
---|
98 | template <int N>
|
---|
99 | struct default_delegate_parse<N, false, true> {
|
---|
100 |
|
---|
101 | template <
|
---|
102 | typename ParserT, typename DefaultT,
|
---|
103 | typename ValueT, typename ScannerT
|
---|
104 | >
|
---|
105 | static typename parser_result<ParserT, ScannerT>::type
|
---|
106 | parse (ValueT const &value, ParserT const &p, DefaultT const &d,
|
---|
107 | ScannerT const &scan, typename ScannerT::iterator_t const save)
|
---|
108 | {
|
---|
109 | // Since there is a default_p case branch defined, the corresponding
|
---|
110 | // parser shouldn't be the nothing_parser
|
---|
111 | BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
|
---|
112 | if (value == N)
|
---|
113 | return delegate_parse(p, scan, save);
|
---|
114 |
|
---|
115 | return delegate_parse(d, scan, save);
|
---|
116 | }
|
---|
117 | };
|
---|
118 |
|
---|
119 | ///////////////////////////////////////////////////////////////////////////////
|
---|
120 | // Look through the case parser chain to test, if there is a default case
|
---|
121 | // branch defined (returned by 'value').
|
---|
122 | template <typename CaseT, bool IsSimple = CaseT::is_simple>
|
---|
123 | struct default_case;
|
---|
124 |
|
---|
125 | ////////////////////////////////////////
|
---|
126 | template <typename ResultT, bool IsDefault>
|
---|
127 | struct get_default_parser {
|
---|
128 |
|
---|
129 | template <typename ParserT>
|
---|
130 | static ResultT
|
---|
131 | get(parser<ParserT> const &p)
|
---|
132 | {
|
---|
133 | return default_case<typename ParserT::derived_t::left_t>::
|
---|
134 | get(p.derived().left());
|
---|
135 | }
|
---|
136 | };
|
---|
137 |
|
---|
138 | template <typename ResultT>
|
---|
139 | struct get_default_parser<ResultT, true> {
|
---|
140 |
|
---|
141 | template <typename ParserT>
|
---|
142 | static ResultT
|
---|
143 | get(parser<ParserT> const &p) { return p.derived().right(); }
|
---|
144 | };
|
---|
145 |
|
---|
146 | ////////////////////////////////////////
|
---|
147 | template <typename CaseT, bool IsSimple>
|
---|
148 | struct default_case {
|
---|
149 |
|
---|
150 | // The 'value' constant is true, if the current case_parser or one of its
|
---|
151 | // left siblings is a default_p generated case_parser.
|
---|
152 | BOOST_STATIC_CONSTANT(bool, value =
|
---|
153 | (CaseT::is_default || default_case<typename CaseT::left_t>::value));
|
---|
154 |
|
---|
155 | // The 'is_epsilon' constant is true, if the current case_parser or one of
|
---|
156 | // its left siblings is a default_p generated parser with an attached
|
---|
157 | // epsilon_p (this is generated by the plain default_p).
|
---|
158 | BOOST_STATIC_CONSTANT(bool, is_epsilon = (
|
---|
159 | (CaseT::is_default && CaseT::is_epsilon) ||
|
---|
160 | default_case<typename CaseT::left_t>::is_epsilon
|
---|
161 | ));
|
---|
162 |
|
---|
163 | // The computed 'type' represents the type of the default case branch
|
---|
164 | // parser (if there is one) or nothing_parser (if there isn't any default
|
---|
165 | // case branch).
|
---|
166 | typedef typename boost::mpl::if_c<
|
---|
167 | CaseT::is_default, typename CaseT::right_embed_t,
|
---|
168 | typename default_case<typename CaseT::left_t>::type
|
---|
169 | >::type type;
|
---|
170 |
|
---|
171 | // The get function returns the parser attached to the default case branch
|
---|
172 | // (if there is one) or an instance of a nothing_parser (if there isn't
|
---|
173 | // any default case branch).
|
---|
174 | template <typename ParserT>
|
---|
175 | static type
|
---|
176 | get(parser<ParserT> const &p)
|
---|
177 | { return get_default_parser<type, CaseT::is_default>::get(p); }
|
---|
178 | };
|
---|
179 |
|
---|
180 | ////////////////////////////////////////
|
---|
181 | template <typename ResultT, bool IsDefault>
|
---|
182 | struct get_default_parser_simple {
|
---|
183 |
|
---|
184 | template <typename ParserT>
|
---|
185 | static ResultT
|
---|
186 | get(parser<ParserT> const &p) { return p.derived(); }
|
---|
187 | };
|
---|
188 |
|
---|
189 | template <typename ResultT>
|
---|
190 | struct get_default_parser_simple<ResultT, false> {
|
---|
191 |
|
---|
192 | template <typename ParserT>
|
---|
193 | static nothing_parser
|
---|
194 | get(parser<ParserT> const &) { return nothing_p; }
|
---|
195 | };
|
---|
196 |
|
---|
197 | ////////////////////////////////////////
|
---|
198 | // Specialization of the default_case template for the last (leftmost) element
|
---|
199 | // of the case parser chain.
|
---|
200 | template <typename CaseT>
|
---|
201 | struct default_case<CaseT, true> {
|
---|
202 |
|
---|
203 | // The 'value' and 'is_epsilon' constant, the 'type' type and the function
|
---|
204 | // 'get' are described above.
|
---|
205 |
|
---|
206 | BOOST_STATIC_CONSTANT(bool, value = CaseT::is_default);
|
---|
207 | BOOST_STATIC_CONSTANT(bool, is_epsilon = (
|
---|
208 | CaseT::is_default && CaseT::is_epsilon
|
---|
209 | ));
|
---|
210 |
|
---|
211 | typedef typename boost::mpl::if_c<
|
---|
212 | CaseT::is_default, CaseT, nothing_parser
|
---|
213 | >::type type;
|
---|
214 |
|
---|
215 | template <typename ParserT>
|
---|
216 | static type
|
---|
217 | get(parser<ParserT> const &p)
|
---|
218 | { return get_default_parser_simple<type, value>::get(p); }
|
---|
219 | };
|
---|
220 |
|
---|
221 | ///////////////////////////////////////////////////////////////////////////////
|
---|
222 | // The case_chain template calculates recursivly the depth of the left
|
---|
223 | // subchain of the given case branch node.
|
---|
224 | template <typename CaseT, bool IsSimple = CaseT::is_simple>
|
---|
225 | struct case_chain {
|
---|
226 |
|
---|
227 | BOOST_STATIC_CONSTANT(int, depth = (
|
---|
228 | case_chain<typename CaseT::left_t>::depth + 1
|
---|
229 | ));
|
---|
230 | };
|
---|
231 |
|
---|
232 | template <typename CaseT>
|
---|
233 | struct case_chain<CaseT, true> {
|
---|
234 |
|
---|
235 | BOOST_STATIC_CONSTANT(int, depth = 0);
|
---|
236 | };
|
---|
237 |
|
---|
238 | ///////////////////////////////////////////////////////////////////////////////
|
---|
239 | // The chain_parser template is used to extract the type and the instance of
|
---|
240 | // a left or a right parser, burried arbitrary deep inside the case parser
|
---|
241 | // chain.
|
---|
242 | template <int Depth, typename CaseT>
|
---|
243 | struct chain_parser {
|
---|
244 |
|
---|
245 | typedef typename CaseT::left_t our_left_t;
|
---|
246 |
|
---|
247 | typedef typename chain_parser<Depth-1, our_left_t>::left_t left_t;
|
---|
248 | typedef typename chain_parser<Depth-1, our_left_t>::right_t right_t;
|
---|
249 |
|
---|
250 | static left_t
|
---|
251 | left(CaseT const &p)
|
---|
252 | { return chain_parser<Depth-1, our_left_t>::left(p.left()); }
|
---|
253 |
|
---|
254 | static right_t
|
---|
255 | right(CaseT const &p)
|
---|
256 | { return chain_parser<Depth-1, our_left_t>::right(p.left()); }
|
---|
257 | };
|
---|
258 |
|
---|
259 | template <typename CaseT>
|
---|
260 | struct chain_parser<1, CaseT> {
|
---|
261 |
|
---|
262 | typedef typename CaseT::left_t left_t;
|
---|
263 | typedef typename CaseT::right_t right_t;
|
---|
264 |
|
---|
265 | static left_t left(CaseT const &p) { return p.left(); }
|
---|
266 | static right_t right(CaseT const &p) { return p.right(); }
|
---|
267 | };
|
---|
268 |
|
---|
269 | template <typename CaseT>
|
---|
270 | struct chain_parser<0, CaseT>; // shouldn't be instantiated
|
---|
271 |
|
---|
272 | ///////////////////////////////////////////////////////////////////////////////
|
---|
273 | // Type computing meta function for calculating the type of the return value
|
---|
274 | // of the used conditional switch expression
|
---|
275 | template <typename TargetT, typename ScannerT>
|
---|
276 | struct condition_result {
|
---|
277 |
|
---|
278 | typedef typename TargetT::template result<ScannerT>::type type;
|
---|
279 | };
|
---|
280 |
|
---|
281 | ///////////////////////////////////////////////////////////////////////////////
|
---|
282 | template <typename LeftT, typename RightT, bool IsDefault>
|
---|
283 | struct compound_case_parser
|
---|
284 | : public binary<LeftT, RightT,
|
---|
285 | parser<compound_case_parser<LeftT, RightT, IsDefault> > >
|
---|
286 | {
|
---|
287 | typedef compound_case_parser<LeftT, RightT, IsDefault> self_t;
|
---|
288 | typedef binary_parser_category parser_category_t;
|
---|
289 | typedef binary<LeftT, RightT, parser<self_t> > base_t;
|
---|
290 |
|
---|
291 | BOOST_STATIC_CONSTANT(int, value = RightT::value);
|
---|
292 | BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
|
---|
293 | BOOST_STATIC_CONSTANT(bool, is_simple = false);
|
---|
294 | BOOST_STATIC_CONSTANT(bool, is_epsilon = (
|
---|
295 | is_default &&
|
---|
296 | boost::is_same<typename RightT::subject_t, epsilon_parser>::value
|
---|
297 | ));
|
---|
298 |
|
---|
299 | compound_case_parser(parser<LeftT> const &lhs, parser<RightT> const &rhs)
|
---|
300 | : base_t(lhs.derived(), rhs.derived())
|
---|
301 | {}
|
---|
302 |
|
---|
303 | template <typename ScannerT>
|
---|
304 | struct result
|
---|
305 | {
|
---|
306 | typedef typename match_result<ScannerT, nil_t>::type type;
|
---|
307 | };
|
---|
308 |
|
---|
309 | template <typename ScannerT, typename CondT>
|
---|
310 | typename parser_result<self_t, ScannerT>::type
|
---|
311 | parse(ScannerT const& scan, CondT const &cond) const;
|
---|
312 |
|
---|
313 | template <int N1, typename ParserT1, bool IsDefault1>
|
---|
314 | compound_case_parser<
|
---|
315 | self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
|
---|
316 | >
|
---|
317 | operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
|
---|
318 | {
|
---|
319 | // If the following compile time assertion fires, you've probably used
|
---|
320 | // more than one default_p case inside the switch_p parser construct.
|
---|
321 | BOOST_STATIC_ASSERT(!default_case<self_t>::value || !IsDefault1);
|
---|
322 |
|
---|
323 | // If this compile time assertion fires, you've probably want to use
|
---|
324 | // more case_p/default_p case branches, than possible.
|
---|
325 | BOOST_STATIC_ASSERT(
|
---|
326 | case_chain<self_t>::depth < BOOST_SPIRIT_SWITCH_CASE_LIMIT
|
---|
327 | );
|
---|
328 |
|
---|
329 | typedef case_parser<N1, ParserT1, IsDefault1> right_t;
|
---|
330 | return compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
|
---|
331 | }
|
---|
332 | };
|
---|
333 |
|
---|
334 | ///////////////////////////////////////////////////////////////////////////////
|
---|
335 | // The parse_switch::do_ functions dispatch to the correct parser, which is
|
---|
336 | // selected through the given conditional switch value.
|
---|
337 | template <int Value, int Depth, bool IsDefault>
|
---|
338 | struct parse_switch;
|
---|
339 |
|
---|
340 | ///////////////////////////////////////////////////////////////////////////////
|
---|
341 | //
|
---|
342 | // The following generates a couple of parse_switch template specializations
|
---|
343 | // with an increasing number of handled case branches (for 1..N).
|
---|
344 | //
|
---|
345 | // template <int Value, bool IsDefault>
|
---|
346 | // struct parse_switch<Value, N, IsDefault> {
|
---|
347 | //
|
---|
348 | // template <typename ParserT, typename ScannerT>
|
---|
349 | // static typename parser_result<ParserT, ScannerT>::type
|
---|
350 | // do_(ParserT const &p, ScannerT const &scan, long cond_value,
|
---|
351 | // typename ScannerT::iterator_t const &save)
|
---|
352 | // {
|
---|
353 | // typedef ParserT left_t0;
|
---|
354 | // typedef typename left_t0::left left_t1;
|
---|
355 | // ...
|
---|
356 | //
|
---|
357 | // switch (cond_value) {
|
---|
358 | // case left_tN::value:
|
---|
359 | // return delegate_parse(chain_parser<
|
---|
360 | // case_chain<ParserT>::depth, ParserT
|
---|
361 | // >::left(p), scan, save);
|
---|
362 | // ...
|
---|
363 | // case left_t1::value:
|
---|
364 | // return delegate_parse(chain_parser<
|
---|
365 | // 1, left_t1
|
---|
366 | // >::right(p.left()), scan, save);
|
---|
367 | //
|
---|
368 | // case left_t0::value:
|
---|
369 | // default:
|
---|
370 | // typedef default_case<ParserT> default_t;
|
---|
371 | // typedef default_delegate_parse<
|
---|
372 | // Value, IsDefault, default_t::value>
|
---|
373 | // default_parse_t;
|
---|
374 | //
|
---|
375 | // return default_parse_t::parse(cond_value, p.right(),
|
---|
376 | // default_t::get(p), scan, save);
|
---|
377 | // }
|
---|
378 | // }
|
---|
379 | // };
|
---|
380 | //
|
---|
381 | ///////////////////////////////////////////////////////////////////////////////
|
---|
382 | #define BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS(z, N, _) \
|
---|
383 | typedef typename BOOST_PP_CAT(left_t, N)::left_t \
|
---|
384 | BOOST_PP_CAT(left_t, BOOST_PP_INC(N)); \
|
---|
385 | /**/
|
---|
386 |
|
---|
387 | #define BOOST_SPIRIT_PARSE_SWITCH_CASES(z, N, _) \
|
---|
388 | case (long)(BOOST_PP_CAT(left_t, N)::value): \
|
---|
389 | return delegate_parse(chain_parser<N, left_t1>::right(p.left()), \
|
---|
390 | scan, save); \
|
---|
391 | /**/
|
---|
392 |
|
---|
393 | #define BOOST_SPIRIT_PARSE_SWITCHES(z, N, _) \
|
---|
394 | template <int Value, bool IsDefault> \
|
---|
395 | struct parse_switch<Value, BOOST_PP_INC(N), IsDefault> { \
|
---|
396 | \
|
---|
397 | template <typename ParserT, typename ScannerT> \
|
---|
398 | static typename parser_result<ParserT, ScannerT>::type \
|
---|
399 | do_(ParserT const &p, ScannerT const &scan, long cond_value, \
|
---|
400 | typename ScannerT::iterator_t const &save) \
|
---|
401 | { \
|
---|
402 | typedef ParserT left_t0; \
|
---|
403 | BOOST_PP_REPEAT_FROM_TO_ ## z(0, BOOST_PP_INC(N), \
|
---|
404 | BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS, _) \
|
---|
405 | \
|
---|
406 | switch (cond_value) { \
|
---|
407 | case (long)(BOOST_PP_CAT(left_t, BOOST_PP_INC(N))::value): \
|
---|
408 | return delegate_parse( \
|
---|
409 | chain_parser< \
|
---|
410 | case_chain<ParserT>::depth, ParserT \
|
---|
411 | >::left(p), scan, save); \
|
---|
412 | \
|
---|
413 | BOOST_PP_REPEAT_FROM_TO_ ## z(1, BOOST_PP_INC(N), \
|
---|
414 | BOOST_SPIRIT_PARSE_SWITCH_CASES, _) \
|
---|
415 | \
|
---|
416 | case (long)(left_t0::value): \
|
---|
417 | default: \
|
---|
418 | typedef default_case<ParserT> default_t; \
|
---|
419 | typedef \
|
---|
420 | default_delegate_parse<Value, IsDefault, default_t::value> \
|
---|
421 | default_parse_t; \
|
---|
422 | \
|
---|
423 | return default_parse_t::parse(cond_value, p.right(), \
|
---|
424 | default_t::get(p), scan, save); \
|
---|
425 | } \
|
---|
426 | } \
|
---|
427 | }; \
|
---|
428 | /**/
|
---|
429 |
|
---|
430 | BOOST_PP_REPEAT(BOOST_PP_DEC(BOOST_SPIRIT_SWITCH_CASE_LIMIT),
|
---|
431 | BOOST_SPIRIT_PARSE_SWITCHES, _)
|
---|
432 |
|
---|
433 | #undef BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS
|
---|
434 | #undef BOOST_SPIRIT_PARSE_SWITCH_CASES
|
---|
435 | #undef BOOST_SPIRIT_PARSE_SWITCHES
|
---|
436 | ///////////////////////////////////////////////////////////////////////////////
|
---|
437 |
|
---|
438 | template <typename LeftT, typename RightT, bool IsDefault>
|
---|
439 | template <typename ScannerT, typename CondT>
|
---|
440 | inline typename parser_result<
|
---|
441 | compound_case_parser<LeftT, RightT, IsDefault>, ScannerT
|
---|
442 | >::type
|
---|
443 | compound_case_parser<LeftT, RightT, IsDefault>::
|
---|
444 | parse(ScannerT const& scan, CondT const &cond) const
|
---|
445 | {
|
---|
446 | scan.at_end(); // allow skipper to take effect
|
---|
447 | return parse_switch<value, case_chain<self_t>::depth, is_default>::
|
---|
448 | do_(*this, scan, cond(scan), scan.first);
|
---|
449 | }
|
---|
450 |
|
---|
451 | ///////////////////////////////////////////////////////////////////////////////
|
---|
452 | // The switch condition is to be evaluated from a parser result value.
|
---|
453 | template <typename ParserT>
|
---|
454 | struct cond_functor {
|
---|
455 |
|
---|
456 | typedef cond_functor<ParserT> self_t;
|
---|
457 |
|
---|
458 | cond_functor(ParserT const &p_)
|
---|
459 | : p(p_)
|
---|
460 | {}
|
---|
461 |
|
---|
462 | template <typename ScannerT>
|
---|
463 | struct result
|
---|
464 | {
|
---|
465 | typedef typename parser_result<ParserT, ScannerT>::type::attr_t type;
|
---|
466 | };
|
---|
467 |
|
---|
468 | template <typename ScannerT>
|
---|
469 | typename condition_result<self_t, ScannerT>::type
|
---|
470 | operator()(ScannerT const &scan) const
|
---|
471 | {
|
---|
472 | typedef typename parser_result<ParserT, ScannerT>::type result_t;
|
---|
473 | typedef typename result_t::attr_t attr_t;
|
---|
474 |
|
---|
475 | result_t result(p.parse(scan));
|
---|
476 | return !result ? attr_t() : result.value();
|
---|
477 | }
|
---|
478 |
|
---|
479 | typename ParserT::embed_t p;
|
---|
480 | };
|
---|
481 |
|
---|
482 | template <typename ParserT>
|
---|
483 | struct make_cond_functor {
|
---|
484 |
|
---|
485 | typedef as_parser<ParserT> as_parser_t;
|
---|
486 |
|
---|
487 | static cond_functor<typename as_parser_t::type>
|
---|
488 | do_(ParserT const &cond)
|
---|
489 | {
|
---|
490 | return cond_functor<typename as_parser_t::type>(
|
---|
491 | as_parser_t::convert(cond));
|
---|
492 | }
|
---|
493 | };
|
---|
494 |
|
---|
495 | ///////////////////////////////////////////////////////////////////////////////
|
---|
496 | // The switch condition is to be evaluated from a phoenix actor
|
---|
497 | template <typename ActorT>
|
---|
498 | struct cond_actor {
|
---|
499 |
|
---|
500 | typedef cond_actor<ActorT> self_t;
|
---|
501 |
|
---|
502 | cond_actor(ActorT const &actor_)
|
---|
503 | : actor(actor_)
|
---|
504 | {}
|
---|
505 |
|
---|
506 | template <typename ScannerT>
|
---|
507 | struct result
|
---|
508 | {
|
---|
509 | typedef typename phoenix::actor_result<ActorT, phoenix::tuple<> >::type
|
---|
510 | type;
|
---|
511 | };
|
---|
512 |
|
---|
513 | template <typename ScannerT>
|
---|
514 | typename condition_result<self_t, ScannerT>::type
|
---|
515 | operator()(ScannerT const& /*scan*/) const
|
---|
516 | {
|
---|
517 | return actor();
|
---|
518 | }
|
---|
519 |
|
---|
520 | ActorT const &actor;
|
---|
521 | };
|
---|
522 |
|
---|
523 | template <typename ActorT>
|
---|
524 | struct make_cond_functor<phoenix::actor<ActorT> > {
|
---|
525 |
|
---|
526 | static cond_actor<phoenix::actor<ActorT> >
|
---|
527 | do_(phoenix::actor<ActorT> const &actor)
|
---|
528 | {
|
---|
529 | return cond_actor<phoenix::actor<ActorT> >(actor);
|
---|
530 | }
|
---|
531 | };
|
---|
532 |
|
---|
533 | ///////////////////////////////////////////////////////////////////////////////
|
---|
534 | // The switch condition is to be taken directly from the input stream
|
---|
535 | struct get_next_token_cond {
|
---|
536 |
|
---|
537 | typedef get_next_token_cond self_t;
|
---|
538 |
|
---|
539 | template <typename ScannerT>
|
---|
540 | struct result
|
---|
541 | {
|
---|
542 | typedef typename ScannerT::value_t type;
|
---|
543 | };
|
---|
544 |
|
---|
545 | template <typename ScannerT>
|
---|
546 | typename condition_result<self_t, ScannerT>::type
|
---|
547 | operator()(ScannerT const &scan) const
|
---|
548 | {
|
---|
549 | typename ScannerT::value_t val(*scan);
|
---|
550 | ++scan.first;
|
---|
551 | return val;
|
---|
552 | }
|
---|
553 | };
|
---|
554 |
|
---|
555 | template <>
|
---|
556 | struct make_cond_functor<get_next_token_cond> {
|
---|
557 |
|
---|
558 | static get_next_token_cond
|
---|
559 | do_(get_next_token_cond const &cond)
|
---|
560 | {
|
---|
561 | return cond;
|
---|
562 | }
|
---|
563 | };
|
---|
564 |
|
---|
565 | ///////////////////////////////////////////////////////////////////////////////
|
---|
566 | } // namespace impl
|
---|
567 | }} // namespace boost::spirit
|
---|
568 |
|
---|
569 | #endif // BOOST_SPIRIT_SWITCH_IPP
|
---|