| /*============================================================================= |
| Copyright (c) 2003 Hartmut Kaiser |
| 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) |
| =============================================================================*/ |
| #ifndef BOOST_SPIRIT_SELECT_HPP |
| #define BOOST_SPIRIT_SELECT_HPP |
| |
| #include <boost/preprocessor/repeat.hpp> |
| #include <boost/preprocessor/enum.hpp> |
| #include <boost/preprocessor/enum_params.hpp> |
| #include <boost/preprocessor/enum_params_with_defaults.hpp> |
| #include <boost/preprocessor/inc.hpp> |
| #include <boost/preprocessor/cat.hpp> |
| #include <boost/preprocessor/facilities/intercept.hpp> |
| |
| #include <boost/spirit/home/classic/namespace.hpp> |
| #include <boost/spirit/home/classic/core/parser.hpp> |
| |
| #include <boost/spirit/home/classic/phoenix/tuples.hpp> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Spirit predefined maximum number of possible embedded select_p parsers. |
| // It should NOT be greater than PHOENIX_LIMIT! |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| #if !defined(BOOST_SPIRIT_SELECT_LIMIT) |
| #define BOOST_SPIRIT_SELECT_LIMIT PHOENIX_LIMIT |
| #endif // !defined(BOOST_SPIRIT_SELECT_LIMIT) |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // ensure BOOST_SPIRIT_SELECT_LIMIT <= PHOENIX_LIMIT and |
| // BOOST_SPIRIT_SELECT_LIMIT > 0 |
| // BOOST_SPIRIT_SELECT_LIMIT <= 15 |
| // |
| // [Pushed this down a little to make CW happy with BOOST_STATIC_ASSERT] |
| // [Otherwise, it complains: 'boost_static_assert_test_42' redefined] |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT <= PHOENIX_LIMIT); |
| BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT > 0); |
| BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT <= 15); |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Calculate the required amount of tuple members rounded up to the nearest |
| // integer dividable by 3 |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| #if BOOST_SPIRIT_SELECT_LIMIT > 12 |
| #define BOOST_SPIRIT_SELECT_LIMIT_A 15 |
| #elif BOOST_SPIRIT_SELECT_LIMIT > 9 |
| #define BOOST_SPIRIT_SELECT_LIMIT_A 12 |
| #elif BOOST_SPIRIT_SELECT_LIMIT > 6 |
| #define BOOST_SPIRIT_SELECT_LIMIT_A 9 |
| #elif BOOST_SPIRIT_SELECT_LIMIT > 3 |
| #define BOOST_SPIRIT_SELECT_LIMIT_A 6 |
| #else |
| #define BOOST_SPIRIT_SELECT_LIMIT_A 3 |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // The select_default_no_fail and select_default_fail structs are used to |
| // distinguish two different behaviours for the select_parser in case that not |
| // any of the given sub-parsers match. |
| // |
| // If the select_parser is used with the select_default_no_fail behaviour, |
| // then in case of no matching sub-parser the whole select_parser returns an |
| // empty match and the value -1. |
| // |
| // If the select_parser is used with the select_default_fail behaviour, then |
| // in case of no matching sub-parser the whole select_parser fails to match at |
| // all. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| struct select_default_no_fail {}; |
| struct select_default_fail {}; |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace BOOST_SPIRIT_CLASSIC_NS |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| #include <boost/spirit/home/classic/dynamic/impl/select.ipp> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename TupleT, typename BehaviourT, typename T> |
| struct select_parser |
| : public parser<select_parser<TupleT, BehaviourT, T> > |
| { |
| typedef select_parser<TupleT, BehaviourT, T> self_t; |
| |
| select_parser(TupleT const &t_) |
| : t(t_) |
| {} |
| |
| template <typename ScannerT> |
| struct result |
| { |
| typedef typename match_result<ScannerT, T>::type type; |
| }; |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| typedef typename parser_result<self_t, ScannerT>::type result_t; |
| |
| if (!scan.at_end()) { |
| return impl::parse_tuple_element< |
| TupleT::length, result_t, TupleT, BehaviourT>::do_(t, scan); |
| } |
| return impl::select_match_gen<result_t, BehaviourT>::do_(scan); |
| } |
| |
| TupleT const t; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename BehaviourT, typename T = int> |
| struct select_parser_gen { |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // This generates different select_parser_gen::operator()() functions with |
| // an increasing number of parser parameters: |
| // |
| // template <typename ParserT0, ...> |
| // select_parser< |
| // ::phoenix::tuple< |
| // typename impl::as_embedded_parser<ParserT0>::type, |
| // ... |
| // >, |
| // BehaviourT, |
| // T |
| // > |
| // operator()(ParserT0 const &p0, ...) const |
| // { |
| // typedef impl::as_embedded_parser<ParserT0> parser_t0; |
| // ... |
| // |
| // typedef ::phoenix::tuple< |
| // parser_t0::type, |
| // ... |
| // > tuple_t; |
| // typedef select_parser<tuple_t, BehaviourT, T> result_t; |
| // |
| // return result_t(tuple_t( |
| // parser_t0::convert(p0), |
| // ... |
| // )); |
| // } |
| // |
| // The number of generated functions depends on the maximum tuple member |
| // limit defined by the PHOENIX_LIMIT pp constant. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| #define BOOST_SPIRIT_SELECT_EMBEDDED(z, N, _) \ |
| typename impl::as_embedded_parser<BOOST_PP_CAT(ParserT, N)>::type \ |
| /**/ |
| #define BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF(z, N, _) \ |
| typedef impl::as_embedded_parser<BOOST_PP_CAT(ParserT, N)> \ |
| BOOST_PP_CAT(parser_t, N); \ |
| /**/ |
| #define BOOST_SPIRIT_SELECT_CONVERT(z, N, _) \ |
| BOOST_PP_CAT(parser_t, N)::convert(BOOST_PP_CAT(p, N)) \ |
| /**/ |
| |
| #define BOOST_SPIRIT_SELECT_PARSER(z, N, _) \ |
| template < \ |
| BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ParserT) \ |
| > \ |
| select_parser< \ |
| ::phoenix::tuple< \ |
| BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N), \ |
| BOOST_SPIRIT_SELECT_EMBEDDED, _) \ |
| >, \ |
| BehaviourT, \ |
| T \ |
| > \ |
| operator()( \ |
| BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N), \ |
| ParserT, const &p) \ |
| ) const \ |
| { \ |
| BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(N), \ |
| BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF, _) \ |
| \ |
| typedef ::phoenix::tuple< \ |
| BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N), \ |
| typename parser_t, ::type BOOST_PP_INTERCEPT) \ |
| > tuple_t; \ |
| typedef select_parser<tuple_t, BehaviourT, T> result_t; \ |
| \ |
| return result_t(tuple_t( \ |
| BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N), \ |
| BOOST_SPIRIT_SELECT_CONVERT, _) \ |
| )); \ |
| } \ |
| /**/ |
| |
| BOOST_PP_REPEAT(BOOST_SPIRIT_SELECT_LIMIT_A, |
| BOOST_SPIRIT_SELECT_PARSER, _) |
| |
| #undef BOOST_SPIRIT_SELECT_PARSER |
| #undef BOOST_SPIRIT_SELECT_CONVERT |
| #undef BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF |
| #undef BOOST_SPIRIT_SELECT_EMBEDDED |
| /////////////////////////////////////////////////////////////////////////// |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Predefined parser generator helper objects |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| select_parser_gen<select_default_no_fail> const select_p = |
| select_parser_gen<select_default_no_fail>(); |
| |
| select_parser_gen<select_default_fail> const select_fail_p = |
| select_parser_gen<select_default_fail>(); |
| |
| #undef BOOST_SPIRIT_SELECT_LIMIT_A |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace BOOST_SPIRIT_CLASSIC_NS |
| |
| #endif // BOOST_SPIRIT_SELECT_HPP |