PageRenderTime 22ms CodeModel.GetById 12ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/src/contrib/boost/spirit/home/classic/dynamic/impl/switch.ipp

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