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