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