grammar_def.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 308 行

HPP
308
字号
/*=============================================================================    Copyright (c) 2003 Hartmut Kaiser    Copyright (c) 2003 Joel de Guzman    http://spirit.sourceforge.net/  Distributed under the Boost Software License, Version 1.0. (See accompanying  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)=============================================================================*/#if !defined(BOOST_SPIRIT_GRAMMAR_DEF_HPP)#define BOOST_SPIRIT_GRAMMAR_DEF_HPP#include <boost/mpl/if.hpp>#include <boost/mpl/eval_if.hpp>#include <boost/type_traits/is_same.hpp>#include <boost/preprocessor/arithmetic/inc.hpp>#include <boost/preprocessor/arithmetic/dec.hpp>#include <boost/preprocessor/enum.hpp>#include <boost/preprocessor/enum_params.hpp>#include <boost/preprocessor/repeat.hpp>#include <boost/preprocessor/repeat_from_to.hpp>#include <boost/spirit/home/classic/namespace.hpp>#include <boost/spirit/home/classic/phoenix/tuples.hpp>#include <boost/spirit/home/classic/core/assert.hpp>#include <boost/spirit/home/classic/utility/grammar_def_fwd.hpp>///////////////////////////////////////////////////////////////////////////////////  Spirit predefined maximum grammar start parser limit. This limit defines//  the maximum number of of possible different parsers exposed from a//  particular grammar. This number defaults to 3.//  The actual maximum is rounded up in multiples of 3. Thus, if this value//  is 4, the actual limit is 6. The ultimate maximum limit in this//  implementation is 15.////  It should NOT be greater than PHOENIX_LIMIT!/////////////////////////////////////////////////////////////////////////////////#if !defined(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT)#define BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT PHOENIX_LIMIT#endif/////////////////////////////////////////////////////////////////////////////////// ensure BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= PHOENIX_LIMIT and//        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= 15 and//        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT > 0/////////////////////////////////////////////////////////////////////////////////BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= PHOENIX_LIMIT);BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT <= 15);BOOST_STATIC_ASSERT(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT > 0);//////////////////////////////////////////////////////////////////////////////namespace boost { namespace spirit {BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGINstruct same {};///////////////////////////////////////////////////////////////////////////////namespace impl {    ///////////////////////////////////////////////////////////////////////////    //    //  The make_const_pointer meta function allows to generate a T const*    //  needed to store the pointer to a given start parser from a grammar.    //    ///////////////////////////////////////////////////////////////////////////    template <typename T0, typename T = T0>    struct make_const_pointer {    private:        // T0 shouldn't be of type 'same'        BOOST_STATIC_ASSERT((!boost::is_same<T0, same>::value));        typedef typename boost::mpl::if_c<                    boost::is_same<T, same>::value,                    T0 const *,                    T const *                >::type            ptr_type;    public:        // If the type in question is phoenix::nil_t, then the returned type        // is still phoenix::nil_t, otherwise a constant pointer type to the        // inspected type is returned.        typedef typename boost::mpl::if_c<                    boost::is_same<T, phoenix::nil_t>::value,                    phoenix::nil_t,                    ptr_type                >::type            type;    };    ///////////////////////////////////////////////////////////////////////////    template <int N, typename ElementT>    struct assign_zero_to_tuple_member {        template <typename TupleT>        static void do_(TupleT &t) { t[phoenix::tuple_index<N>()] = 0; }    };    template <int N>    struct assign_zero_to_tuple_member<N, phoenix::nil_t> {        template <typename TupleT>        static void do_(TupleT& /*t*/) {}    };    struct phoenix_nil_type {        typedef phoenix::nil_t type;    };    template <int N>    struct init_tuple_member {        template <typename TupleT>        static void        do_(TupleT &t)        {            typedef typename boost::mpl::eval_if_c<                        (N < TupleT::length),                        phoenix::tuple_element<N, TupleT>,                        phoenix_nil_type                    >::type                element_type;            assign_zero_to_tuple_member<N, element_type>::do_(t);        }    };///////////////////////////////////////////////////////////////////////////////}   // namespace impl///////////////////////////////////////////////////////////////////////////////////  grammar_def class////      This class may be used as a base class for the embedded definition//      class inside the grammar<> derived user grammar.//      It exposes the two functions needed for start rule access:////          rule<> const &start() const;////      and////          template <int N>//          rule<> const *get_start_parser() const;////      Additionally it exposes a set o 'start_parsers' functions, which are to//      be called by the user to define the parsers to use as start parsers//      of the given grammar./////////////////////////////////////////////////////////////////////////////////template <    typename T,    BOOST_PP_ENUM_PARAMS(        BOOST_PP_DEC(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A), typename T)>class grammar_def {private:    ///////////////////////////////////////////////////////////////////////////    //    //  This generates the full tuple type from the given template parameters    //  T, T0, ...    //    //      typedef phoenix::tuple<    //              typename impl::make_const_pointer<T>::type,    //              typename impl::make_const_pointer<T, T0>::type,    //              ...    //          > tuple_t;    //    ///////////////////////////////////////////////////////////////////////////    #define BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM(z, N, _) \        typename impl::make_const_pointer<T, BOOST_PP_CAT(T, N)>::type \        /**/    typedef phoenix::tuple<            typename impl::make_const_pointer<T>::type,            BOOST_PP_ENUM(                BOOST_PP_DEC(BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A),                BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM,                _            )        > tuple_t;    #undef BOOST_SPIRIT_GRAMMARDEF_TUPLE_PARAM    ///////////////////////////////////////////////////////////////////////////protected:    ///////////////////////////////////////////////////////////////////////////    //    //  This generates a sequence of 'start_parsers' functions with increasing    //  number of arguments, which allow to initialize the tuple members with    //  the pointers to the start parsers of the grammar:    //    //      template <typename TC0, ...>    //      void start_parsers (TC0 const &t0, ...)    //      {    //          using phoenix::tuple_index_names::_1;    //          t[_1] = &t0;    //          ...    //      }    //    //      where a TC0 const* must be convertible to a T0 const*    //    ///////////////////////////////////////////////////////////////////////////    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS(z, N, _) \        BOOST_PP_CAT(TC, N) const &BOOST_PP_CAT(t, N) \        /**/    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN(z, N, _) \        using phoenix::tuple_index_names::BOOST_PP_CAT(_, BOOST_PP_INC(N)); \        t[BOOST_PP_CAT(_, BOOST_PP_INC(N))] = &BOOST_PP_CAT(t, N); \        /**/    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_START(z, N, _) \        template <BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename TC)> \        void \        start_parsers(BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N), \            BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS, _) ) \        { \            BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(N), \                BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN, _) \        } \        /**/    BOOST_PP_REPEAT(        BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A,        BOOST_SPIRIT_GRAMMARDEF_ENUM_START, _)    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_START    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_ASSIGN    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_PARAMS    ///////////////////////////////////////////////////////////////////////////    ///////////////////////////////////////////////////////////////////////////    //    //  This generates some initialization code, which allows to initialize all    //  used tuple members to 0 (zero):    //    //      t[_1] = 0;    //      impl::init_tuple_member<1>::do_(t);    //      ...    //    ///////////////////////////////////////////////////////////////////////////    #define BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT(z, N, _) \        impl::init_tuple_member<N>::do_(t); \        /**/    grammar_def()    {        using phoenix::tuple_index_names::_1;        t[_1] = 0;        BOOST_PP_REPEAT_FROM_TO(            1, BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_A,            BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT, _)    }    #undef BOOST_SPIRIT_GRAMMARDEF_ENUM_INIT    ///////////////////////////////////////////////////////////////////////////public:    T const &    start() const    {    //  If the following assertion is fired, you have probably forgot to call    //  the start_parser() function from inside the constructor of your    //  embedded definition class to initialize the start parsers to be exposed    //  from your grammar.        using phoenix::tuple_index_names::_1;        BOOST_SPIRIT_ASSERT(0 != t[_1]);        return *t[_1];    }    template <int N>    typename phoenix::tuple_element<N, tuple_t>::crtype    get_start_parser() const    {    //  If the following expression yields a compiler error, you have probably    //  tried to access a start rule, which isn't exposed as such from your    //  grammar.        BOOST_STATIC_ASSERT(N > 0 && N < tuple_t::length);    //  If the following assertion is fired, you have probably forgot to call    //  the start_parser() function from inside the constructor of your    //  embedded definition class to initialize the start parsers to be exposed    //  from your grammar.    //  Another reason may be, that there is a count mismatch between    //  the number of template parameters to the grammar_def<> class and the    //  number of parameters used while calling start_parsers().        BOOST_SPIRIT_ASSERT(0 != t[phoenix::tuple_index<N>()]);        return t[phoenix::tuple_index<N>()];    }private:    tuple_t t;};#undef BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT_ABOOST_SPIRIT_CLASSIC_NAMESPACE_END}} // namespace BOOST_SPIRIT_CLASSIC_NS#endif // BOOST_SPIRIT_GRAMMAR_DEF_HPP

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?