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