os/ossrv/ossrv_pub/boost_apis/boost/spirit/dynamic/select.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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_SELECT_HPP
    10 #define BOOST_SPIRIT_SELECT_HPP
    11 
    12 #include <boost/preprocessor/repeat.hpp>
    13 #include <boost/preprocessor/enum.hpp>
    14 #include <boost/preprocessor/enum_params.hpp>
    15 #include <boost/preprocessor/enum_params_with_defaults.hpp>
    16 #include <boost/preprocessor/inc.hpp>
    17 #include <boost/preprocessor/cat.hpp>
    18 #include <boost/preprocessor/facilities/intercept.hpp>
    19 
    20 #include <boost/spirit/core/parser.hpp>
    21 
    22 #include <boost/spirit/phoenix/tuples.hpp>
    23 
    24 ///////////////////////////////////////////////////////////////////////////////
    25 //
    26 //  Spirit predefined maximum number of possible embedded select_p parsers.
    27 //  It should NOT be greater than PHOENIX_LIMIT!
    28 //
    29 ///////////////////////////////////////////////////////////////////////////////
    30 #if !defined(BOOST_SPIRIT_SELECT_LIMIT)
    31 #define BOOST_SPIRIT_SELECT_LIMIT PHOENIX_LIMIT
    32 #endif // !defined(BOOST_SPIRIT_SELECT_LIMIT)
    33 
    34 ///////////////////////////////////////////////////////////////////////////////
    35 //
    36 // ensure   BOOST_SPIRIT_SELECT_LIMIT <= PHOENIX_LIMIT and 
    37 //          BOOST_SPIRIT_SELECT_LIMIT > 0
    38 //          BOOST_SPIRIT_SELECT_LIMIT <= 15
    39 //
    40 //  [Pushed this down a little to make CW happy with BOOST_STATIC_ASSERT]
    41 //  [Otherwise, it complains: 'boost_static_assert_test_42' redefined]
    42 //
    43 ///////////////////////////////////////////////////////////////////////////////
    44 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT <= PHOENIX_LIMIT);
    45 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT > 0);
    46 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT <= 15);
    47 
    48 ///////////////////////////////////////////////////////////////////////////////
    49 //
    50 //  Calculate the required amount of tuple members rounded up to the nearest 
    51 //  integer dividable by 3
    52 //
    53 ///////////////////////////////////////////////////////////////////////////////
    54 #if BOOST_SPIRIT_SELECT_LIMIT > 12
    55 #define BOOST_SPIRIT_SELECT_LIMIT_A     15
    56 #elif BOOST_SPIRIT_SELECT_LIMIT > 9
    57 #define BOOST_SPIRIT_SELECT_LIMIT_A     12
    58 #elif BOOST_SPIRIT_SELECT_LIMIT > 6
    59 #define BOOST_SPIRIT_SELECT_LIMIT_A     9
    60 #elif BOOST_SPIRIT_SELECT_LIMIT > 3
    61 #define BOOST_SPIRIT_SELECT_LIMIT_A     6
    62 #else
    63 #define BOOST_SPIRIT_SELECT_LIMIT_A     3
    64 #endif
    65 
    66 ///////////////////////////////////////////////////////////////////////////////
    67 namespace boost { namespace spirit {
    68 
    69 ///////////////////////////////////////////////////////////////////////////////
    70 //
    71 //  The select_default_no_fail and select_default_fail structs are used to 
    72 //  distinguish two different behaviours for the select_parser in case that not
    73 //  any of the given sub-parsers match.
    74 //
    75 //  If the select_parser is used with the select_default_no_fail behaviour,
    76 //  then in case of no matching sub-parser the whole select_parser returns an
    77 //  empty match and the value -1.
    78 //
    79 //  If the select_parser is used with the select_default_fail behaviour, then
    80 //  in case of no matching sub-parser the whole select_parser fails to match at 
    81 //  all.
    82 //
    83 ///////////////////////////////////////////////////////////////////////////////
    84 struct select_default_no_fail {};
    85 struct select_default_fail {};
    86 
    87 }}  // namespace boost::spirit
    88 
    89 ///////////////////////////////////////////////////////////////////////////////
    90 #include <boost/spirit/dynamic/impl/select.ipp>
    91 
    92 ///////////////////////////////////////////////////////////////////////////////
    93 namespace boost { namespace spirit {
    94 
    95 ///////////////////////////////////////////////////////////////////////////////
    96 template <typename TupleT, typename BehaviourT, typename T>
    97 struct select_parser
    98 :   public parser<select_parser<TupleT, BehaviourT, T> >
    99 {
   100     typedef select_parser<TupleT, BehaviourT, T> self_t;
   101 
   102     select_parser(TupleT const &t_)
   103     :   t(t_)
   104     {}
   105     
   106     template <typename ScannerT>
   107     struct result
   108     {
   109         typedef typename match_result<ScannerT, T>::type type;
   110     };
   111 
   112     template <typename ScannerT>
   113     typename parser_result<self_t, ScannerT>::type
   114     parse(ScannerT const& scan) const
   115     {
   116         typedef typename parser_result<self_t, ScannerT>::type result_t;
   117         
   118         if (!scan.at_end()) {
   119             return impl::parse_tuple_element<
   120                 TupleT::length, result_t, TupleT, BehaviourT>::do_(t, scan);
   121         }
   122         return impl::select_match_gen<result_t, BehaviourT>::do_(scan);
   123     }
   124         
   125     TupleT const t;
   126 };
   127 
   128 ///////////////////////////////////////////////////////////////////////////////
   129 template <typename BehaviourT, typename T = int>
   130 struct select_parser_gen {
   131 
   132     ///////////////////////////////////////////////////////////////////////////
   133     //
   134     //  This generates different select_parser_gen::operator()() functions with 
   135     //  an increasing number of parser parameters:
   136     //
   137     //      template <typename ParserT0, ...>
   138     //      select_parser<
   139     //          phoenix::tuple<
   140     //              typename impl::as_embedded_parser<ParserT0>::type,
   141     //              ...
   142     //          >,
   143     //          BehaviourT,
   144     //          T
   145     //      >
   146     //      operator()(ParserT0 const &p0, ...) const
   147     //      {
   148     //          typedef impl::as_embedded_parser<ParserT0> parser_t0;
   149     //          ...
   150     //
   151     //          typedef phoenix::tuple< 
   152     //                  parser_t0::type,
   153     //                  ...
   154     //              > tuple_t; 
   155     //          typedef select_parser<tuple_t, BehaviourT, T> result_t;
   156     //
   157     //          return result_t(tuple_t(
   158     //                  parser_t0::convert(p0),
   159     //                  ...
   160     //              ));
   161     //      }
   162     //
   163     //  The number of generated functions depends on the maximum tuple member 
   164     //  limit defined by the PHOENIX_LIMIT pp constant. 
   165     //
   166     ///////////////////////////////////////////////////////////////////////////
   167     #define BOOST_SPIRIT_SELECT_EMBEDDED(z, N, _)                           \
   168         typename impl::as_embedded_parser<BOOST_PP_CAT(ParserT, N)>::type   \
   169         /**/
   170     #define BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF(z, N, _)                   \
   171         typedef impl::as_embedded_parser<BOOST_PP_CAT(ParserT, N)>          \
   172             BOOST_PP_CAT(parser_t, N);                                      \
   173         /**/
   174     #define BOOST_SPIRIT_SELECT_CONVERT(z, N, _)                            \
   175         BOOST_PP_CAT(parser_t, N)::convert(BOOST_PP_CAT(p, N))              \
   176         /**/
   177         
   178     #define BOOST_SPIRIT_SELECT_PARSER(z, N, _)                             \
   179         template <                                                          \
   180             BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ParserT)    \
   181         >                                                                   \
   182         select_parser<                                                      \
   183             phoenix::tuple<                                                 \
   184                 BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N),                        \
   185                     BOOST_SPIRIT_SELECT_EMBEDDED, _)                        \
   186             >,                                                              \
   187             BehaviourT,                                                     \
   188             T                                                               \
   189         >                                                                   \
   190         operator()(                                                         \
   191             BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N),               \
   192                 ParserT, const &p)                                          \
   193         ) const                                                             \
   194         {                                                                   \
   195             BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(N),                          \
   196                 BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF, _)                    \
   197                                                                             \
   198             typedef phoenix::tuple<                                         \
   199                     BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N),       \
   200                         typename parser_t, ::type BOOST_PP_INTERCEPT)       \
   201                 > tuple_t;                                                  \
   202             typedef select_parser<tuple_t, BehaviourT, T> result_t;         \
   203                                                                             \
   204             return result_t(tuple_t(                                        \
   205                     BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N),                    \
   206                         BOOST_SPIRIT_SELECT_CONVERT, _)                     \
   207                 ));                                                         \
   208         }                                                                   \
   209         /**/
   210         
   211     BOOST_PP_REPEAT(BOOST_SPIRIT_SELECT_LIMIT_A, 
   212         BOOST_SPIRIT_SELECT_PARSER, _)
   213         
   214     #undef BOOST_SPIRIT_SELECT_PARSER
   215     #undef BOOST_SPIRIT_SELECT_CONVERT
   216     #undef BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF
   217     #undef BOOST_SPIRIT_SELECT_EMBEDDED
   218     ///////////////////////////////////////////////////////////////////////////
   219 };
   220 
   221 ///////////////////////////////////////////////////////////////////////////////
   222 //
   223 //  Predefined parser generator helper objects
   224 //
   225 ///////////////////////////////////////////////////////////////////////////////
   226 select_parser_gen<select_default_no_fail> const select_p = 
   227     select_parser_gen<select_default_no_fail>();
   228 
   229 select_parser_gen<select_default_fail> const select_fail_p = 
   230     select_parser_gen<select_default_fail>();
   231 
   232 #undef BOOST_SPIRIT_SELECT_LIMIT_A
   233 
   234 ///////////////////////////////////////////////////////////////////////////////
   235 }}  // namespace boost::spirit
   236 
   237 #endif // BOOST_SPIRIT_SELECT_HPP