Line data Source code
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 : {
117 : #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
118 : || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
119 : public: // YUCK!
120 : #else
121 : template <
122 : typename DerivedT
123 : , typename EmbedT
124 : , typename T0
125 : , typename T1
126 : , typename T2
127 : >
128 : friend class rule_base;
129 : #endif
130 : template <typename RuleT>
131 : static typename RuleT::abstract_parser_t*
132 0 : get(RuleT const& r)
133 : {
134 0 : return r.get();
135 : }
136 : };
137 :
138 : template <
139 : typename DerivedT // derived class
140 : , typename EmbedT // how derived class is embedded
141 : , typename T0 // see rule class
142 : , typename T1 // see rule class
143 : , typename T2 // see rule class
144 : >
145 : class rule_base
146 : : public parser<DerivedT>
147 : , public impl::get_context<T0, T1, T2>::type::base_t
148 : , public context_aux<
149 : typename impl::get_context<T0, T1, T2>::type, DerivedT>
150 : , public impl::get_tag<T0, T1, T2>::type
151 : {
152 : public:
153 :
154 : typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t;
155 : typedef typename impl::get_context<T0, T1, T2>::type context_t;
156 : typedef typename impl::get_tag<T0, T1, T2>::type tag_t;
157 :
158 : typedef EmbedT embed_t;
159 : typedef typename context_t::context_linker_t linked_context_t;
160 : typedef typename linked_context_t::attr_t attr_t;
161 :
162 : template <typename ScannerT>
163 : struct result
164 : {
165 : typedef typename match_result<ScannerT, attr_t>::type type;
166 : };
167 :
168 : template <typename ScannerT>
169 : typename parser_result<DerivedT, ScannerT>::type
170 0 : parse(ScannerT const& scan) const
171 : {
172 : typedef parser_scanner_linker<ScannerT> linked_scanner_t;
173 : typedef typename parser_result<DerivedT, ScannerT>::type result_t;
174 0 : BOOST_SPIRIT_CONTEXT_PARSE(
175 : scan, *this, linked_scanner_t, linked_context_t, result_t);
176 : }
177 :
178 : template <typename ScannerT>
179 : typename parser_result<DerivedT, ScannerT>::type
180 0 : parse_main(ScannerT const& scan) const
181 : {
182 0 : typename parser_result<DerivedT, ScannerT>::type hit;
183 :
184 : // MWCW 8.3 needs this cast to be done through a pointer,
185 : // not a reference. Otherwise, it will silently construct
186 : // a temporary, causing an infinite runtime recursion.
187 0 : DerivedT const* derived_this = static_cast<DerivedT const*>(this);
188 :
189 0 : if (rule_base_access::get(*derived_this))
190 : {
191 0 : typename ScannerT::iterator_t s(scan.first);
192 0 : hit = rule_base_access::get(*derived_this)
193 : ->do_parse_virtual(scan);
194 0 : scan.group_match(hit, this->id(), s, scan.first);
195 : }
196 : else
197 : {
198 : hit = scan.no_match();
199 : }
200 : return hit;
201 : }
202 : };
203 :
204 : ///////////////////////////////////////////////////////////////////////
205 : //
206 : // abstract_parser class
207 : //
208 : ///////////////////////////////////////////////////////////////////////
209 : template <typename ScannerT, typename AttrT>
210 : struct abstract_parser
211 : {
212 0 : abstract_parser() {}
213 0 : virtual ~abstract_parser() {}
214 :
215 : virtual typename match_result<ScannerT, AttrT>::type
216 : do_parse_virtual(ScannerT const& scan) const = 0;
217 :
218 : virtual abstract_parser*
219 : clone() const = 0;
220 : };
221 :
222 : ///////////////////////////////////////////////////////////////////////
223 : //
224 : // concrete_parser class
225 : //
226 : ///////////////////////////////////////////////////////////////////////
227 : #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
228 : #pragma warning(push)
229 : #pragma warning(disable:4512) //assignment operator could not be generated
230 : #endif
231 :
232 : template <typename ParserT, typename ScannerT, typename AttrT>
233 : struct concrete_parser : abstract_parser<ScannerT, AttrT>
234 : {
235 0 : concrete_parser(ParserT const& p_) : p(p_) {}
236 0 : virtual ~concrete_parser() {}
237 :
238 : virtual typename match_result<ScannerT, AttrT>::type
239 0 : do_parse_virtual(ScannerT const& scan) const
240 : {
241 0 : return p.parse(scan);
242 : }
243 :
244 : virtual abstract_parser<ScannerT, AttrT>*
245 0 : clone() const
246 : {
247 0 : return new concrete_parser(p);
248 : }
249 :
250 : typename ParserT::embed_t p;
251 : };
252 :
253 : #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
254 : #pragma warning(pop)
255 : #endif
256 :
257 : #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
258 :
259 : ///////////////////////////////////////////////////////////////////////
260 : //
261 : // This generates partial specializations for the class
262 : //
263 : // abstract_parser
264 : //
265 : // with an increasing number of different ScannerT template parameters
266 : // and corresponding do_parse_virtual function declarations for each
267 : // of the different required scanner types:
268 : //
269 : // template <typename ScannerT0, ..., typename AttrT>
270 : // struct abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
271 : // {
272 : // abstract_parser() {}
273 : // virtual ~abstract_parser() {}
274 : //
275 : // virtual typename match_result<ScannerT0, AttrT>::type
276 : // do_parse_virtual(ScannerT0 const &scan) const = 0;
277 : //
278 : // virtual abstract_parser*
279 : // clone() const = 0;
280 : //
281 : // ...
282 : // };
283 : //
284 : ///////////////////////////////////////////////////////////////////////
285 : #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_A(z, N, _) \
286 : virtual typename match_result< \
287 : BOOST_PP_CAT(ScannerT, N), AttrT \
288 : >::type \
289 : do_parse_virtual( \
290 : BOOST_PP_CAT(ScannerT, N) const& scan) const = 0; \
291 :
292 : #define BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS(z, N, _) \
293 : template < \
294 : BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \
295 : typename AttrT \
296 : > \
297 : struct abstract_parser< \
298 : scanner_list< \
299 : BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
300 : >, \
301 : AttrT \
302 : > \
303 : { \
304 : abstract_parser() {} \
305 : virtual ~abstract_parser() {} \
306 : \
307 : BOOST_PP_REPEAT_ ## z( \
308 : BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_A, _) \
309 : \
310 : virtual abstract_parser* \
311 : clone() const = 0; \
312 : }; \
313 :
314 : BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
315 : BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS, _)
316 :
317 : #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_A
318 : #undef BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS
319 : ///////////////////////////////////////////////////////////////////////
320 :
321 : ///////////////////////////////////////////////////////////////////////
322 : //
323 : // This generates partial specializations for the class
324 : //
325 : // concrete_parser
326 : //
327 : // with an increasing number of different ScannerT template parameters
328 : // and corresponding do_parse_virtual function declarations for each
329 : // of the different required scanner types:
330 : //
331 : // template <
332 : // typename ParserT, typename ScannerT0, ..., typename AttrT
333 : // >
334 : // struct concrete_parser<
335 : // ParserT, scanner_list<ScannerT0, ...>, AttrT
336 : // >
337 : // : public abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
338 : // {
339 : // concrete_parser(ParserT const& p_) : p(p_) {}
340 : // virtual ~concrete_parser() {}
341 : //
342 : // virtual typename match_result<ScannerT0, AttrT>::type
343 : // do_parse_virtual(ScannerT0 const &scan) const
344 : // { return p.parse(scan); }
345 : //
346 : // virtual abstract_parser<scanner_list<ScannerT0, ...>, AttrT>*
347 : // clone() const
348 : // {
349 : // return new concrete_parser(p);
350 : // }
351 : //
352 : // ...
353 : //
354 : // typename ParserT::embed_t p;
355 : // };
356 : //
357 : ///////////////////////////////////////////////////////////////////////
358 : #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_C(z, N, _) \
359 : virtual typename match_result< \
360 : BOOST_PP_CAT(ScannerT, N), AttrT \
361 : >::type \
362 : do_parse_virtual( \
363 : BOOST_PP_CAT(ScannerT, N) const& scan) const \
364 : { return p.parse(scan); } \
365 :
366 : #define BOOST_SPIRIT_ENUM_CONCRETE_PARSERS(z, N, _) \
367 : template < \
368 : typename ParserT, \
369 : BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \
370 : typename AttrT \
371 : > \
372 : struct concrete_parser< \
373 : ParserT, \
374 : scanner_list< \
375 : BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
376 : >, \
377 : AttrT \
378 : > \
379 : : abstract_parser< \
380 : scanner_list< \
381 : BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
382 : >, \
383 : AttrT \
384 : > \
385 : { \
386 : concrete_parser(ParserT const& p_) : p(p_) {} \
387 : virtual ~concrete_parser() {} \
388 : \
389 : BOOST_PP_REPEAT_ ## z( \
390 : BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_C, _) \
391 : \
392 : virtual abstract_parser< \
393 : scanner_list< \
394 : BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
395 : >, \
396 : AttrT \
397 : >* \
398 : clone() const \
399 : { \
400 : return new concrete_parser(p); \
401 : } \
402 : \
403 : typename ParserT::embed_t p; \
404 : }; \
405 :
406 : BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
407 : BOOST_SPIRIT_ENUM_CONCRETE_PARSERS, _)
408 :
409 : #undef BOOST_SPIRIT_ENUM_CONCRETE_PARSERS
410 : #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_C
411 : ///////////////////////////////////////////////////////////////////////
412 :
413 : #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
414 :
415 : } // namespace impl
416 :
417 : BOOST_SPIRIT_CLASSIC_NAMESPACE_END
418 :
419 : }} // namespace boost::spirit
420 :
421 : #endif
|