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