Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:08

0001 /*=============================================================================
0002     Copyright (c) 2003 Hartmut Kaiser
0003     Copyright (c) 2003 Joel de Guzman
0004     http://spirit.sourceforge.net/
0005 
0006   Distributed under the Boost Software License, Version 1.0. (See accompanying
0007   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 =============================================================================*/
0009 #if !defined(BOOST_SPIRIT_GRAMMAR_DEF_HPP)
0010 #define BOOST_SPIRIT_GRAMMAR_DEF_HPP
0011 
0012 #include <boost/mpl/if.hpp>
0013 #include <boost/mpl/eval_if.hpp>
0014 #include <boost/type_traits/is_same.hpp>
0015 #include <boost/preprocessor/arithmetic/inc.hpp>
0016 #include <boost/preprocessor/arithmetic/dec.hpp>
0017 #include <boost/preprocessor/enum.hpp>
0018 #include <boost/preprocessor/enum_params.hpp>
0019 #include <boost/preprocessor/repeat.hpp>
0020 #include <boost/preprocessor/repeat_from_to.hpp>
0021 #include <boost/spirit/home/classic/namespace.hpp>
0022 #include <boost/spirit/home/classic/phoenix/tuples.hpp>
0023 #include <boost/spirit/home/classic/core/assert.hpp>
0024 #include <boost/spirit/home/classic/utility/grammar_def_fwd.hpp>
0025 
0026 ///////////////////////////////////////////////////////////////////////////////
0027 //
0028 //  Spirit predefined maximum grammar start parser limit. This limit defines
0029 //  the maximum number of possible different parsers exposed from a
0030 //  particular grammar. This number defaults to 3.
0031 //  The actual maximum is rounded up in multiples of 3. Thus, if this value
0032 //  is 4, the actual limit is 6. The ultimate maximum limit in this
0033 //  implementation is 15.
0034 //
0035 //  It should NOT be greater than PHOENIX_LIMIT!
0036 //
0037 ///////////////////////////////////////////////////////////////////////////////
0038 #if !defined(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT)
0039 #define BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT PHOENIX_LIMIT
0040 #endif
0041 
0042 ///////////////////////////////////////////////////////////////////////////////
0043 //
0044 // ensure BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= PHOENIX_LIMIT and
0045 //        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= 15 and
0046 //        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT > 0
0047 //
0048 ///////////////////////////////////////////////////////////////////////////////
0049 BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= PHOENIX_LIMIT);
0050 BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= 15);
0051 BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT > 0);
0052 
0053 //////////////////////////////////////////////////////////////////////////////
0054 namespace boost { namespace spirit {
0055 
0056 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0057 
0058 struct same {};
0059 
0060 ///////////////////////////////////////////////////////////////////////////////
0061 namespace impl {
0062 
0063     ///////////////////////////////////////////////////////////////////////////
0064     //
0065     //  The make_const_pointer meta function allows to generate a T const*
0066     //  needed to store the pointer to a given start parser from a grammar.
0067     //
0068     ///////////////////////////////////////////////////////////////////////////
0069     template <typename T0, typename T = T0>
0070     struct make_const_pointer {
0071 
0072     private:
0073         // T0 shouldn't be of type 'same'
0074         BOOST_STATIC_ASSERT((!boost::is_same<T0, same>::value));
0075 
0076         typedef typename boost::mpl::if_c<
0077                     boost::is_same<T, same>::value,
0078                     T0 const *,
0079                     T const *
0080                 >::type
0081             ptr_type;
0082 
0083     public:
0084         // If the type in question is phoenix::nil_t, then the returned type
0085         // is still phoenix::nil_t, otherwise a constant pointer type to the
0086         // inspected type is returned.
0087         typedef typename boost::mpl::if_c<
0088                     boost::is_same<T, ::phoenix::nil_t>::value,
0089                     ::phoenix::nil_t,
0090                     ptr_type
0091                 >::type
0092             type;
0093     };
0094 
0095     ///////////////////////////////////////////////////////////////////////////
0096     template <int N, typename ElementT>
0097     struct assign_zero_to_tuple_member {
0098 
0099         template <typename TupleT>
0100         static void do_(TupleT &t)
0101         {
0102             ::phoenix::tuple_index<N> const idx;
0103             t[idx] = 0;
0104         }
0105     };
0106 
0107     template <int N>
0108     struct assign_zero_to_tuple_member<N, ::phoenix::nil_t> {
0109 
0110         template <typename TupleT>
0111         static void do_(TupleT& /*t*/) {}
0112     };
0113 
0114     struct phoenix_nil_type {
0115 
0116         typedef ::phoenix::nil_t type;
0117     };
0118 
0119     template <int N>
0120     struct init_tuple_member {
0121 
0122         template <typename TupleT>
0123         static void
0124         do_(TupleT &t)
0125         {
0126             typedef typename boost::mpl::eval_if_c<
0127                         (N < TupleT::length),
0128                         ::phoenix::tuple_element<N, TupleT>,
0129                         phoenix_nil_type
0130                     >::type
0131                 element_type;
0132 
0133             assign_zero_to_tuple_member<N, element_type>::do_(t);
0134         }
0135     };
0136 
0137 ///////////////////////////////////////////////////////////////////////////////
0138 }   // namespace impl
0139 
0140 ///////////////////////////////////////////////////////////////////////////////
0141 //
0142 //  grammar_def class
0143 //
0144 //      This class may be used as a base class for the embedded definition
0145 //      class inside the grammar<> derived user grammar.
0146 //      It exposes the two functions needed for start rule access:
0147 //
0148 //          rule<> const &start() const;
0149 //
0150 //      and
0151 //
0152 //          template <int N>
0153 //          rule<> const *get_start_parser() const;
0154 //
0155 //      Additionally it exposes a set o 'start_parsers' functions, which are to
0156 //      be called by the user to define the parsers to use as start parsers
0157 //      of the given grammar.
0158 //
0159 ///////////////////////////////////////////////////////////////////////////////
0160 template <
0161     typename T,
0162     BOOST_PP_ENUM_PARAMS(
0163         BOOST_PP_DEC(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A), typename T)
0164 >
0165 class grammar_def {
0166 
0167 private:
0168     ///////////////////////////////////////////////////////////////////////////
0169     //
0170     //  This generates the full tuple type from the given template parameters
0171     //  T, T0, ...
0172     //
0173     //      typedef ::phoenix::tuple<
0174     //              typename impl::make_const_pointer<T>::type,
0175     //              typename impl::make_const_pointer<T, T0>::type,
0176     //              ...
0177     //          > tuple_t;
0178     //
0179     ///////////////////////////////////////////////////////////////////////////
0180     #define BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM(z, N, _) \
0181         typename impl::make_const_pointer<T, BOOST_PP_CAT(T, N)>::type \
0182         /**/
0183 
0184     typedef ::phoenix::tuple<
0185             typename impl::make_const_pointer<T>::type,
0186             BOOST_PP_ENUM(
0187                 BOOST_PP_DEC(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A),
0188                 BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM,
0189                 _
0190             )
0191         > tuple_t;
0192 
0193     #undef BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM
0194     ///////////////////////////////////////////////////////////////////////////
0195 
0196 protected:
0197     ///////////////////////////////////////////////////////////////////////////
0198     //
0199     //  This generates a sequence of 'start_parsers' functions with increasing
0200     //  number of arguments, which allow to initialize the tuple members with
0201     //  the pointers to the start parsers of the grammar:
0202     //
0203     //      template <typename TC0, ...>
0204     //      void start_parsers (TC0 const &t0, ...)
0205     //      {
0206     //          using ::phoenix::tuple_index_names::_1;
0207     //          t[_1] = &t0;
0208     //          ...
0209     //      }
0210     //
0211     //      where a TC0 const* must be convertible to a T0 const*
0212     //
0213     ///////////////////////////////////////////////////////////////////////////
0214     #define BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS(z, N, _) \
0215         BOOST_PP_CAT(TC, N) const &BOOST_PP_CAT(t, N) \
0216         /**/
0217     #define BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN(z, N, _) \
0218         using ::phoenix::tuple_index_names::BOOST_PP_CAT(_, BOOST_PP_INC(N)); \
0219         t[BOOST_PP_CAT(_, BOOST_PP_INC(N))] = &BOOST_PP_CAT(t, N); \
0220         /**/
0221     #define BOOST_SPIRIT_GRAMMARDEF_ENUM_START(z, N, _) \
0222         template <BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename TC)> \
0223         void \
0224         start_parsers(BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N), \
0225             BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS, _) ) \
0226         { \
0227             BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(N), \
0228                 BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN, _) \
0229         } \
0230         /**/
0231 
0232     BOOST_PP_REPEAT(
0233         BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A,
0234         BOOST_SPIRIT_GRAMMARDEF_ENUM_START, _)
0235 
0236     #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_START
0237     #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN
0238     #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS
0239     ///////////////////////////////////////////////////////////////////////////
0240 
0241     ///////////////////////////////////////////////////////////////////////////
0242     //
0243     //  This generates some initialization code, which allows to initialize all
0244     //  used tuple members to 0 (zero):
0245     //
0246     //      t[_1] = 0;
0247     //      impl::init_tuple_member<1>::do_(t);
0248     //      ...
0249     //
0250     ///////////////////////////////////////////////////////////////////////////
0251     #define BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT(z, N, _) \
0252         impl::init_tuple_member<N>::do_(t); \
0253         /**/
0254 
0255     grammar_def()
0256     {
0257         using ::phoenix::tuple_index_names::_1;
0258         t[_1] = 0;
0259         BOOST_PP_REPEAT_FROM_TO(
0260             1, BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A,
0261             BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT, _)
0262     }
0263 
0264     #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT
0265     ///////////////////////////////////////////////////////////////////////////
0266 
0267 public:
0268     T const &
0269     start() const
0270     {
0271     //  If the following assertion is fired, you have probably forgot to call
0272     //  the start_parser() function from inside the constructor of your
0273     //  embedded definition class to initialize the start parsers to be exposed
0274     //  from your grammar.
0275         using ::phoenix::tuple_index_names::_1;
0276         BOOST_SPIRIT_ASSERT(0 != t[_1]);
0277         return *t[_1];
0278     }
0279 
0280     template <int N>
0281     typename ::phoenix::tuple_element<N, tuple_t>::crtype
0282     get_start_parser() const
0283     {
0284     //  If the following expression yields a compiler error, you have probably
0285     //  tried to access a start rule, which isn't exposed as such from your
0286     //  grammar.
0287         BOOST_STATIC_ASSERT(N > 0 && N < tuple_t::length);
0288 
0289         ::phoenix::tuple_index<N> const idx;
0290 
0291     //  If the following assertion is fired, you have probably forgot to call
0292     //  the start_parser() function from inside the constructor of your
0293     //  embedded definition class to initialize the start parsers to be exposed
0294     //  from your grammar.
0295     //  Another reason may be, that there is a count mismatch between
0296     //  the number of template parameters to the grammar_def<> class and the
0297     //  number of parameters used while calling start_parsers().
0298         BOOST_SPIRIT_ASSERT(0 != t[idx]);
0299 
0300         return t[idx];
0301     }
0302 
0303 private:
0304     tuple_t t;
0305 };
0306 
0307 #undef BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A
0308 
0309 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0310 
0311 }} // namespace BOOST_SPIRIT_CLASSIC_NS
0312 
0313 #endif // BOOST_SPIRIT_GRAMMAR_DEF_HPP