1 /*=============================================================================
2     Copyright (c) 2010 Thomas Heller
3 
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 
8 #ifndef BOOST_PHOENIX_CORE_DETAIL_EXPRESSION_HPP
9 #define BOOST_PHOENIX_CORE_DETAIL_EXPRESSION_HPP
10 
11 #include <boost/preprocessor/empty.hpp>
12 #include <boost/preprocessor/arithmetic/add.hpp>
13 #include <boost/preprocessor/arithmetic/dec.hpp>
14 #include <boost/preprocessor/comma_if.hpp>
15 #include <boost/preprocessor/comparison/equal.hpp>
16 #include <boost/preprocessor/seq/size.hpp>
17 #include <boost/preprocessor/seq/enum.hpp>
18 #include <boost/preprocessor/seq/for_each.hpp>
19 #include <boost/preprocessor/seq/pop_back.hpp>
20 #include <boost/preprocessor/seq/reverse.hpp>
21 #include <boost/preprocessor/tuple/elem.hpp>
22 #include <boost/preprocessor/enum_params.hpp>
23 #include <boost/preprocessor/repeat_from_to.hpp>
24 
25 #define BOOST_PHOENIX_DEFINE_EXPRESSION(NAME_SEQ, SEQ)                          \
26     BOOST_PHOENIX_DEFINE_EXPRESSION_BASE(                                       \
27         NAME_SEQ                                                                \
28       , SEQ                                                                     \
29       , BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_DEFAULT                      \
30       , BOOST_PHOENIX_DEFINE_EXPRESSION_RULE_DEFAULT                            \
31       , BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_DEFAULT                  \
32       , BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_DEFAULT                 \
33       , _                                                                       \
34     )                                                                           \
35 /**/
36 
37 #define BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG(NAME_SEQ, GRAMMAR_SEQ, LIMIT)    \
38     BOOST_PHOENIX_DEFINE_EXPRESSION_BASE(                                       \
39         NAME_SEQ                                                                \
40       , GRAMMAR_SEQ                                                             \
41       , BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_VARARG                       \
42       , BOOST_PHOENIX_DEFINE_EXPRESSION_RULE_VARARG                             \
43       , BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_VARARG                   \
44       , BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_VARARG                  \
45       , LIMIT                                                                   \
46     )                                                                           \
47 /**/
48 
49 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXT(ACTOR, NAME_SEQ, GRAMMAR_SEQ)       \
50     BOOST_PHOENIX_DEFINE_EXPRESSION_BASE(                                       \
51         NAME_SEQ                                                                \
52       , GRAMMAR_SEQ                                                             \
53       , BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_EXT                          \
54       , BOOST_PHOENIX_DEFINE_EXPRESSION_RULE_DEFAULT                            \
55       , BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_DEFAULT                  \
56       , BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_DEFAULT                 \
57       , ACTOR                                                                   \
58     )                                                                           \
59 /**/
60 
61 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG(ACTOR, NAME, GRAMMAR, LIMIT) \
62     BOOST_PHOENIX_DEFINE_EXPRESSION_BASE(                                       \
63         NAME_SEQ                                                                \
64       , GRAMMAR_SEQ                                                             \
65       , BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_VARARG_EXT                   \
66       , BOOST_PHOENIX_DEFINE_EXPRESSION_RULE_VARARG                             \
67       , BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_VARARG                   \
68       , BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_VARARG                  \
69       , ACTOR                                                                   \
70     )                                                                           \
71 /**/
72 
73 #define BOOST_PHOENIX_DEFINE_EXPRESSION_NAMESPACE(R, D, E)                      \
74 namespace E {                                                                   \
75 /**/
76 
77 #define BOOST_PHOENIX_DEFINE_EXPRESSION_NAMESPACE_END(R, D, E)                  \
78 }                                                                               \
79 /**/
80 
81 #define BOOST_PHOENIX_DEFINE_EXPRESSION_NS(R, D, E)                             \
82 E ::                                                                            \
83 /**/
84 
85 #define BOOST_PHOENIX_DEFINE_EXPRESSION_BASE(NAME_SEQ, GRAMMAR_SEQ, EXPRESSION, RULE, RESULT_OF_MAKE, MAKE_EXPRESSION, DATA) \
86 BOOST_PP_SEQ_FOR_EACH(                                                          \
87     BOOST_PHOENIX_DEFINE_EXPRESSION_NAMESPACE                                   \
88   , _                                                                           \
89   , BOOST_PP_SEQ_POP_BACK(NAME_SEQ)                                             \
90 )                                                                               \
91     namespace tag                                                               \
92     {                                                                           \
93         struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ)) {};            \
94         template <typename Ostream>                                             \
95         inline Ostream &operator<<(                                             \
96             Ostream & os                                                        \
97           , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ)))                  \
98         {                                                                       \
99             os << BOOST_PP_STRINGIZE(                                           \
100                 BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))               \
101             );                                                                  \
102             return os;                                                          \
103         }                                                                       \
104     }                                                                           \
105     namespace expression                                                        \
106     {                                                                           \
107         EXPRESSION(NAME_SEQ, GRAMMAR_SEQ, DATA)                                 \
108     }                                                                           \
109     namespace rule                                                              \
110     {                                                                           \
111         RULE(NAME_SEQ, GRAMMAR_SEQ, DATA)                                       \
112     }                                                                           \
113     namespace functional                                                        \
114     {                                                                           \
115         typedef                                                                 \
116             boost::proto::functional::make_expr<                                \
117                     tag:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))     \
118             >                                                                   \
119             BOOST_PP_CAT(                                                       \
120                 make_                                                           \
121               , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))               \
122             );                                                                  \
123     }                                                                           \
124     namespace result_of                                                         \
125     {                                                                           \
126         RESULT_OF_MAKE(NAME_SEQ, GRAMMAR_SEQ, DATA)                             \
127     }                                                                           \
128     MAKE_EXPRESSION(NAME_SEQ, GRAMMAR_SEQ, DATA)                                \
129                                                                                 \
130 BOOST_PP_SEQ_FOR_EACH(                                                          \
131     BOOST_PHOENIX_DEFINE_EXPRESSION_NAMESPACE_END                               \
132   , _                                                                           \
133   , BOOST_PP_SEQ_POP_BACK(NAME_SEQ)                                             \
134 )                                                                               \
135 namespace boost { namespace phoenix                                             \
136 {                                                                               \
137     template <typename Dummy>                                                   \
138     struct meta_grammar::case_<                                                 \
139         :: BOOST_PP_SEQ_FOR_EACH(                                               \
140             BOOST_PHOENIX_DEFINE_EXPRESSION_NS                                  \
141           , _                                                                   \
142           , BOOST_PP_SEQ_POP_BACK(NAME_SEQ)                                     \
143         ) tag:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))               \
144       , Dummy                                                                   \
145     >                                                                           \
146         : enable_rule<                                                          \
147             :: BOOST_PP_SEQ_FOR_EACH(                                           \
148                 BOOST_PHOENIX_DEFINE_EXPRESSION_NS                              \
149               , _                                                               \
150               , BOOST_PP_SEQ_POP_BACK(NAME_SEQ)                                 \
151             ) rule:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))          \
152          , Dummy                                                                \
153         >                                                                       \
154     {};                                                                         \
155 } }                                                                             \
156 /**/
157 
158 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_DEFAULT(NAME_SEQ, GRAMMAR_SEQ, D) \
159         template <BOOST_PHOENIX_typename_A(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))>     \
160         struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                \
161             : boost::phoenix::expr<                                             \
162                 :: BOOST_PP_SEQ_FOR_EACH(                                       \
163                     BOOST_PHOENIX_DEFINE_EXPRESSION_NS                          \
164                   , _                                                           \
165                   , BOOST_PP_SEQ_POP_BACK(NAME_SEQ)                             \
166                 ) tag:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))       \
167               , BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ), A)>        \
168         {};                                                                     \
169 /**/
170 
171 #define BOOST_PHOENIX_DEFINE_EXPRESSION_RULE_DEFAULT(NAME_SEQ, GRAMMAR_SEQ, D)  \
172     struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                    \
173         : expression:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))        \
174             <BOOST_PP_SEQ_ENUM(GRAMMAR_SEQ)>                                    \
175     {};                                                                         \
176 /**/
177 
178 #define BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_DEFAULT(NAME_SEQ, GRAMMAR_SEQ, D) \
179     template <BOOST_PHOENIX_typename_A(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))>         \
180     struct BOOST_PP_CAT(make_, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))) \
181         : boost::result_of<                                                     \
182             functional::                                                        \
183                 BOOST_PP_CAT(                                                   \
184                     make_                                                       \
185                   , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))           \
186                 )(BOOST_PHOENIX_A(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ)))              \
187         >                                                                       \
188     {};                                                                         \
189 /**/
190 
191 #define BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_DEFAULT(NAME_SEQ, GRAMMAR_SEQ, D) \
192     template <BOOST_PHOENIX_typename_A(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))>         \
193     inline                                                                      \
194     typename                                                                    \
195         result_of::BOOST_PP_CAT(                                                \
196             make_                                                               \
197           , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                   \
198         )<                                                                      \
199             BOOST_PHOENIX_A(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))                     \
200         >::type const                                                           \
201     BOOST_PP_CAT(                                                               \
202         make_                                                                   \
203       , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                       \
204     )(                                                                          \
205         BOOST_PHOENIX_A_const_ref_a(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))             \
206     )                                                                           \
207     {                                                                           \
208         return                                                                  \
209             functional::BOOST_PP_CAT(                                           \
210                 make_                                                           \
211               , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))               \
212             )()(                                                                \
213               BOOST_PHOENIX_a(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))                   \
214             );                                                                  \
215     }                                                                           \
216 /**/
217 
218 #ifndef BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
219 
220 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_VARARG(NAME_SEQ, _G, _L)     \
221     template <typename A0, typename... A>                                       \
222     struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                    \
223         : boost::phoenix::expr<                                                 \
224             tag:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))             \
225           , A0, A...                                                            \
226         >                                                                       \
227     {};                                                                         \
228 /**/
229 
230 #else // BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
231 
232 #define BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG_R(_, N, NAME)                    \
233     template <                                                                  \
234         BOOST_PHOENIX_typename_A(                                               \
235             BOOST_PP_ADD(                                                       \
236                 N                                                               \
237               , BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2, 1, NAME))              \
238             )                                                                   \
239         )                                                                       \
240     >                                                                           \
241     struct BOOST_PP_TUPLE_ELEM(2, 0, NAME)<                                     \
242         BOOST_PHOENIX_A(                                                        \
243             BOOST_PP_ADD(N, BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2, 1, NAME))) \
244         )                                                                       \
245     >                                                                           \
246         : boost::phoenix::expr<                                                 \
247             tag:: BOOST_PP_TUPLE_ELEM(2, 0, NAME)                               \
248           , BOOST_PHOENIX_A(                                                    \
249                 BOOST_PP_ADD(                                                   \
250                     N                                                           \
251                   , BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2, 1, NAME))          \
252                 )                                                               \
253             )                                                                   \
254         >                                                                       \
255     {};                                                                         \
256 /**/
257 
258 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_VARARG(NAME_SEQ, GRAMMAR_SEQ, LIMIT) \
259         template <                                                              \
260             BOOST_PHOENIX_typename_A_void(                                      \
261                 BOOST_PP_ADD(                                                   \
262                     LIMIT, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ)))        \
263             )                                                                   \
264           , typename Dummy = void                                               \
265         >                                                                       \
266         struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ));               \
267                                                                                 \
268         BOOST_PP_REPEAT_FROM_TO(                                                \
269             1                                                                   \
270           , BOOST_PP_ADD(LIMIT, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ)))   \
271           , BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG_R                            \
272           , (                                                                   \
273                 BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))               \
274               , BOOST_PP_SEQ_POP_BACK(GRAMMAR_SEQ)                              \
275             )                                                                   \
276         )                                                                       \
277 /**/
278 #endif // BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
279 
280 #define BOOST_PHOENIX_DEFINE_EXPRESSION_RULE_VARARG(NAME_SEQ, GRAMMAR_SEQ, LIMIT) \
281         struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                \
282             : expression:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ)) <  \
283                 BOOST_PP_IF(                                                    \
284                     BOOST_PP_EQUAL(1, BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))           \
285                   , BOOST_PP_EMPTY                                              \
286                   , BOOST_PP_IDENTITY(                                          \
287                       BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_POP_BACK(GRAMMAR_SEQ))     \
288                     )                                                           \
289                 )()                                                             \
290                 BOOST_PP_COMMA_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))) \
291                 boost::proto::vararg<                                           \
292                     BOOST_PP_SEQ_ELEM(                                          \
293                         BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))            \
294                       , GRAMMAR_SEQ                                             \
295                     )                                                           \
296                 >                                                               \
297             >                                                                   \
298         {};                                                                     \
299 /**/
300 
301 #ifndef BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
302 
303 #define BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_VARARG(NAME_SEQ, _G, _L) \
304     template <typename A0, typename... A>                                       \
305     struct BOOST_PP_CAT(make_, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))) \
306         : boost::result_of<                                                     \
307             functional:: BOOST_PP_CAT(make_, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ)))( \
308                 A0, A...                                                        \
309             )                                                                   \
310         >                                                                       \
311     {};                                                                         \
312 /**/
313 
314 #else // BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
315 
316 #define BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_VARARG_R(Z, N, NAME)     \
317     template <BOOST_PHOENIX_typename_A(N)>                                      \
318     struct BOOST_PP_CAT(make_, NAME) <BOOST_PHOENIX_A(N)>                       \
319         : boost::result_of<                                                     \
320             functional:: BOOST_PP_CAT(make_, NAME)(                             \
321                 BOOST_PHOENIX_A(N)                                              \
322             )                                                                   \
323         >                                                                       \
324     {};                                                                         \
325 /**/
326 
327 #define BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_VARARG(NAME_SEQ, GRAMMAR_SEQ, LIMIT) \
328     template <BOOST_PHOENIX_typename_A_void(LIMIT), typename Dummy = void>      \
329     struct BOOST_PP_CAT(                                                        \
330         make_                                                                   \
331       , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                       \
332     );                                                                          \
333     BOOST_PP_REPEAT_FROM_TO(                                                    \
334         1                                                                       \
335       , LIMIT                                                                   \
336       , BOOST_PHOENIX_DEFINE_EXPRESSION_RESULT_OF_MAKE_VARARG_R                 \
337       , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                       \
338     )                                                                           \
339 /**/
340 #endif // BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
341 
342 #ifndef BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
343 
344 #define BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_VARARG(NAME_SEQ, GRAMMAR_SEQ, LIMIT) \
345     template <typename A0, typename... A>                                       \
346     inline                                                                      \
347     typename                                                                    \
348         result_of:: BOOST_PP_CAT(make_, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ)))< \
349             A0, A...                                                            \
350         >::type                                                                 \
351     BOOST_PP_CAT(make_, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ)))(A0 const& a0, A const&... a) \
352     {                                                                           \
353         return functional::BOOST_PP_CAT(make_, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ)))()(a0, a...); \
354     }                                                                           \
355 /**/
356 
357 #else // BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
358 
359 #define BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_VARARG_R(Z, N, NAME)    \
360     template <BOOST_PHOENIX_typename_A(N)>                                      \
361     inline                                                                      \
362     typename                                                                    \
363         result_of:: BOOST_PP_CAT(make_, NAME)<                                  \
364             BOOST_PHOENIX_A(N)                                                  \
365         >::type                                                                 \
366     BOOST_PP_CAT(make_, NAME)(BOOST_PHOENIX_A_const_ref_a(N))                   \
367     {                                                                           \
368         return functional::BOOST_PP_CAT(make_, NAME)()(BOOST_PHOENIX_a(N));     \
369     }                                                                           \
370 /**/
371 
372 #define BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_VARARG(NAME_SEQ, GRAMMAR_SEQ, LIMIT) \
373     BOOST_PP_REPEAT_FROM_TO(                                                    \
374         1                                                                       \
375       , LIMIT                                                                   \
376       , BOOST_PHOENIX_DEFINE_EXPRESSION_MAKE_EXPRESSION_VARARG_R                \
377       , BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                       \
378     )                                                                           \
379 /**/
380 #endif // BOOST_PHOENIX_NO_VARIADIC_EXPRESSION
381 
382 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXPRESSION_EXT(NAME_SEQ, GRAMMAR_SEQ, ACTOR) \
383         template <BOOST_PHOENIX_typename_A(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))>     \
384         struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))                \
385             : ::boost::phoenix::expr_ext<                                       \
386                 ACTOR                                                           \
387               , tag:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(NAME_SEQ))         \
388               , BOOST_PHOENIX_A(BOOST_PP_SEQ_SIZE(GRAMMAR_SEQ))>                \
389         {};                                                                     \
390 /**/
391 
392 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG_R(_, N, NAME)                \
393     template <                                                                  \
394         BOOST_PHOENIX_typename_A(                                               \
395             BOOST_PP_ADD(                                                       \
396                 N                                                               \
397               , BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(3, 1, NAME))              \
398             )                                                                   \
399         )                                                                       \
400     >                                                                           \
401     struct BOOST_PP_TUPLE_ELEM(3, 0, NAME)<                                     \
402         BOOST_PHOENIX_A(                                                        \
403             BOOST_PP_ADD(N, BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(3, 1, NAME))) \
404         )                                                                       \
405     >                                                                           \
406         : expr_ext<                                                             \
407             BOOST_PP_TUPLE_ELEM(3, 2, NAME)                                     \
408           , tag:: BOOST_PP_TUPLE_ELEM(3, 0, NAME)                               \
409           , BOOST_PHOENIX_A(                                                    \
410                 BOOST_PP_ADD(                                                   \
411                     N                                                           \
412                   , BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(3, 1, NAME))          \
413                 )                                                               \
414             )                                                                   \
415         >                                                                       \
416     {};                                                                         \
417 /**/
418 
419 #define BOOST_PHOENIX_DEFINE_EXPRESSION_EXRPESSION_VARARG_EXT(N, G, D)          \
420         template <                                                              \
421             BOOST_PHOENIX_typename_A_void(                                      \
422                 BOOST_PP_ADD(LIMIT, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(G)))         \
423             )                                                                   \
424           , typename Dummy = void                                               \
425         >                                                                       \
426         struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(N));                      \
427                                                                                 \
428         BOOST_PP_REPEAT_FROM_TO(                                                \
429             1                                                                   \
430           , BOOST_PP_ADD(LIMIT, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(G)))             \
431           , BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG_R                        \
432           , (                                                                   \
433               BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(N))                        \
434             , BOOST_PP_SEQ_POP_BACK(G)                                          \
435             , ACTOR                                                             \
436           )                                                                     \
437         )                                                                       \
438 /**/
439 
440 #define BOOST_PHOENIX_DEFINE_EXPRESSION_RULE_VARARG_EXT(N, GRAMMAR, D)          \
441         struct BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(N))                       \
442             : expression:: BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REVERSE(N)) <         \
443                 BOOST_PP_IF(                                                    \
444                     BOOST_PP_EQUAL(1, BOOST_PP_SEQ_SIZE(GRAMMAR))               \
445                   , BOOST_PP_EMPTY                                              \
446                   , BOOST_PP_IDENTITY(                                          \
447                       BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_POP_BACK(GRAMMAR))         \
448                     )                                                           \
449                 )()                                                             \
450                 BOOST_PP_COMMA_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(GRAMMAR)))     \
451                 proto::vararg<                                                  \
452                     BOOST_PP_SEQ_ELEM(                                          \
453                         BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(GRAMMAR))                \
454                       , GRAMMAR                                                 \
455                     )                                                           \
456                 >                                                               \
457             >                                                                   \
458         {};                                                                     \
459 
460 
461 #endif
462