Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/spirit/utility/grammar_def.hpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 10.7 KB
Line 
1/*=============================================================================
2    Copyright (c) 2003 Hartmut Kaiser
3    Copyright (c) 2003 Joel de Guzman
4    http://spirit.sourceforge.net/
5
6    Use, modification and distribution is subject to the Boost Software
7    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8    http://www.boost.org/LICENSE_1_0.txt)
9=============================================================================*/
10#if !defined(BOOST_SPIRIT_GRAMMAR_DEF_HPP)
11#define BOOST_SPIRIT_GRAMMAR_DEF_HPP
12
13#include <boost/mpl/if.hpp>
14#include <boost/mpl/eval_if.hpp>
15#include <boost/type_traits/is_same.hpp>
16#include <boost/preprocessor/arithmetic/inc.hpp>
17#include <boost/preprocessor/arithmetic/dec.hpp>
18#include <boost/preprocessor/enum.hpp>
19#include <boost/preprocessor/enum_params.hpp>
20#include <boost/preprocessor/repeat.hpp>
21#include <boost/preprocessor/repeat_from_to.hpp>
22#include <boost/spirit/phoenix/tuples.hpp>
23#include <boost/spirit/core/assert.hpp>
24#include <boost/spirit/utility/grammar_def_fwd.hpp>
25
26///////////////////////////////////////////////////////////////////////////////
27//
28//  Spirit predefined maximum grammar start parser limit. This limit defines
29//  the maximum number of of possible different parsers exposed from a
30//  particular grammar. This number defaults to 3.
31//  The actual maximum is rounded up in multiples of 3. Thus, if this value
32//  is 4, the actual limit is 6. The ultimate maximum limit in this
33//  implementation is 15.
34//
35//  It should NOT be greater than PHOENIX_LIMIT!
36//
37///////////////////////////////////////////////////////////////////////////////
38#if !defined(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT)
39#define BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT PHOENIX_LIMIT
40#endif
41
42///////////////////////////////////////////////////////////////////////////////
43//
44// ensure BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= PHOENIX_LIMIT and
45//        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= 15 and
46//        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT > 0
47//
48///////////////////////////////////////////////////////////////////////////////
49BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= PHOENIX_LIMIT);
50BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= 15);
51BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT > 0);
52
53//////////////////////////////////////////////////////////////////////////////
54namespace boost { namespace spirit {
55
56struct same {};
57
58///////////////////////////////////////////////////////////////////////////////
59namespace impl {
60
61    ///////////////////////////////////////////////////////////////////////////
62    //
63    //  The make_const_pointer meta function allows to generate a T const*
64    //  needed to store the pointer to a given start parser from a grammar.
65    //
66    ///////////////////////////////////////////////////////////////////////////
67    template <typename T0, typename T = T0>
68    struct make_const_pointer {
69
70    private:
71        // T0 shouldn't be of type 'same'
72        BOOST_STATIC_ASSERT((!boost::is_same<T0, same>::value));
73
74        typedef typename boost::mpl::if_c<
75                    boost::is_same<T, same>::value,
76                    T0 const *,
77                    T const *
78                >::type
79            ptr_type;
80
81    public:
82        // If the type in question is phoenix::nil_t, then the returned type
83        // is still phoenix::nil_t, otherwise a constant pointer type to the
84        // inspected type is returned.
85        typedef typename boost::mpl::if_c<
86                    boost::is_same<T, phoenix::nil_t>::value,
87                    phoenix::nil_t,
88                    ptr_type
89                >::type
90            type;
91    };
92
93    ///////////////////////////////////////////////////////////////////////////
94    template <int N, typename ElementT>
95    struct assign_zero_to_tuple_member {
96
97        template <typename TupleT>
98        static void do_(TupleT &t) { t[phoenix::tuple_index<N>()] = 0; }
99    };
100
101    template <int N>
102    struct assign_zero_to_tuple_member<N, phoenix::nil_t> {
103
104        template <typename TupleT>
105        static void do_(TupleT& /*t*/) {}
106    };
107
108    struct phoenix_nil_type {
109
110        typedef phoenix::nil_t type;
111    };
112
113    template <int N>
114    struct init_tuple_member {
115
116        template <typename TupleT>
117        static void
118        do_(TupleT &t)
119        {
120            typedef typename boost::mpl::eval_if_c<
121                        (N < TupleT::length),
122                        phoenix::tuple_element<N, TupleT>,
123                        phoenix_nil_type
124                    >::type
125                element_type;
126
127            assign_zero_to_tuple_member<N, element_type>::do_(t);
128        }
129    };
130
131///////////////////////////////////////////////////////////////////////////////
132}   // namespace impl
133
134///////////////////////////////////////////////////////////////////////////////
135//
136//  grammar_def class
137//
138//      This class may be used as a base class for the embedded definition
139//      class inside the grammar<> derived user grammar.
140//      It exposes the two functions needed for start rule access:
141//
142//          rule<> const &start() const;
143//
144//      and
145//
146//          template <int N>
147//          rule<> const *get_start_parser() const;
148//
149//      Additionally it exposes a set o 'start_parsers' functions, which are to
150//      be called by the user to define the parsers to use as start parsers
151//      of the given grammar.
152//
153///////////////////////////////////////////////////////////////////////////////
154template <
155    typename T,
156    BOOST_PP_ENUM_PARAMS(
157        BOOST_PP_DEC(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A), typename T)
158>
159class grammar_def {
160
161private:
162    ///////////////////////////////////////////////////////////////////////////
163    //
164    //  This generates the full tuple type from the given template parameters
165    //  T, T0, ...
166    //
167    //      typedef phoenix::tuple<
168    //              typename impl::make_const_pointer<T>::type,
169    //              typename impl::make_const_pointer<T, T0>::type,
170    //              ...
171    //          > tuple_t;
172    //
173    ///////////////////////////////////////////////////////////////////////////
174    #define BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM(z, N, _) \
175        typename impl::make_const_pointer<T, BOOST_PP_CAT(T, N)>::type \
176        /**/
177
178    typedef phoenix::tuple<
179            typename impl::make_const_pointer<T>::type,
180            BOOST_PP_ENUM(
181                BOOST_PP_DEC(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A),
182                BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM,
183                _
184            )
185        > tuple_t;
186
187    #undef BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM
188    ///////////////////////////////////////////////////////////////////////////
189
190protected:
191    ///////////////////////////////////////////////////////////////////////////
192    //
193    //  This generates a sequence of 'start_parsers' functions with increasing
194    //  number of arguments, which allow to initialize the tuple members with
195    //  the pointers to the start parsers of the grammar:
196    //
197    //      template <typename TC0, ...>
198    //      void start_parsers (TC0 const &t0, ...)
199    //      {
200    //          using phoenix::tuple_index_names::_1;
201    //          t[_1] = &t0;
202    //          ...
203    //      }
204    //
205    //      where a TC0 const* must be convertible to a T0 const*
206    //
207    ///////////////////////////////////////////////////////////////////////////
208    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS(z, N, _) \
209        BOOST_PP_CAT(TC, N) const &BOOST_PP_CAT(t, N) \
210        /**/
211    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN(z, N, _) \
212        using phoenix::tuple_index_names::BOOST_PP_CAT(_, BOOST_PP_INC(N)); \
213        t[BOOST_PP_CAT(_, BOOST_PP_INC(N))] = &BOOST_PP_CAT(t, N); \
214        /**/
215    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_START(z, N, _) \
216        template <BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename TC)> \
217        void \
218        start_parsers(BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N), \
219            BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS, _) ) \
220        { \
221            BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(N), \
222                BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN, _) \
223        } \
224        /**/
225
226    BOOST_PP_REPEAT(
227        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A,
228        BOOST_SPIRIT_GRAMMARDEF_ENUM_START, _)
229
230    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_START
231    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN
232    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS
233    ///////////////////////////////////////////////////////////////////////////
234
235    ///////////////////////////////////////////////////////////////////////////
236    //
237    //  This generates some initialization code, which allows to initialize all
238    //  used tuple members to 0 (zero):
239    //
240    //      t[_1] = 0;
241    //      impl::init_tuple_member<1>::do_(t);
242    //      ...
243    //
244    ///////////////////////////////////////////////////////////////////////////
245    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT(z, N, _) \
246        impl::init_tuple_member<N>::do_(t); \
247        /**/
248
249    grammar_def()
250    {
251        using phoenix::tuple_index_names::_1;
252        t[_1] = 0;
253        BOOST_PP_REPEAT_FROM_TO(
254            1, BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A,
255            BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT, _)
256    }
257
258    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT
259    ///////////////////////////////////////////////////////////////////////////
260
261public:
262    T const &
263    start() const
264    {
265    //  If the following assertion is fired, you have probably forgot to call
266    //  the start_parser() function from inside the constructor of your
267    //  embedded definition class to initialize the start parsers to be exposed
268    //  from your grammar.
269        using phoenix::tuple_index_names::_1;
270        BOOST_SPIRIT_ASSERT(0 != t[_1]);
271        return *t[_1];
272    }
273
274    template <int N>
275    typename phoenix::tuple_element<N, tuple_t>::crtype
276    get_start_parser() const
277    {
278    //  If the following expression yields a compiler error, you have probably
279    //  tried to access a start rule, which isn't exposed as such from your
280    //  grammar.
281        BOOST_STATIC_ASSERT(N > 0 && N < tuple_t::length);
282
283    //  If the following assertion is fired, you have probably forgot to call
284    //  the start_parser() function from inside the constructor of your
285    //  embedded definition class to initialize the start parsers to be exposed
286    //  from your grammar.
287    //  Another reason may be, that there is a count mismatch between
288    //  the number of template parameters to the grammar_def<> class and the
289    //  number of parameters used while calling start_parsers().
290        BOOST_SPIRIT_ASSERT(0 != t[phoenix::tuple_index<N>()]);
291
292        return t[phoenix::tuple_index<N>()];
293    }
294
295private:
296    tuple_t t;
297};
298
299#undef BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A
300
301}} // namespace boost::spirit
302
303#endif // BOOST_SPIRIT_GRAMMAR_DEF_HPP
Note: See TracBrowser for help on using the repository browser.