1 /*============================================================================= 2 Copyright (c) 2003 Hartmut Kaiser 3 http://spirit.sourceforge.net/ 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 =============================================================================*/ 8 #ifndef BOOST_SPIRIT_SELECT_HPP 9 #define BOOST_SPIRIT_SELECT_HPP 10 11 #include <boost/preprocessor/repeat.hpp> 12 #include <boost/preprocessor/enum.hpp> 13 #include <boost/preprocessor/enum_params.hpp> 14 #include <boost/preprocessor/enum_params_with_defaults.hpp> 15 #include <boost/preprocessor/inc.hpp> 16 #include <boost/preprocessor/cat.hpp> 17 #include <boost/preprocessor/facilities/intercept.hpp> 18 19 #include <boost/spirit/home/classic/namespace.hpp> 20 #include <boost/spirit/home/classic/core/parser.hpp> 21 22 #include <boost/spirit/home/classic/phoenix/tuples.hpp> 23 24 /////////////////////////////////////////////////////////////////////////////// 25 // 26 // Spirit predefined maximum number of possible embedded select_p parsers. 27 // It should NOT be greater than PHOENIX_LIMIT! 28 // 29 /////////////////////////////////////////////////////////////////////////////// 30 #if !defined(BOOST_SPIRIT_SELECT_LIMIT) 31 #define BOOST_SPIRIT_SELECT_LIMIT PHOENIX_LIMIT 32 #endif // !defined(BOOST_SPIRIT_SELECT_LIMIT) 33 34 /////////////////////////////////////////////////////////////////////////////// 35 // 36 // ensure BOOST_SPIRIT_SELECT_LIMIT <= PHOENIX_LIMIT and 37 // BOOST_SPIRIT_SELECT_LIMIT > 0 38 // BOOST_SPIRIT_SELECT_LIMIT <= 15 39 // 40 // [Pushed this down a little to make CW happy with BOOST_STATIC_ASSERT] 41 // [Otherwise, it complains: 'boost_static_assert_test_42' redefined] 42 // 43 /////////////////////////////////////////////////////////////////////////////// 44 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT <= PHOENIX_LIMIT); 45 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT > 0); 46 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SELECT_LIMIT <= 15); 47 48 /////////////////////////////////////////////////////////////////////////////// 49 // 50 // Calculate the required amount of tuple members rounded up to the nearest 51 // integer dividable by 3 52 // 53 /////////////////////////////////////////////////////////////////////////////// 54 #if BOOST_SPIRIT_SELECT_LIMIT > 12 55 #define BOOST_SPIRIT_SELECT_LIMIT_A 15 56 #elif BOOST_SPIRIT_SELECT_LIMIT > 9 57 #define BOOST_SPIRIT_SELECT_LIMIT_A 12 58 #elif BOOST_SPIRIT_SELECT_LIMIT > 6 59 #define BOOST_SPIRIT_SELECT_LIMIT_A 9 60 #elif BOOST_SPIRIT_SELECT_LIMIT > 3 61 #define BOOST_SPIRIT_SELECT_LIMIT_A 6 62 #else 63 #define BOOST_SPIRIT_SELECT_LIMIT_A 3 64 #endif 65 66 /////////////////////////////////////////////////////////////////////////////// 67 namespace boost { namespace spirit { 68 69 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 70 71 /////////////////////////////////////////////////////////////////////////////// 72 // 73 // The select_default_no_fail and select_default_fail structs are used to 74 // distinguish two different behaviours for the select_parser in case that not 75 // any of the given sub-parsers match. 76 // 77 // If the select_parser is used with the select_default_no_fail behaviour, 78 // then in case of no matching sub-parser the whole select_parser returns an 79 // empty match and the value -1. 80 // 81 // If the select_parser is used with the select_default_fail behaviour, then 82 // in case of no matching sub-parser the whole select_parser fails to match at 83 // all. 84 // 85 /////////////////////////////////////////////////////////////////////////////// 86 struct select_default_no_fail {}; 87 struct select_default_fail {}; 88 89 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 90 91 }} // namespace BOOST_SPIRIT_CLASSIC_NS 92 93 /////////////////////////////////////////////////////////////////////////////// 94 #include <boost/spirit/home/classic/dynamic/impl/select.ipp> 95 96 /////////////////////////////////////////////////////////////////////////////// 97 namespace boost { namespace spirit { 98 99 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 100 101 /////////////////////////////////////////////////////////////////////////////// 102 template <typename TupleT, typename BehaviourT, typename T> 103 struct select_parser 104 : public parser<select_parser<TupleT, BehaviourT, T> > 105 { 106 typedef select_parser<TupleT, BehaviourT, T> self_t; 107 select_parserboost::spirit::select_parser108 select_parser(TupleT const &t_) 109 : t(t_) 110 {} 111 112 template <typename ScannerT> 113 struct result 114 { 115 typedef typename match_result<ScannerT, T>::type type; 116 }; 117 118 template <typename ScannerT> 119 typename parser_result<self_t, ScannerT>::type parseboost::spirit::select_parser120 parse(ScannerT const& scan) const 121 { 122 typedef typename parser_result<self_t, ScannerT>::type result_t; 123 124 if (!scan.at_end()) { 125 return impl::parse_tuple_element< 126 TupleT::length, result_t, TupleT, BehaviourT>::do_(t, scan); 127 } 128 return impl::select_match_gen<result_t, BehaviourT>::do_(scan); 129 } 130 131 TupleT const t; 132 }; 133 134 /////////////////////////////////////////////////////////////////////////////// 135 template <typename BehaviourT, typename T = int> 136 struct select_parser_gen { 137 138 /////////////////////////////////////////////////////////////////////////// 139 // 140 // This generates different select_parser_gen::operator()() functions with 141 // an increasing number of parser parameters: 142 // 143 // template <typename ParserT0, ...> 144 // select_parser< 145 // ::phoenix::tuple< 146 // typename impl::as_embedded_parser<ParserT0>::type, 147 // ... 148 // >, 149 // BehaviourT, 150 // T 151 // > 152 // operator()(ParserT0 const &p0, ...) const 153 // { 154 // typedef impl::as_embedded_parser<ParserT0> parser_t0; 155 // ... 156 // 157 // typedef ::phoenix::tuple< 158 // parser_t0::type, 159 // ... 160 // > tuple_t; 161 // typedef select_parser<tuple_t, BehaviourT, T> result_t; 162 // 163 // return result_t(tuple_t( 164 // parser_t0::convert(p0), 165 // ... 166 // )); 167 // } 168 // 169 // The number of generated functions depends on the maximum tuple member 170 // limit defined by the PHOENIX_LIMIT pp constant. 171 // 172 /////////////////////////////////////////////////////////////////////////// 173 #define BOOST_SPIRIT_SELECT_EMBEDDED(z, N, _) \ 174 typename impl::as_embedded_parser<BOOST_PP_CAT(ParserT, N)>::type \ 175 /**/ 176 #define BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF(z, N, _) \ 177 typedef impl::as_embedded_parser<BOOST_PP_CAT(ParserT, N)> \ 178 BOOST_PP_CAT(parser_t, N); \ 179 /**/ 180 #define BOOST_SPIRIT_SELECT_CONVERT(z, N, _) \ 181 BOOST_PP_CAT(parser_t, N)::convert(BOOST_PP_CAT(p, N)) \ 182 /**/ 183 184 #define BOOST_SPIRIT_SELECT_PARSER(z, N, _) \ 185 template < \ 186 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ParserT) \ 187 > \ 188 select_parser< \ 189 ::phoenix::tuple< \ 190 BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N), \ 191 BOOST_SPIRIT_SELECT_EMBEDDED, _) \ 192 >, \ 193 BehaviourT, \ 194 T \ 195 > \ 196 operator()( \ 197 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N), \ 198 ParserT, const &p) \ 199 ) const \ 200 { \ 201 BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(N), \ 202 BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF, _) \ 203 \ 204 typedef ::phoenix::tuple< \ 205 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N), \ 206 typename parser_t, ::type BOOST_PP_INTERCEPT) \ 207 > tuple_t; \ 208 typedef select_parser<tuple_t, BehaviourT, T> result_t; \ 209 \ 210 return result_t(tuple_t( \ 211 BOOST_PP_ENUM_ ## z(BOOST_PP_INC(N), \ 212 BOOST_SPIRIT_SELECT_CONVERT, _) \ 213 )); \ 214 } \ 215 /**/ 216 217 BOOST_PP_REPEAT(BOOST_SPIRIT_SELECT_LIMIT_A, 218 BOOST_SPIRIT_SELECT_PARSER, _) 219 220 #undef BOOST_SPIRIT_SELECT_PARSER 221 #undef BOOST_SPIRIT_SELECT_CONVERT 222 #undef BOOST_SPIRIT_SELECT_EMBEDDED_TYPEDEF 223 #undef BOOST_SPIRIT_SELECT_EMBEDDED 224 /////////////////////////////////////////////////////////////////////////// 225 }; 226 227 /////////////////////////////////////////////////////////////////////////////// 228 // 229 // Predefined parser generator helper objects 230 // 231 /////////////////////////////////////////////////////////////////////////////// 232 select_parser_gen<select_default_no_fail> const select_p = 233 select_parser_gen<select_default_no_fail>(); 234 235 select_parser_gen<select_default_fail> const select_fail_p = 236 select_parser_gen<select_default_fail>(); 237 238 #undef BOOST_SPIRIT_SELECT_LIMIT_A 239 240 /////////////////////////////////////////////////////////////////////////////// 241 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 242 243 }} // namespace BOOST_SPIRIT_CLASSIC_NS 244 245 #endif // BOOST_SPIRIT_SELECT_HPP 246