]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 1998-2003 Joel de Guzman | |
3 | http://spirit.sourceforge.net/ | |
4 | ||
5 | Use, modification and distribution is subject to the Boost Software | |
6 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | http://www.boost.org/LICENSE_1_0.txt) | |
8 | =============================================================================*/ | |
9 | #if !defined(BOOST_SPIRIT_RULE_IPP) | |
10 | #define BOOST_SPIRIT_RULE_IPP | |
11 | ||
12 | #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 | |
13 | #include <boost/preprocessor/repeat.hpp> | |
14 | #include <boost/preprocessor/repeat_from_to.hpp> | |
15 | #include <boost/preprocessor/enum_params.hpp> | |
16 | #include <boost/preprocessor/enum_params_with_defaults.hpp> | |
17 | #include <boost/preprocessor/facilities/intercept.hpp> | |
18 | #include <boost/preprocessor/inc.hpp> | |
19 | #include <boost/preprocessor/cat.hpp> | |
20 | #endif | |
21 | ||
22 | #include <boost/spirit/home/classic/core/parser.hpp> | |
23 | #include <boost/spirit/home/classic/core/scanner/scanner.hpp> | |
24 | #include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp> | |
25 | #include <boost/spirit/home/classic/core/non_terminal/parser_id.hpp> | |
26 | #include <boost/type_traits/is_base_and_derived.hpp> | |
27 | #include <boost/mpl/if.hpp> | |
28 | ||
29 | /////////////////////////////////////////////////////////////////////////////// | |
30 | namespace boost { namespace spirit { | |
31 | ||
32 | BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN | |
33 | ||
34 | #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 | |
35 | ||
36 | template < | |
37 | BOOST_PP_ENUM_BINARY_PARAMS( | |
38 | BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, | |
39 | typename ScannerT, = mpl::void_ BOOST_PP_INTERCEPT | |
40 | ) | |
41 | > | |
42 | struct scanner_list; | |
43 | ||
44 | #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 | |
45 | ||
46 | /////////////////////////////////////////////////////////////////////////// | |
47 | namespace impl | |
48 | { | |
49 | template <typename BaseT, typename DefaultT | |
50 | , typename T0, typename T1, typename T2> | |
51 | struct get_param | |
52 | { | |
53 | typedef typename mpl::if_< | |
54 | is_base_and_derived<BaseT, T0> | |
55 | , T0 | |
56 | , typename mpl::if_< | |
57 | is_base_and_derived<BaseT, T1> | |
58 | , T1 | |
59 | , typename mpl::if_< | |
60 | is_base_and_derived<BaseT, T2> | |
61 | , T2 | |
62 | , DefaultT | |
63 | >::type | |
64 | >::type | |
65 | >::type type; | |
66 | }; | |
67 | ||
68 | template <typename T0, typename T1, typename T2> | |
69 | struct get_context | |
70 | { | |
71 | typedef typename get_param< | |
72 | parser_context_base, parser_context<>, T0, T1, T2>::type | |
73 | type; | |
74 | }; | |
75 | ||
76 | template <typename T0, typename T1, typename T2> | |
77 | struct get_tag | |
78 | { | |
79 | typedef typename get_param< | |
80 | parser_tag_base, parser_address_tag, T0, T1, T2>::type | |
81 | type; | |
82 | }; | |
83 | ||
84 | template <typename T0, typename T1, typename T2> | |
85 | struct get_scanner | |
86 | { | |
87 | typedef typename get_param< | |
88 | scanner_base, scanner<>, T0, T1, T2>::type | |
89 | type; | |
90 | }; | |
91 | ||
92 | /////////////////////////////////////////////////////////////////////// | |
93 | // | |
94 | // rule_base class | |
95 | // | |
96 | // The rule_base class implements the basic plumbing for rules | |
97 | // minus the storage mechanism. It is up to the derived class | |
98 | // to actually store the definition somewhere. The rule_base | |
99 | // class assumes that the derived class provides a get() function | |
100 | // that will return a pointer to a parser. The get() function | |
101 | // may return NULL. See rule below for details. | |
102 | // | |
103 | // <<< For framework use only. Not for public consumption. >>> | |
104 | // | |
105 | /////////////////////////////////////////////////////////////////////// | |
106 | template < | |
107 | typename DerivedT // derived class | |
108 | , typename EmbedT // how derived class is embedded | |
109 | , typename T0 = nil_t // see rule class | |
110 | , typename T1 = nil_t // see rule class | |
111 | , typename T2 = nil_t // see rule class | |
112 | > | |
113 | class rule_base; // forward declaration | |
114 | ||
115 | class rule_base_access | |
116 | { | |
20effc67 | 117 | #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) |
7c673cae FG |
118 | public: // YUCK! |
119 | #else | |
120 | template < | |
121 | typename DerivedT | |
122 | , typename EmbedT | |
123 | , typename T0 | |
124 | , typename T1 | |
125 | , typename T2 | |
126 | > | |
127 | friend class rule_base; | |
128 | #endif | |
129 | template <typename RuleT> | |
130 | static typename RuleT::abstract_parser_t* | |
131 | get(RuleT const& r) | |
132 | { | |
133 | return r.get(); | |
134 | } | |
135 | }; | |
136 | ||
137 | template < | |
138 | typename DerivedT // derived class | |
139 | , typename EmbedT // how derived class is embedded | |
140 | , typename T0 // see rule class | |
141 | , typename T1 // see rule class | |
142 | , typename T2 // see rule class | |
143 | > | |
144 | class rule_base | |
145 | : public parser<DerivedT> | |
146 | , public impl::get_context<T0, T1, T2>::type::base_t | |
147 | , public context_aux< | |
148 | typename impl::get_context<T0, T1, T2>::type, DerivedT> | |
149 | , public impl::get_tag<T0, T1, T2>::type | |
150 | { | |
151 | public: | |
152 | ||
153 | typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t; | |
154 | typedef typename impl::get_context<T0, T1, T2>::type context_t; | |
155 | typedef typename impl::get_tag<T0, T1, T2>::type tag_t; | |
156 | ||
157 | typedef EmbedT embed_t; | |
158 | typedef typename context_t::context_linker_t linked_context_t; | |
159 | typedef typename linked_context_t::attr_t attr_t; | |
160 | ||
161 | template <typename ScannerT> | |
162 | struct result | |
163 | { | |
164 | typedef typename match_result<ScannerT, attr_t>::type type; | |
165 | }; | |
166 | ||
167 | template <typename ScannerT> | |
168 | typename parser_result<DerivedT, ScannerT>::type | |
169 | parse(ScannerT const& scan) const | |
170 | { | |
171 | typedef parser_scanner_linker<ScannerT> linked_scanner_t; | |
172 | typedef typename parser_result<DerivedT, ScannerT>::type result_t; | |
173 | BOOST_SPIRIT_CONTEXT_PARSE( | |
174 | scan, *this, linked_scanner_t, linked_context_t, result_t); | |
175 | } | |
176 | ||
177 | template <typename ScannerT> | |
178 | typename parser_result<DerivedT, ScannerT>::type | |
179 | parse_main(ScannerT const& scan) const | |
180 | { | |
181 | typename parser_result<DerivedT, ScannerT>::type hit; | |
182 | ||
183 | // MWCW 8.3 needs this cast to be done through a pointer, | |
184 | // not a reference. Otherwise, it will silently construct | |
185 | // a temporary, causing an infinite runtime recursion. | |
186 | DerivedT const* derived_this = static_cast<DerivedT const*>(this); | |
187 | ||
188 | if (rule_base_access::get(*derived_this)) | |
189 | { | |
190 | typename ScannerT::iterator_t s(scan.first); | |
191 | hit = rule_base_access::get(*derived_this) | |
192 | ->do_parse_virtual(scan); | |
193 | scan.group_match(hit, this->id(), s, scan.first); | |
194 | } | |
195 | else | |
196 | { | |
197 | hit = scan.no_match(); | |
198 | } | |
199 | return hit; | |
200 | } | |
201 | }; | |
202 | ||
203 | /////////////////////////////////////////////////////////////////////// | |
204 | // | |
205 | // abstract_parser class | |
206 | // | |
207 | /////////////////////////////////////////////////////////////////////// | |
208 | template <typename ScannerT, typename AttrT> | |
209 | struct abstract_parser | |
210 | { | |
211 | abstract_parser() {} | |
212 | virtual ~abstract_parser() {} | |
213 | ||
214 | virtual typename match_result<ScannerT, AttrT>::type | |
215 | do_parse_virtual(ScannerT const& scan) const = 0; | |
216 | ||
217 | virtual abstract_parser* | |
218 | clone() const = 0; | |
219 | }; | |
220 | ||
221 | /////////////////////////////////////////////////////////////////////// | |
222 | // | |
223 | // concrete_parser class | |
224 | // | |
225 | /////////////////////////////////////////////////////////////////////// | |
226 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) | |
227 | #pragma warning(push) | |
228 | #pragma warning(disable:4512) //assignment operator could not be generated | |
229 | #endif | |
230 | ||
231 | template <typename ParserT, typename ScannerT, typename AttrT> | |
232 | struct concrete_parser : abstract_parser<ScannerT, AttrT> | |
233 | { | |
234 | concrete_parser(ParserT const& p_) : p(p_) {} | |
20effc67 | 235 | ~concrete_parser() BOOST_OVERRIDE {} |
7c673cae | 236 | |
20effc67 TL |
237 | typename match_result<ScannerT, AttrT>::type |
238 | do_parse_virtual(ScannerT const& scan) const BOOST_OVERRIDE | |
7c673cae FG |
239 | { |
240 | return p.parse(scan); | |
241 | } | |
242 | ||
20effc67 TL |
243 | abstract_parser<ScannerT, AttrT>* |
244 | clone() const BOOST_OVERRIDE | |
7c673cae FG |
245 | { |
246 | return new concrete_parser(p); | |
247 | } | |
248 | ||
249 | typename ParserT::embed_t p; | |
250 | }; | |
251 | ||
252 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) | |
253 | #pragma warning(pop) | |
254 | #endif | |
255 | ||
256 | #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 | |
257 | ||
258 | /////////////////////////////////////////////////////////////////////// | |
259 | // | |
260 | // This generates partial specializations for the class | |
261 | // | |
262 | // abstract_parser | |
263 | // | |
264 | // with an increasing number of different ScannerT template parameters | |
265 | // and corresponding do_parse_virtual function declarations for each | |
266 | // of the different required scanner types: | |
267 | // | |
268 | // template <typename ScannerT0, ..., typename AttrT> | |
269 | // struct abstract_parser<scanner_list<ScannerT0, ...>, AttrT> | |
270 | // { | |
271 | // abstract_parser() {} | |
272 | // virtual ~abstract_parser() {} | |
273 | // | |
274 | // virtual typename match_result<ScannerT0, AttrT>::type | |
275 | // do_parse_virtual(ScannerT0 const &scan) const = 0; | |
276 | // | |
277 | // virtual abstract_parser* | |
278 | // clone() const = 0; | |
279 | // | |
280 | // ... | |
281 | // }; | |
282 | // | |
283 | /////////////////////////////////////////////////////////////////////// | |
284 | #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_A(z, N, _) \ | |
285 | virtual typename match_result< \ | |
286 | BOOST_PP_CAT(ScannerT, N), AttrT \ | |
287 | >::type \ | |
288 | do_parse_virtual( \ | |
289 | BOOST_PP_CAT(ScannerT, N) const& scan) const = 0; \ | |
290 | ||
291 | #define BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS(z, N, _) \ | |
292 | template < \ | |
293 | BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \ | |
294 | typename AttrT \ | |
295 | > \ | |
296 | struct abstract_parser< \ | |
297 | scanner_list< \ | |
298 | BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ | |
299 | >, \ | |
300 | AttrT \ | |
301 | > \ | |
302 | { \ | |
303 | abstract_parser() {} \ | |
304 | virtual ~abstract_parser() {} \ | |
305 | \ | |
306 | BOOST_PP_REPEAT_ ## z( \ | |
307 | BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_A, _) \ | |
308 | \ | |
309 | virtual abstract_parser* \ | |
310 | clone() const = 0; \ | |
311 | }; \ | |
312 | ||
313 | BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, | |
314 | BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS, _) | |
315 | ||
316 | #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_A | |
317 | #undef BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS | |
318 | /////////////////////////////////////////////////////////////////////// | |
319 | ||
320 | /////////////////////////////////////////////////////////////////////// | |
321 | // | |
322 | // This generates partial specializations for the class | |
323 | // | |
324 | // concrete_parser | |
325 | // | |
326 | // with an increasing number of different ScannerT template parameters | |
327 | // and corresponding do_parse_virtual function declarations for each | |
328 | // of the different required scanner types: | |
329 | // | |
330 | // template < | |
331 | // typename ParserT, typename ScannerT0, ..., typename AttrT | |
332 | // > | |
333 | // struct concrete_parser< | |
334 | // ParserT, scanner_list<ScannerT0, ...>, AttrT | |
335 | // > | |
336 | // : public abstract_parser<scanner_list<ScannerT0, ...>, AttrT> | |
337 | // { | |
338 | // concrete_parser(ParserT const& p_) : p(p_) {} | |
339 | // virtual ~concrete_parser() {} | |
340 | // | |
341 | // virtual typename match_result<ScannerT0, AttrT>::type | |
342 | // do_parse_virtual(ScannerT0 const &scan) const | |
343 | // { return p.parse(scan); } | |
344 | // | |
345 | // virtual abstract_parser<scanner_list<ScannerT0, ...>, AttrT>* | |
346 | // clone() const | |
347 | // { | |
348 | // return new concrete_parser(p); | |
349 | // } | |
350 | // | |
351 | // ... | |
352 | // | |
353 | // typename ParserT::embed_t p; | |
354 | // }; | |
355 | // | |
356 | /////////////////////////////////////////////////////////////////////// | |
357 | #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_C(z, N, _) \ | |
358 | virtual typename match_result< \ | |
359 | BOOST_PP_CAT(ScannerT, N), AttrT \ | |
360 | >::type \ | |
361 | do_parse_virtual( \ | |
362 | BOOST_PP_CAT(ScannerT, N) const& scan) const \ | |
363 | { return p.parse(scan); } \ | |
364 | ||
365 | #define BOOST_SPIRIT_ENUM_CONCRETE_PARSERS(z, N, _) \ | |
366 | template < \ | |
367 | typename ParserT, \ | |
368 | BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \ | |
369 | typename AttrT \ | |
370 | > \ | |
371 | struct concrete_parser< \ | |
372 | ParserT, \ | |
373 | scanner_list< \ | |
374 | BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ | |
375 | >, \ | |
376 | AttrT \ | |
377 | > \ | |
378 | : abstract_parser< \ | |
379 | scanner_list< \ | |
380 | BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ | |
381 | >, \ | |
382 | AttrT \ | |
383 | > \ | |
384 | { \ | |
385 | concrete_parser(ParserT const& p_) : p(p_) {} \ | |
386 | virtual ~concrete_parser() {} \ | |
387 | \ | |
388 | BOOST_PP_REPEAT_ ## z( \ | |
389 | BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_C, _) \ | |
390 | \ | |
391 | virtual abstract_parser< \ | |
392 | scanner_list< \ | |
393 | BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \ | |
394 | >, \ | |
395 | AttrT \ | |
396 | >* \ | |
397 | clone() const \ | |
398 | { \ | |
399 | return new concrete_parser(p); \ | |
400 | } \ | |
401 | \ | |
402 | typename ParserT::embed_t p; \ | |
403 | }; \ | |
404 | ||
405 | BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, | |
406 | BOOST_SPIRIT_ENUM_CONCRETE_PARSERS, _) | |
407 | ||
408 | #undef BOOST_SPIRIT_ENUM_CONCRETE_PARSERS | |
409 | #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_C | |
410 | /////////////////////////////////////////////////////////////////////// | |
411 | ||
412 | #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 | |
413 | ||
414 | } // namespace impl | |
415 | ||
416 | BOOST_SPIRIT_CLASSIC_NAMESPACE_END | |
417 | ||
418 | }} // namespace boost::spirit | |
419 | ||
420 | #endif |