source: NonGTP/Boost/boost/spirit/dynamic/select.hpp @ 857

Revision 857, 10.2 KB checked in by igarcia, 18 years ago (diff)
Line 
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///////////////////////////////////////////////////////////////////////////////
44BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT <= PHOENIX_LIMIT);
45BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT > 0);
46BOOST_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///////////////////////////////////////////////////////////////////////////////
67namespace 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///////////////////////////////////////////////////////////////////////////////
84struct select_default_no_fail {};
85struct select_default_fail {};
86
87}}  // namespace boost::spirit
88
89///////////////////////////////////////////////////////////////////////////////
90#include <boost/spirit/dynamic/impl/select.ipp>
91
92///////////////////////////////////////////////////////////////////////////////
93namespace boost { namespace spirit {
94
95///////////////////////////////////////////////////////////////////////////////
96template <typename TupleT, typename BehaviourT, typename T>
97struct 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///////////////////////////////////////////////////////////////////////////////
129template <typename BehaviourT, typename T = int>
130struct 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///////////////////////////////////////////////////////////////////////////////
226select_parser_gen<select_default_no_fail> const select_p =
227    select_parser_gen<select_default_no_fail>();
228
229select_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
Note: See TracBrowser for help on using the repository browser.