Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:01:56

0001 /*=============================================================================
0002     Copyright (c) 2003 Hartmut Kaiser
0003     http://spirit.sourceforge.net/
0004 
0005     Use, modification and distribution is subject to the Boost Software
0006     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0007     http://www.boost.org/LICENSE_1_0.txt)
0008 =============================================================================*/
0009 #ifndef BOOST_SPIRIT_SWITCH_IPP
0010 #define BOOST_SPIRIT_SWITCH_IPP
0011 
0012 #include <boost/mpl/if.hpp>
0013 #include <boost/type_traits/is_same.hpp>
0014 #include <boost/static_assert.hpp>
0015 #include <boost/core/ignore_unused.hpp>
0016 
0017 #include <boost/preprocessor/cat.hpp>
0018 #include <boost/preprocessor/inc.hpp>
0019 #include <boost/preprocessor/repeat.hpp>
0020 #include <boost/preprocessor/repeat_from_to.hpp>
0021 
0022 #include <boost/spirit/home/classic/core/parser.hpp>
0023 #include <boost/spirit/home/classic/core/primitives/primitives.hpp>
0024 #include <boost/spirit/home/classic/core/composite/composite.hpp>
0025 #include <boost/spirit/home/classic/meta/as_parser.hpp>
0026 
0027 #include <boost/spirit/home/classic/phoenix/actor.hpp>
0028 #include <boost/spirit/home/classic/phoenix/tuples.hpp>
0029 
0030 ///////////////////////////////////////////////////////////////////////////////
0031 namespace boost { namespace spirit {
0032 
0033 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0034 
0035 // forward declaration
0036 template <int N, typename ParserT, bool IsDefault> struct case_parser;
0037 
0038 ///////////////////////////////////////////////////////////////////////////////
0039 namespace impl {
0040 
0041 ///////////////////////////////////////////////////////////////////////////////
0042 //  parse helper functions
0043 template <typename ParserT, typename ScannerT>
0044 inline typename parser_result<ParserT, ScannerT>::type
0045 delegate_parse(ParserT const &p, ScannerT const &scan,
0046     typename ScannerT::iterator_t const save)
0047 {
0048     typedef typename parser_result<ParserT, ScannerT>::type result_t;
0049 
0050     result_t result (p.subject().parse(scan));
0051     if (!result)
0052         scan.first = save;
0053     return result;
0054 }
0055 
0056 ///////////////////////////////////////////////////////////////////////////////
0057 //  General default case handling (no default_p case branch given).
0058 //  First try to match the current parser node (if the condition value is
0059 //  matched) and, if that fails, return a no_match
0060 template <int N, bool IsDefault, bool HasDefault>
0061 struct default_delegate_parse {
0062 
0063     template <
0064         typename ParserT, typename DefaultT,
0065         typename ValueT, typename ScannerT
0066     >
0067     static typename parser_result<ParserT, ScannerT>::type
0068     parse (ValueT const &value, ParserT const &p, DefaultT const &,
0069         ScannerT const &scan, typename ScannerT::iterator_t const save)
0070     {
0071         if (value == N)
0072             return delegate_parse(p, scan, save);
0073         return scan.no_match();
0074     }
0075 };
0076 
0077 //  The current case parser node is the default parser.
0078 //  Ignore the given case value and try to match the given default parser.
0079 template <int N, bool HasDefault>
0080 struct default_delegate_parse<N, true, HasDefault> {
0081 
0082     template <
0083         typename ParserT, typename DefaultT,
0084         typename ValueT, typename ScannerT
0085     >
0086     static typename parser_result<ParserT, ScannerT>::type
0087     parse (ValueT const& /*value*/, ParserT const &, DefaultT const &d,
0088         ScannerT const &scan, typename ScannerT::iterator_t const save)
0089     {
0090         //  Since there is a default_p case branch defined, the corresponding
0091         //  parser shouldn't be the nothing_parser
0092         BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
0093         return delegate_parse(d, scan, save);
0094     }
0095 };
0096 
0097 //  The current case parser node is not the default parser, but there is a
0098 //  default_p branch given inside the switch_p parser.
0099 //  First try to match the current parser node (if the condition value is
0100 //  matched) and, if that fails, match the given default_p parser.
0101 template <int N>
0102 struct default_delegate_parse<N, false, true> {
0103 
0104     template <
0105         typename ParserT, typename DefaultT,
0106         typename ValueT, typename ScannerT
0107     >
0108     static typename parser_result<ParserT, ScannerT>::type
0109     parse (ValueT const &value, ParserT const &p, DefaultT const &d,
0110         ScannerT const &scan, typename ScannerT::iterator_t const save)
0111     {
0112         //  Since there is a default_p case branch defined, the corresponding
0113         //  parser shouldn't be the nothing_parser
0114         BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
0115         if (value == N)
0116             return delegate_parse(p, scan, save);
0117 
0118         return delegate_parse(d, scan, save);
0119     }
0120 };
0121 
0122 ///////////////////////////////////////////////////////////////////////////////
0123 //  Look through the case parser chain to test, if there is a default case
0124 //  branch defined (returned by 'value').
0125 template <typename CaseT, bool IsSimple = CaseT::is_simple>
0126 struct default_case;
0127 
0128 ////////////////////////////////////////
0129 template <typename ResultT, bool IsDefault>
0130 struct get_default_parser {
0131 
0132     template <typename ParserT>
0133     static ResultT
0134     get(parser<ParserT> const &p)
0135     {
0136         return default_case<typename ParserT::derived_t::left_t>::
0137             get(p.derived().left());
0138     }
0139 };
0140 
0141 template <typename ResultT>
0142 struct get_default_parser<ResultT, true> {
0143 
0144     template <typename ParserT>
0145     static ResultT
0146     get(parser<ParserT> const &p) { return p.derived().right(); }
0147 };
0148 
0149 ////////////////////////////////////////
0150 template <typename CaseT, bool IsSimple>
0151 struct default_case {
0152 
0153     //  The 'value' constant is true, if the current case_parser or one of its
0154     //  left siblings is a default_p generated case_parser.
0155     BOOST_STATIC_CONSTANT(bool, value =
0156         (CaseT::is_default || default_case<typename CaseT::left_t>::value));
0157 
0158     //  The 'is_epsilon' constant is true, if the current case_parser or one of
0159     //  its left siblings is a default_p generated parser with an attached
0160     //  epsilon_p (this is generated by the plain default_p).
0161     BOOST_STATIC_CONSTANT(bool, is_epsilon = (
0162         (CaseT::is_default && CaseT::is_epsilon) ||
0163             default_case<typename CaseT::left_t>::is_epsilon
0164     ));
0165 
0166     //  The computed 'type' represents the type of the default case branch
0167     //  parser (if there is one) or nothing_parser (if there isn't any default
0168     //  case branch).
0169     typedef typename boost::mpl::if_c<
0170             CaseT::is_default, typename CaseT::right_embed_t,
0171             typename default_case<typename CaseT::left_t>::type
0172         >::type type;
0173 
0174     //  The get function returns the parser attached to the default case branch
0175     //  (if there is one) or an instance of a nothing_parser (if there isn't
0176     //  any default case branch).
0177     template <typename ParserT>
0178     static type
0179     get(parser<ParserT> const &p)
0180     { return get_default_parser<type, CaseT::is_default>::get(p); }
0181 };
0182 
0183 ////////////////////////////////////////
0184 template <typename ResultT, bool IsDefault>
0185 struct get_default_parser_simple {
0186 
0187     template <typename ParserT>
0188     static ResultT
0189     get(parser<ParserT> const &p) { return p.derived(); }
0190 };
0191 
0192 template <typename ResultT>
0193 struct get_default_parser_simple<ResultT, false> {
0194 
0195     template <typename ParserT>
0196     static nothing_parser
0197     get(parser<ParserT> const &) { return nothing_p; }
0198 };
0199 
0200 ////////////////////////////////////////
0201 //  Specialization of the default_case template for the last (leftmost) element
0202 //  of the case parser chain.
0203 template <typename CaseT>
0204 struct default_case<CaseT, true> {
0205 
0206     //  The 'value' and 'is_epsilon' constant, the 'type' type and the function
0207     //  'get' are described above.
0208 
0209     BOOST_STATIC_CONSTANT(bool, value = CaseT::is_default);
0210     BOOST_STATIC_CONSTANT(bool, is_epsilon = (
0211         CaseT::is_default && CaseT::is_epsilon
0212     ));
0213 
0214     typedef typename boost::mpl::if_c<
0215             CaseT::is_default, CaseT, nothing_parser
0216         >::type type;
0217 
0218     template <typename ParserT>
0219     static type
0220     get(parser<ParserT> const &p)
0221     { return get_default_parser_simple<type, value>::get(p); }
0222 };
0223 
0224 ///////////////////////////////////////////////////////////////////////////////
0225 //  The case_chain template calculates recursively the depth of the left
0226 //  subchain of the given case branch node.
0227 template <typename CaseT, bool IsSimple = CaseT::is_simple>
0228 struct case_chain {
0229 
0230     BOOST_STATIC_CONSTANT(int, depth = (
0231         case_chain<typename CaseT::left_t>::depth + 1
0232     ));
0233 };
0234 
0235 template <typename CaseT>
0236 struct case_chain<CaseT, true> {
0237 
0238     BOOST_STATIC_CONSTANT(int, depth = 0);
0239 };
0240 
0241 ///////////////////////////////////////////////////////////////////////////////
0242 //  The chain_parser template is used to extract the type and the instance of
0243 //  a left or a right parser, buried arbitrary deep inside the case parser
0244 //  chain.
0245 template <int Depth, typename CaseT>
0246 struct chain_parser {
0247 
0248     typedef typename CaseT::left_t our_left_t;
0249 
0250     typedef typename chain_parser<Depth-1, our_left_t>::left_t  left_t;
0251     typedef typename chain_parser<Depth-1, our_left_t>::right_t right_t;
0252 
0253     static left_t
0254     left(CaseT const &p)
0255     { return chain_parser<Depth-1, our_left_t>::left(p.left()); }
0256 
0257     static right_t
0258     right(CaseT const &p)
0259     { return chain_parser<Depth-1, our_left_t>::right(p.left()); }
0260 };
0261 
0262 template <typename CaseT>
0263 struct chain_parser<1, CaseT> {
0264 
0265     typedef typename CaseT::left_t  left_t;
0266     typedef typename CaseT::right_t right_t;
0267 
0268     static left_t left(CaseT const &p) { return p.left(); }
0269     static right_t right(CaseT const &p) { return p.right(); }
0270 };
0271 
0272 template <typename CaseT>
0273 struct chain_parser<0, CaseT>;      // shouldn't be instantiated
0274 
0275 ///////////////////////////////////////////////////////////////////////////////
0276 //  Type computing meta function for calculating the type of the return value
0277 //  of the used conditional switch expression
0278 template <typename TargetT, typename ScannerT>
0279 struct condition_result {
0280 
0281     typedef typename TargetT::template result<ScannerT>::type type;
0282 };
0283 
0284 ///////////////////////////////////////////////////////////////////////////////
0285 template <typename LeftT, typename RightT, bool IsDefault>
0286 struct compound_case_parser
0287 :   public binary<LeftT, RightT,
0288         parser<compound_case_parser<LeftT, RightT, IsDefault> > >
0289 {
0290     typedef compound_case_parser<LeftT, RightT, IsDefault>    self_t;
0291     typedef binary_parser_category                  parser_category_t;
0292     typedef binary<LeftT, RightT, parser<self_t> >  base_t;
0293 
0294     BOOST_STATIC_CONSTANT(int, value = RightT::value);
0295     BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
0296     BOOST_STATIC_CONSTANT(bool, is_simple = false);
0297     BOOST_STATIC_CONSTANT(bool, is_epsilon = (
0298         is_default &&
0299             boost::is_same<typename RightT::subject_t, epsilon_parser>::value
0300     ));
0301 
0302     compound_case_parser(parser<LeftT> const &lhs, parser<RightT> const &rhs)
0303     :   base_t(lhs.derived(), rhs.derived())
0304     {}
0305 
0306     template <typename ScannerT>
0307     struct result
0308     {
0309         typedef typename match_result<ScannerT, nil_t>::type type;
0310     };
0311 
0312     template <typename ScannerT, typename CondT>
0313     typename parser_result<self_t, ScannerT>::type
0314     parse(ScannerT const& scan, CondT const &cond) const;
0315 
0316     template <int N1, typename ParserT1, bool IsDefault1>
0317     compound_case_parser<
0318         self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
0319     >
0320     operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
0321     {
0322         //  If the following compile time assertion fires, you've probably used
0323         //  more than one default_p case inside the switch_p parser construct.
0324         BOOST_STATIC_ASSERT(!default_case<self_t>::value || !IsDefault1);
0325 
0326         //  If this compile time assertion fires, you've probably want to use
0327         //  more case_p/default_p case branches, than possible.
0328         BOOST_STATIC_ASSERT(
0329             case_chain<self_t>::depth < BOOST_SPIRIT_SWITCH_CASE_LIMIT
0330         );
0331 
0332         typedef case_parser<N1, ParserT1, IsDefault1> rhs_t;
0333         return compound_case_parser<self_t, rhs_t, IsDefault1>(*this, p);
0334     }
0335 };
0336 
0337 ///////////////////////////////////////////////////////////////////////////////
0338 //  The parse_switch::do_ functions dispatch to the correct parser, which is
0339 //  selected through the given conditional switch value.
0340 template <int Value, int Depth, bool IsDefault>
0341 struct parse_switch;
0342 
0343 ///////////////////////////////////////////////////////////////////////////////
0344 //
0345 //  The following generates a couple of parse_switch template specializations
0346 //  with an increasing number of handled case branches (for 1..N).
0347 //
0348 //      template <int Value, bool IsDefault>
0349 //      struct parse_switch<Value, N, IsDefault> {
0350 //
0351 //          template <typename ParserT, typename ScannerT>
0352 //          static typename parser_result<ParserT, ScannerT>::type
0353 //          do_(ParserT const &p, ScannerT const &scan, long cond_value,
0354 //              typename ScannerT::iterator_t const &save)
0355 //          {
0356 //              typedef ParserT left_t0;
0357 //              typedef typename left_t0::left left_t1;
0358 //              ...
0359 //
0360 //              switch (cond_value) {
0361 //              case left_tN::value:
0362 //                  return delegate_parse(chain_parser<
0363 //                          case_chain<ParserT>::depth, ParserT
0364 //                      >::left(p), scan, save);
0365 //              ...
0366 //              case left_t1::value:
0367 //                  return delegate_parse(chain_parser<
0368 //                          1, left_t1
0369 //                      >::right(p.left()), scan, save);
0370 //
0371 //              case left_t0::value:
0372 //              default:
0373 //                  typedef default_case<ParserT> default_t;
0374 //                  typedef default_delegate_parse<
0375 //                              Value, IsDefault, default_t::value>
0376 //                      default_parse_t;
0377 //
0378 //                  return default_parse_t::parse(cond_value, p.right(),
0379 //                      default_t::get(p), scan, save);
0380 //              }
0381 //          }
0382 //      };
0383 //
0384 ///////////////////////////////////////////////////////////////////////////////
0385 #define BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS(z, N, _)                         \
0386     typedef typename BOOST_PP_CAT(left_t, N)::left_t                        \
0387         BOOST_PP_CAT(left_t, BOOST_PP_INC(N));                              \
0388     /**/
0389 
0390 #define BOOST_SPIRIT_PARSE_SWITCH_CASES(z, N, _)                            \
0391     case (long)(BOOST_PP_CAT(left_t, N)::value):                            \
0392         return delegate_parse(chain_parser<N, left_t1>::right(p.left()),    \
0393             scan, save);                                                    \
0394     /**/
0395 
0396 #define BOOST_SPIRIT_PARSE_SWITCHES(z, N, _)                                \
0397     template <int Value, bool IsDefault>                                    \
0398     struct parse_switch<Value, BOOST_PP_INC(N), IsDefault> {                \
0399                                                                             \
0400         template <typename ParserT, typename ScannerT>                      \
0401         static typename parser_result<ParserT, ScannerT>::type              \
0402         do_(ParserT const &p, ScannerT const &scan, long cond_value,        \
0403             typename ScannerT::iterator_t const &save)                      \
0404         {                                                                   \
0405             typedef ParserT left_t0;                                        \
0406             BOOST_PP_REPEAT_FROM_TO_ ## z(0, BOOST_PP_INC(N),               \
0407                 BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS, _)                      \
0408                                                                             \
0409             switch (cond_value) {                                           \
0410             case (long)(BOOST_PP_CAT(left_t, BOOST_PP_INC(N))::value):      \
0411                 return delegate_parse(                                      \
0412                     chain_parser<                                           \
0413                         case_chain<ParserT>::depth, ParserT                 \
0414                     >::left(p), scan, save);                                \
0415                                                                             \
0416             BOOST_PP_REPEAT_FROM_TO_ ## z(1, BOOST_PP_INC(N),               \
0417                 BOOST_SPIRIT_PARSE_SWITCH_CASES, _)                         \
0418                                                                             \
0419             case (long)(left_t0::value):                                    \
0420             default:                                                        \
0421                 typedef default_case<ParserT> default_t;                    \
0422                 typedef                                                     \
0423                     default_delegate_parse<Value, IsDefault, default_t::value> \
0424                     default_parse_t;                                        \
0425                                                                             \
0426                 return default_parse_t::parse(cond_value, p.right(),        \
0427                     default_t::get(p), scan, save);                         \
0428             }                                                               \
0429         }                                                                   \
0430     };                                                                      \
0431     /**/
0432 
0433 BOOST_PP_REPEAT(BOOST_PP_DEC(BOOST_SPIRIT_SWITCH_CASE_LIMIT),
0434     BOOST_SPIRIT_PARSE_SWITCHES, _)
0435 
0436 #undef BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS
0437 #undef BOOST_SPIRIT_PARSE_SWITCH_CASES
0438 #undef BOOST_SPIRIT_PARSE_SWITCHES
0439 ///////////////////////////////////////////////////////////////////////////////
0440 
0441 template <typename LeftT, typename RightT, bool IsDefault>
0442 template <typename ScannerT, typename CondT>
0443 inline typename parser_result<
0444     compound_case_parser<LeftT, RightT, IsDefault>, ScannerT
0445 >::type
0446 compound_case_parser<LeftT, RightT, IsDefault>::
0447     parse(ScannerT const& scan, CondT const &cond) const
0448 {
0449     ignore_unused(scan.at_end());    // allow skipper to take effect
0450     return parse_switch<value, case_chain<self_t>::depth, is_default>::
0451         do_(*this, scan, cond(scan), scan.first);
0452 }
0453 
0454 ///////////////////////////////////////////////////////////////////////////////
0455 //  The switch condition is to be evaluated from a parser result value.
0456 template <typename ParserT>
0457 struct cond_functor {
0458 
0459     typedef cond_functor<ParserT> self_t;
0460 
0461     cond_functor(ParserT const &p_)
0462     :   p(p_)
0463     {}
0464 
0465     template <typename ScannerT>
0466     struct result
0467     {
0468         typedef typename parser_result<ParserT, ScannerT>::type::attr_t type;
0469     };
0470 
0471     template <typename ScannerT>
0472     typename condition_result<self_t, ScannerT>::type
0473     operator()(ScannerT const &scan) const
0474     {
0475         typedef typename parser_result<ParserT, ScannerT>::type result_t;
0476         typedef typename result_t::attr_t attr_t;
0477 
0478         result_t result(p.parse(scan));
0479         return !result ? attr_t() : result.value();
0480     }
0481 
0482     typename ParserT::embed_t p;
0483 };
0484 
0485 template <typename ParserT>
0486 struct make_cond_functor {
0487 
0488     typedef as_parser<ParserT> as_parser_t;
0489 
0490     static cond_functor<typename as_parser_t::type>
0491     do_(ParserT const &cond)
0492     {
0493         return cond_functor<typename as_parser_t::type>(
0494             as_parser_t::convert(cond));
0495     }
0496 };
0497 
0498 ///////////////////////////////////////////////////////////////////////////////
0499 //  The switch condition is to be evaluated from a phoenix actor
0500 template <typename ActorT>
0501 struct cond_actor {
0502 
0503     typedef cond_actor<ActorT> self_t;
0504 
0505     cond_actor(ActorT const &actor_)
0506     :   actor(actor_)
0507     {}
0508 
0509     template <typename ScannerT>
0510     struct result
0511     {
0512         typedef typename ::phoenix::actor_result<ActorT, ::phoenix::tuple<> >::type
0513             type;
0514     };
0515 
0516     template <typename ScannerT>
0517     typename condition_result<self_t, ScannerT>::type
0518     operator()(ScannerT const& /*scan*/) const
0519     {
0520         return actor();
0521     }
0522 
0523     ActorT const &actor;
0524 };
0525 
0526 template <typename ActorT>
0527 struct make_cond_functor< ::phoenix::actor<ActorT> > {
0528 
0529     static cond_actor< ::phoenix::actor<ActorT> >
0530     do_(::phoenix::actor<ActorT> const &actor)
0531     {
0532         return cond_actor< ::phoenix::actor<ActorT> >(actor);
0533     }
0534 };
0535 
0536 ///////////////////////////////////////////////////////////////////////////////
0537 //  The switch condition is to be taken directly from the input stream
0538 struct get_next_token_cond {
0539 
0540     typedef get_next_token_cond self_t;
0541 
0542     template <typename ScannerT>
0543     struct result
0544     {
0545         typedef typename ScannerT::value_t type;
0546     };
0547 
0548     template <typename ScannerT>
0549     typename condition_result<self_t, ScannerT>::type
0550     operator()(ScannerT const &scan) const
0551     {
0552         typename ScannerT::value_t val(*scan);
0553         ++scan.first;
0554         return val;
0555     }
0556 };
0557 
0558 template <>
0559 struct make_cond_functor<get_next_token_cond> {
0560 
0561     static get_next_token_cond
0562     do_(get_next_token_cond const &cond)
0563     {
0564         return cond;
0565     }
0566 };
0567 
0568 ///////////////////////////////////////////////////////////////////////////////
0569 }   // namespace impl
0570 
0571 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0572 
0573 }}  // namespace boost::spirit
0574 
0575 #endif  // BOOST_SPIRIT_SWITCH_IPP