]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/spirit/home/classic/core/non_terminal/impl/rule.ipp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / spirit / home / classic / core / non_terminal / impl / rule.ipp
CommitLineData
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///////////////////////////////////////////////////////////////////////////////
30namespace boost { namespace spirit {
31
32BOOST_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
416BOOST_SPIRIT_CLASSIC_NAMESPACE_END
417
418}} // namespace boost::spirit
419
420#endif