]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2001-2011 Hartmut Kaiser | |
4 | Copyright (c) 2011 Thomas Heller | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ==============================================================================*/ | |
9 | #if !defined(BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM) | |
10 | #define BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | #include <boost/config.hpp> | |
17 | #include <boost/spirit/include/phoenix_core.hpp> | |
18 | #include <boost/spirit/include/phoenix_function.hpp> | |
19 | #include <boost/proto/proto.hpp> | |
20 | #include <boost/spirit/home/support/meta_compiler.hpp> | |
21 | #include <boost/spirit/home/support/detail/make_vector.hpp> | |
22 | #include <boost/spirit/home/support/unused.hpp> | |
23 | #include <boost/spirit/home/support/detail/is_spirit_tag.hpp> | |
24 | #include <boost/preprocessor/tuple/elem.hpp> | |
25 | ||
26 | #include <boost/spirit/home/support/terminal_expression.hpp> | |
27 | ||
28 | namespace boost { namespace spirit | |
29 | { | |
30 | template <typename Terminal, typename Args> | |
31 | struct terminal_ex | |
32 | { | |
33 | typedef Terminal terminal_type; | |
34 | typedef Args args_type; | |
35 | ||
36 | terminal_ex(Args const& args_) | |
37 | : args(args_) {} | |
38 | terminal_ex(Args const& args_, Terminal const& term_) | |
39 | : args(args_), term(term_) {} | |
40 | ||
41 | Args args; // Args is guaranteed to be a fusion::vectorN so you | |
42 | // can use that template for detection and specialization | |
43 | Terminal term; | |
44 | }; | |
45 | ||
46 | template <typename Terminal, typename Actor, int Arity> | |
47 | struct lazy_terminal | |
48 | { | |
49 | typedef Terminal terminal_type; | |
50 | typedef Actor actor_type; | |
51 | static int const arity = Arity; | |
52 | ||
53 | lazy_terminal(Actor const& actor_) | |
54 | : actor(actor_) {} | |
55 | lazy_terminal(Actor const& actor_, Terminal const& term_) | |
56 | : actor(actor_), term(term_) {} | |
57 | ||
58 | Actor actor; | |
59 | Terminal term; | |
60 | }; | |
61 | ||
62 | template <typename Domain, typename Terminal, int Arity, typename Enable = void> | |
63 | struct use_lazy_terminal : mpl::false_ {}; | |
64 | ||
65 | template <typename Domain, typename Terminal, int Arity, typename Enable = void> | |
66 | struct use_lazy_directive : mpl::false_ {}; | |
67 | ||
68 | template <typename Terminal> | |
69 | struct terminal; | |
70 | ||
71 | template <typename Domain, typename Terminal> | |
72 | struct use_terminal<Domain, terminal<Terminal> > | |
73 | : use_terminal<Domain, Terminal> {}; | |
74 | ||
75 | template <typename Domain, typename Terminal, int Arity, typename Actor> | |
76 | struct use_terminal<Domain, lazy_terminal<Terminal, Actor, Arity> > | |
77 | : use_lazy_terminal<Domain, Terminal, Arity> {}; | |
78 | ||
79 | template <typename Domain, typename Terminal, int Arity, typename Actor> | |
80 | struct use_directive<Domain, lazy_terminal<Terminal, Actor, Arity> > | |
81 | : use_lazy_directive<Domain, Terminal, Arity> {}; | |
82 | ||
83 | template < | |
84 | typename F | |
85 | , typename A0 = unused_type | |
86 | , typename A1 = unused_type | |
87 | , typename A2 = unused_type | |
88 | , typename Unused = unused_type | |
89 | > | |
90 | struct make_lazy; | |
91 | ||
92 | template <typename F, typename A0> | |
93 | struct make_lazy<F, A0> | |
94 | { | |
95 | typedef typename | |
96 | proto::terminal< | |
97 | lazy_terminal< | |
98 | typename F::terminal_type | |
99 | , typename phoenix::detail::expression::function_eval<F, A0>::type | |
100 | , 1 // arity | |
101 | > | |
102 | >::type | |
103 | result_type; | |
104 | typedef result_type type; | |
105 | ||
106 | result_type | |
107 | operator()(F f, A0 const& _0_) const | |
108 | { | |
109 | typedef typename result_type::proto_child0 child_type; | |
110 | return result_type::make(child_type( | |
111 | phoenix::detail::expression::function_eval<F, A0>::make(f, _0_) | |
112 | , f.proto_base().child0 | |
113 | )); | |
114 | } | |
115 | }; | |
116 | ||
117 | template <typename F, typename A0, typename A1> | |
118 | struct make_lazy<F, A0, A1> | |
119 | { | |
120 | typedef typename | |
121 | proto::terminal< | |
122 | lazy_terminal< | |
123 | typename F::terminal_type | |
124 | , typename phoenix::detail::expression::function_eval<F, A0, A1>::type | |
125 | , 2 // arity | |
126 | > | |
127 | >::type | |
128 | result_type; | |
129 | typedef result_type type; | |
130 | ||
131 | result_type | |
132 | operator()(F f, A0 const& _0_, A1 const& _1_) const | |
133 | { | |
134 | typedef typename result_type::proto_child0 child_type; | |
135 | return result_type::make(child_type( | |
136 | phoenix::detail::expression::function_eval<F, A0, A1>::make(f, _0_, _1_) | |
137 | , f.proto_base().child0 | |
138 | )); | |
139 | } | |
140 | }; | |
141 | ||
142 | template <typename F, typename A0, typename A1, typename A2> | |
143 | struct make_lazy<F, A0, A1, A2> | |
144 | { | |
145 | typedef typename | |
146 | proto::terminal< | |
147 | lazy_terminal< | |
148 | typename F::terminal_type | |
149 | , typename phoenix::detail::expression::function_eval<F, A0, A1, A2>::type | |
150 | , 3 // arity | |
151 | > | |
152 | >::type | |
153 | result_type; | |
154 | typedef result_type type; | |
155 | ||
156 | result_type | |
157 | operator()(F f, A0 const& _0_, A1 const& _1_, A2 const& _2_) const | |
158 | { | |
159 | typedef typename result_type::proto_child0 child_type; | |
160 | return result_type::make(child_type( | |
161 | phoenix::detail::expression::function_eval<F, A0, A1, A2>::make(f, _0_, _1_, _2_) | |
162 | , f.proto_base().child0 | |
163 | )); | |
164 | } | |
165 | }; | |
166 | ||
167 | namespace detail | |
168 | { | |
169 | // Helper struct for SFINAE purposes | |
170 | template <bool C> struct bool_; | |
171 | ||
172 | template <> | |
173 | struct bool_<true> : mpl::bool_<true> | |
174 | { | |
175 | typedef bool_<true>* is_true; | |
176 | }; | |
177 | ||
178 | template <> | |
179 | struct bool_<false> : mpl::bool_<false> | |
180 | { | |
181 | typedef bool_<false>* is_false; | |
182 | }; | |
183 | ||
184 | // Metafunction to detect if at least one arg is a Phoenix actor | |
185 | template < | |
186 | typename A0 | |
187 | , typename A1 = unused_type | |
188 | , typename A2 = unused_type | |
189 | > | |
190 | struct contains_actor | |
191 | : bool_< | |
192 | phoenix::is_actor<A0>::value | |
193 | || phoenix::is_actor<A1>::value | |
194 | || phoenix::is_actor<A2>::value | |
195 | > | |
196 | {}; | |
197 | ||
198 | // to_lazy_arg: convert a terminal arg type to the type make_lazy needs | |
199 | template <typename A> | |
200 | struct to_lazy_arg | |
201 | : phoenix::as_actor<A> // wrap A in a Phoenix actor if not already one | |
202 | {}; | |
203 | ||
204 | template <typename A> | |
205 | struct to_lazy_arg<const A> | |
206 | : to_lazy_arg<A> | |
207 | {}; | |
208 | ||
209 | template <typename A> | |
210 | struct to_lazy_arg<A &> | |
211 | : to_lazy_arg<A> | |
212 | {}; | |
213 | ||
214 | template <> | |
215 | struct to_lazy_arg<unused_type> | |
216 | { | |
217 | // unused arg: make_lazy wants unused_type | |
218 | typedef unused_type type; | |
219 | }; | |
220 | ||
221 | // to_nonlazy_arg: convert a terminal arg type to the type make_vector needs | |
222 | template <typename A> | |
223 | struct to_nonlazy_arg | |
224 | { | |
225 | // identity | |
226 | typedef A type; | |
227 | }; | |
228 | ||
229 | template <typename A> | |
230 | struct to_nonlazy_arg<const A> | |
231 | : to_nonlazy_arg<A> | |
232 | {}; | |
233 | ||
234 | template <typename A> | |
235 | struct to_nonlazy_arg<A &> | |
236 | : to_nonlazy_arg<A> | |
237 | {}; | |
238 | ||
239 | // incomplete type: should not be appeared unused_type in nonlazy arg. | |
240 | template <> | |
241 | struct to_nonlazy_arg<unused_type>; | |
242 | } | |
243 | ||
244 | template <typename Terminal> | |
245 | struct terminal | |
246 | : proto::extends< | |
247 | typename proto::terminal<Terminal>::type | |
248 | , terminal<Terminal> | |
249 | > | |
250 | { | |
251 | typedef terminal<Terminal> this_type; | |
252 | typedef Terminal terminal_type; | |
253 | ||
254 | typedef proto::extends< | |
255 | typename proto::terminal<Terminal>::type | |
256 | , terminal<Terminal> | |
257 | > base_type; | |
258 | ||
259 | terminal() {} | |
260 | ||
261 | terminal(Terminal const& t) | |
262 | : base_type(proto::terminal<Terminal>::type::make(t)) | |
263 | {} | |
264 | ||
265 | #if defined(BOOST_MSVC) | |
266 | #pragma warning(push) | |
267 | // warning C4348: 'boost::spirit::terminal<...>::result_helper': redefinition of default parameter: parameter 3, 4 | |
268 | #pragma warning(disable: 4348) | |
269 | #endif | |
270 | ||
271 | template < | |
272 | bool Lazy | |
273 | , typename A0 | |
274 | , typename A1 = unused_type | |
275 | , typename A2 = unused_type | |
276 | > | |
277 | struct result_helper; | |
278 | ||
279 | #if defined(BOOST_MSVC) | |
280 | #pragma warning(pop) | |
281 | #endif | |
282 | ||
283 | template < | |
284 | typename A0 | |
285 | > | |
286 | struct result_helper<false, A0> | |
287 | { | |
288 | typedef typename | |
289 | proto::terminal< | |
290 | terminal_ex< | |
291 | Terminal | |
292 | , typename detail::result_of::make_vector< | |
293 | typename detail::to_nonlazy_arg<A0>::type>::type> | |
294 | >::type | |
295 | type; | |
296 | }; | |
297 | ||
298 | template < | |
299 | typename A0 | |
300 | , typename A1 | |
301 | > | |
302 | struct result_helper<false, A0, A1> | |
303 | { | |
304 | typedef typename | |
305 | proto::terminal< | |
306 | terminal_ex< | |
307 | Terminal | |
308 | , typename detail::result_of::make_vector< | |
309 | typename detail::to_nonlazy_arg<A0>::type | |
310 | , typename detail::to_nonlazy_arg<A1>::type>::type> | |
311 | >::type | |
312 | type; | |
313 | }; | |
314 | ||
315 | template < | |
316 | typename A0 | |
317 | , typename A1 | |
318 | , typename A2 | |
319 | > | |
320 | struct result_helper<false, A0, A1, A2> | |
321 | { | |
322 | typedef typename | |
323 | proto::terminal< | |
324 | terminal_ex< | |
325 | Terminal | |
326 | , typename detail::result_of::make_vector< | |
327 | typename detail::to_nonlazy_arg<A0>::type | |
328 | , typename detail::to_nonlazy_arg<A1>::type | |
329 | , typename detail::to_nonlazy_arg<A2>::type>::type> | |
330 | >::type | |
331 | type; | |
332 | }; | |
333 | ||
334 | template < | |
335 | typename A0 | |
336 | , typename A1 | |
337 | , typename A2 | |
338 | > | |
339 | struct result_helper<true, A0, A1, A2> | |
340 | { | |
341 | typedef typename | |
342 | make_lazy<this_type | |
343 | , typename detail::to_lazy_arg<A0>::type | |
344 | , typename detail::to_lazy_arg<A1>::type | |
345 | , typename detail::to_lazy_arg<A2>::type>::type | |
346 | type; | |
347 | }; | |
348 | ||
349 | // FIXME: we need to change this to conform to the result_of protocol | |
350 | template < | |
351 | typename A0 | |
352 | , typename A1 = unused_type | |
353 | , typename A2 = unused_type // Support up to 3 args | |
354 | > | |
355 | struct result | |
356 | { | |
357 | typedef typename | |
358 | result_helper< | |
359 | detail::contains_actor<A0, A1, A2>::value | |
360 | , A0, A1, A2 | |
361 | >::type | |
362 | type; | |
363 | }; | |
364 | ||
365 | template <typename This, typename A0> | |
366 | struct result<This(A0)> | |
367 | { | |
368 | typedef typename | |
369 | result_helper< | |
370 | detail::contains_actor<A0, unused_type, unused_type>::value | |
371 | , A0, unused_type, unused_type | |
372 | >::type | |
373 | type; | |
374 | }; | |
375 | ||
376 | template <typename This, typename A0, typename A1> | |
377 | struct result<This(A0, A1)> | |
378 | { | |
379 | typedef typename | |
380 | result_helper< | |
381 | detail::contains_actor<A0, A1, unused_type>::value | |
382 | , A0, A1, unused_type | |
383 | >::type | |
384 | type; | |
385 | }; | |
386 | ||
387 | ||
388 | template <typename This, typename A0, typename A1, typename A2> | |
389 | struct result<This(A0, A1, A2)> | |
390 | { | |
391 | typedef typename | |
392 | result_helper< | |
393 | detail::contains_actor<A0, A1, A2>::value | |
394 | , A0, A1, A2 | |
395 | >::type | |
396 | type; | |
397 | }; | |
398 | ||
399 | // Note: in the following overloads, SFINAE cannot | |
400 | // be done on return type because of gcc bug #24915: | |
401 | // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24915 | |
402 | // Hence an additional, fake argument is used for SFINAE, | |
403 | // using a type which can never be a real argument type. | |
404 | ||
405 | // Non-lazy overloads. Only enabled when all | |
406 | // args are immediates (no Phoenix actor). | |
407 | ||
408 | template <typename A0> | |
409 | typename result<A0>::type | |
410 | operator()(A0 const& _0_ | |
411 | , typename detail::contains_actor<A0>::is_false = 0) const | |
412 | { | |
413 | typedef typename result<A0>::type result_type; | |
414 | typedef typename result_type::proto_child0 child_type; | |
415 | return result_type::make( | |
416 | child_type( | |
417 | detail::make_vector(_0_) | |
418 | , this->proto_base().child0) | |
419 | ); | |
420 | } | |
421 | ||
422 | template <typename A0, typename A1> | |
423 | typename result<A0, A1>::type | |
424 | operator()(A0 const& _0_, A1 const& _1_ | |
425 | , typename detail::contains_actor<A0, A1>::is_false = 0) const | |
426 | { | |
427 | typedef typename result<A0, A1>::type result_type; | |
428 | typedef typename result_type::proto_child0 child_type; | |
429 | return result_type::make( | |
430 | child_type( | |
431 | detail::make_vector(_0_, _1_) | |
432 | , this->proto_base().child0) | |
433 | ); | |
434 | } | |
435 | ||
436 | template <typename A0, typename A1, typename A2> | |
437 | typename result<A0, A1, A2>::type | |
438 | operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_ | |
439 | , typename detail::contains_actor<A0, A1, A2>::is_false = 0) const | |
440 | { | |
441 | typedef typename result<A0, A1, A2>::type result_type; | |
442 | typedef typename result_type::proto_child0 child_type; | |
443 | return result_type::make( | |
444 | child_type( | |
445 | detail::make_vector(_0_, _1_, _2_) | |
446 | , this->proto_base().child0) | |
447 | ); | |
448 | } | |
449 | ||
450 | // Lazy overloads. Enabled when at | |
451 | // least one arg is a Phoenix actor. | |
452 | template <typename A0> | |
453 | typename result<A0>::type | |
454 | operator()(A0 const& _0_ | |
455 | , typename detail::contains_actor<A0>::is_true = 0) const | |
456 | { | |
457 | return make_lazy<this_type | |
458 | , typename phoenix::as_actor<A0>::type>()(*this | |
459 | , phoenix::as_actor<A0>::convert(_0_)); | |
460 | } | |
461 | ||
462 | template <typename A0, typename A1> | |
463 | typename result<A0, A1>::type | |
464 | operator()(A0 const& _0_, A1 const& _1_ | |
465 | , typename detail::contains_actor<A0, A1>::is_true = 0) const | |
466 | { | |
467 | return make_lazy<this_type | |
468 | , typename phoenix::as_actor<A0>::type | |
469 | , typename phoenix::as_actor<A1>::type>()(*this | |
470 | , phoenix::as_actor<A0>::convert(_0_) | |
471 | , phoenix::as_actor<A1>::convert(_1_)); | |
472 | } | |
473 | ||
474 | template <typename A0, typename A1, typename A2> | |
475 | typename result<A0, A1, A2>::type | |
476 | operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_ | |
477 | , typename detail::contains_actor<A0, A1, A2>::is_true = 0) const | |
478 | { | |
479 | return make_lazy<this_type | |
480 | , typename phoenix::as_actor<A0>::type | |
481 | , typename phoenix::as_actor<A1>::type | |
482 | , typename phoenix::as_actor<A2>::type>()(*this | |
483 | , phoenix::as_actor<A0>::convert(_0_) | |
484 | , phoenix::as_actor<A1>::convert(_1_) | |
485 | , phoenix::as_actor<A2>::convert(_2_)); | |
486 | } | |
487 | ||
488 | private: | |
489 | // silence MSVC warning C4512: assignment operator could not be generated | |
490 | terminal& operator= (terminal const&); | |
491 | }; | |
492 | ||
493 | /////////////////////////////////////////////////////////////////////////// | |
494 | namespace result_of | |
495 | { | |
496 | // Calculate the type of the compound terminal if generated by one of | |
497 | // the spirit::terminal::operator() overloads above | |
498 | ||
499 | // The terminal type itself is passed through without modification | |
500 | template <typename Tag> | |
501 | struct terminal | |
502 | { | |
503 | typedef spirit::terminal<Tag> type; | |
504 | }; | |
505 | ||
506 | template <typename Tag, typename A0> | |
507 | struct terminal<Tag(A0)> | |
508 | { | |
509 | typedef typename spirit::terminal<Tag>:: | |
510 | template result<A0>::type type; | |
511 | }; | |
512 | ||
513 | template <typename Tag, typename A0, typename A1> | |
514 | struct terminal<Tag(A0, A1)> | |
515 | { | |
516 | typedef typename spirit::terminal<Tag>:: | |
517 | template result<A0, A1>::type type; | |
518 | }; | |
519 | ||
520 | template <typename Tag, typename A0, typename A1, typename A2> | |
521 | struct terminal<Tag(A0, A1, A2)> | |
522 | { | |
523 | typedef typename spirit::terminal<Tag>:: | |
524 | template result<A0, A1, A2>::type type; | |
525 | }; | |
526 | } | |
527 | ||
528 | /////////////////////////////////////////////////////////////////////////// | |
529 | // support for stateful tag types | |
530 | namespace tag | |
531 | { | |
532 | template < | |
533 | typename Data, typename Tag | |
534 | , typename DataTag1 = unused_type, typename DataTag2 = unused_type> | |
535 | struct stateful_tag | |
536 | { | |
537 | BOOST_SPIRIT_IS_TAG() | |
538 | ||
539 | typedef Data data_type; | |
540 | ||
541 | stateful_tag() {} | |
542 | stateful_tag(data_type const& data) : data_(data) {} | |
543 | ||
544 | data_type data_; | |
545 | ||
546 | private: | |
547 | // silence MSVC warning C4512: assignment operator could not be generated | |
548 | stateful_tag& operator= (stateful_tag const&); | |
549 | }; | |
550 | } | |
551 | ||
552 | template < | |
553 | typename Data, typename Tag | |
554 | , typename DataTag1 = unused_type, typename DataTag2 = unused_type> | |
555 | struct stateful_tag_type | |
556 | : spirit::terminal<tag::stateful_tag<Data, Tag, DataTag1, DataTag2> > | |
557 | { | |
558 | typedef tag::stateful_tag<Data, Tag, DataTag1, DataTag2> tag_type; | |
559 | ||
560 | stateful_tag_type() {} | |
561 | stateful_tag_type(Data const& data) | |
562 | : spirit::terminal<tag_type>(data) | |
563 | {} | |
564 | ||
565 | private: | |
566 | // silence MSVC warning C4512: assignment operator could not be generated | |
567 | stateful_tag_type& operator= (stateful_tag_type const&); | |
568 | }; | |
569 | ||
570 | namespace detail | |
571 | { | |
572 | // extract expression if this is a Tag | |
573 | template <typename StatefulTag> | |
574 | struct get_stateful_data | |
575 | { | |
576 | typedef typename StatefulTag::data_type data_type; | |
577 | ||
578 | // is invoked if given tag is != Tag | |
579 | template <typename Tag_> | |
580 | static data_type call(Tag_) { return data_type(); } | |
581 | ||
582 | // this is invoked if given tag is same as'Tag' | |
583 | static data_type const& call(StatefulTag const& t) { return t.data_; } | |
584 | }; | |
585 | } | |
586 | ||
587 | }} | |
588 | ||
589 | namespace boost { namespace phoenix | |
590 | { | |
591 | template <typename Tag> | |
592 | struct is_custom_terminal<Tag, typename Tag::is_spirit_tag> | |
593 | : mpl::true_ | |
594 | {}; | |
595 | ||
596 | template <typename Tag> | |
597 | struct custom_terminal<Tag, typename Tag::is_spirit_tag> | |
598 | { | |
599 | #ifndef BOOST_PHOENIX_NO_SPECIALIZE_CUSTOM_TERMINAL | |
600 | typedef void _is_default_custom_terminal; // fix for #7730 | |
601 | #endif | |
602 | ||
603 | typedef spirit::terminal<Tag> result_type; | |
604 | ||
605 | template <typename Context> | |
606 | result_type operator()(Tag const & t, Context const &) | |
607 | { | |
608 | return spirit::terminal<Tag>(t); | |
609 | } | |
610 | }; | |
611 | }} | |
612 | ||
613 | // Define a spirit terminal. This macro may be placed in any namespace. | |
614 | // Common placeholders are placed in the main boost::spirit namespace | |
615 | // (see common_terminals.hpp) | |
616 | ||
617 | #define BOOST_SPIRIT_TERMINAL_X(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_Y | |
618 | #define BOOST_SPIRIT_TERMINAL_Y(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_X | |
619 | #define BOOST_SPIRIT_TERMINAL_X0 | |
620 | #define BOOST_SPIRIT_TERMINAL_Y0 | |
621 | ||
622 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
623 | ||
624 | #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \ | |
625 | namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \ | |
626 | typedef boost::proto::terminal<tag::name>::type type_name; \ | |
627 | type_name const name = {{}}; \ | |
628 | inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \ | |
629 | /***/ | |
630 | ||
631 | #else | |
632 | ||
633 | #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \ | |
634 | namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \ | |
635 | typedef boost::proto::terminal<tag::name>::type type_name; \ | |
636 | /***/ | |
637 | ||
638 | #endif | |
639 | ||
640 | #define BOOST_SPIRIT_TERMINAL(name) \ | |
641 | BOOST_SPIRIT_TERMINAL_NAME(name, name ## _type) \ | |
642 | /***/ | |
643 | ||
644 | #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A(r, _, names) \ | |
645 | BOOST_SPIRIT_TERMINAL_NAME( \ | |
646 | BOOST_PP_TUPLE_ELEM(2, 0, names), \ | |
647 | BOOST_PP_TUPLE_ELEM(2, 1, names) \ | |
648 | ) \ | |
649 | /***/ | |
650 | ||
651 | #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME(seq) \ | |
652 | BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A, _, \ | |
653 | BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \ | |
654 | /***/ | |
655 | ||
656 | // Define a spirit extended terminal. This macro may be placed in any namespace. | |
657 | // Common placeholders are placed in the main boost::spirit namespace | |
658 | // (see common_terminals.hpp) | |
659 | ||
660 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
661 | ||
662 | #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \ | |
663 | namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \ | |
664 | typedef boost::spirit::terminal<tag::name> type_name; \ | |
665 | type_name const name = type_name(); \ | |
666 | inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \ | |
667 | /***/ | |
668 | ||
669 | #else | |
670 | ||
671 | #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \ | |
672 | namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \ | |
673 | typedef boost::spirit::terminal<tag::name> type_name; \ | |
674 | /***/ | |
675 | ||
676 | #endif | |
677 | ||
678 | #define BOOST_SPIRIT_TERMINAL_EX(name) \ | |
679 | BOOST_SPIRIT_TERMINAL_NAME_EX(name, name ## _type) \ | |
680 | /***/ | |
681 | ||
682 | #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A(r, _, names) \ | |
683 | BOOST_SPIRIT_TERMINAL_NAME_EX( \ | |
684 | BOOST_PP_TUPLE_ELEM(2, 0, names), \ | |
685 | BOOST_PP_TUPLE_ELEM(2, 1, names) \ | |
686 | ) \ | |
687 | /***/ | |
688 | ||
689 | #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(seq) \ | |
690 | BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A, _, \ | |
691 | BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \ | |
692 | /***/ | |
693 | ||
694 | #endif | |
695 | ||
696 |