]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
108 | 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 | |
120 | 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 |