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