]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2001-2011 Hartmut Kaiser | |
4 | Copyright (c) 2010 Bryce Lelbach | |
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_CHAR_APRIL_16_2006_1051AM) | |
10 | #define BOOST_SPIRIT_CHAR_APRIL_16_2006_1051AM | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | #include <boost/spirit/home/support/common_terminals.hpp> | |
17 | #include <boost/spirit/home/support/string_traits.hpp> | |
18 | #include <boost/spirit/home/support/info.hpp> | |
19 | #include <boost/spirit/home/support/detail/get_encoding.hpp> | |
20 | #include <boost/spirit/home/support/char_set/basic_chset.hpp> | |
21 | #include <boost/spirit/home/qi/char/char_parser.hpp> | |
22 | #include <boost/spirit/home/qi/char/char_class.hpp> | |
23 | #include <boost/spirit/home/qi/meta_compiler.hpp> | |
24 | #include <boost/spirit/home/qi/auxiliary/lazy.hpp> | |
25 | #include <boost/spirit/home/qi/detail/enable_lit.hpp> | |
26 | #include <boost/fusion/include/at.hpp> | |
27 | #include <boost/mpl/if.hpp> | |
28 | #include <boost/mpl/assert.hpp> | |
29 | #include <boost/mpl/identity.hpp> | |
30 | #include <boost/utility/enable_if.hpp> | |
31 | #include <boost/type_traits/remove_const.hpp> | |
32 | #include <string> | |
33 | ||
34 | #if defined(_MSC_VER) | |
35 | #pragma once | |
36 | #endif | |
37 | ||
38 | namespace boost { namespace spirit | |
39 | { | |
40 | /////////////////////////////////////////////////////////////////////////// | |
41 | // Enablers | |
42 | /////////////////////////////////////////////////////////////////////////// | |
43 | template <typename CharEncoding> | |
44 | struct use_terminal<qi::domain | |
45 | , terminal< | |
46 | tag::char_code<tag::char_, CharEncoding> // enables char_ | |
47 | > | |
48 | > : mpl::true_ {}; | |
49 | ||
50 | template <typename CharEncoding, typename A0> | |
51 | struct use_terminal<qi::domain | |
52 | , terminal_ex< | |
53 | tag::char_code<tag::char_, CharEncoding> // enables char_('x'), char_("x") | |
54 | , fusion::vector1<A0> // and char_("a-z0-9") | |
55 | > | |
56 | > : mpl::true_ {}; | |
57 | ||
58 | template <typename CharEncoding, typename A0, typename A1> | |
59 | struct use_terminal<qi::domain | |
60 | , terminal_ex< | |
61 | tag::char_code<tag::char_, CharEncoding> // enables char_('a','z') | |
62 | , fusion::vector2<A0, A1> | |
63 | > | |
64 | > : mpl::true_ {}; | |
65 | ||
66 | template <typename CharEncoding> // enables *lazy* char_('x'), char_("x") | |
67 | struct use_lazy_terminal< // and char_("a-z0-9") | |
68 | qi::domain | |
69 | , tag::char_code<tag::char_, CharEncoding> | |
70 | , 1 // arity | |
71 | > : mpl::true_ {}; | |
72 | ||
73 | template <typename CharEncoding> // enables *lazy* char_('a','z') | |
74 | struct use_lazy_terminal< | |
75 | qi::domain | |
76 | , tag::char_code<tag::char_, CharEncoding> | |
77 | , 2 // arity | |
78 | > : mpl::true_ {}; | |
79 | ||
80 | template <> | |
81 | struct use_terminal<qi::domain, char> // enables 'x' | |
82 | : mpl::true_ {}; | |
83 | ||
84 | template <> | |
85 | struct use_terminal<qi::domain, char[2]> // enables "x" | |
86 | : mpl::true_ {}; | |
87 | ||
88 | template <> | |
89 | struct use_terminal<qi::domain, wchar_t> // enables wchar_t | |
90 | : mpl::true_ {}; | |
91 | ||
92 | template <> | |
93 | struct use_terminal<qi::domain, wchar_t[2]> // enables L"x" | |
94 | : mpl::true_ {}; | |
95 | ||
96 | // enables lit(...) | |
97 | template <typename A0> | |
98 | struct use_terminal<qi::domain | |
99 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
100 | , typename enable_if<traits::is_char<A0> >::type> | |
101 | : mpl::true_ {}; | |
102 | }} | |
103 | ||
104 | namespace boost { namespace spirit { namespace qi | |
105 | { | |
106 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
107 | using spirit::lit; // lit('x') is equivalent to 'x' | |
108 | #endif | |
109 | using spirit::lit_type; | |
110 | ||
111 | /////////////////////////////////////////////////////////////////////////// | |
112 | // Parser for a single character | |
113 | /////////////////////////////////////////////////////////////////////////// | |
114 | template <typename CharEncoding, bool no_attribute, bool no_case = false> | |
115 | struct literal_char | |
116 | : char_parser< | |
117 | literal_char<CharEncoding, no_attribute, false> | |
118 | , typename CharEncoding::char_type | |
119 | , typename mpl::if_c<no_attribute, unused_type | |
120 | , typename CharEncoding::char_type>::type> | |
121 | { | |
122 | typedef typename CharEncoding::char_type char_type; | |
123 | typedef CharEncoding char_encoding; | |
124 | ||
125 | template <typename Char> | |
126 | literal_char(Char ch_) | |
127 | : ch(static_cast<char_type>(ch_)) {} | |
128 | ||
129 | template <typename Context, typename Iterator> | |
130 | struct attribute | |
131 | { | |
132 | typedef typename mpl::if_c< | |
133 | no_attribute, unused_type, char_type>::type | |
134 | type; | |
135 | }; | |
136 | ||
137 | template <typename CharParam, typename Context> | |
138 | bool test(CharParam ch_, Context&) const | |
139 | { | |
140 | return traits::ischar<CharParam, char_encoding>::call(ch_) && | |
141 | ch == char_type(ch_); | |
142 | } | |
143 | ||
144 | template <typename Context> | |
145 | info what(Context& /*context*/) const | |
146 | { | |
147 | return info("literal-char", char_encoding::toucs4(ch)); | |
148 | } | |
149 | ||
150 | char_type ch; | |
151 | }; | |
152 | ||
153 | template <typename CharEncoding, bool no_attribute> | |
154 | struct literal_char<CharEncoding, no_attribute, true> // case insensitive | |
155 | : char_parser< | |
156 | literal_char<CharEncoding, no_attribute, true> | |
157 | , typename mpl::if_c<no_attribute, unused_type | |
158 | , typename CharEncoding::char_type>::type> | |
159 | { | |
160 | typedef typename CharEncoding::char_type char_type; | |
161 | typedef CharEncoding char_encoding; | |
162 | ||
163 | literal_char(char_type ch) | |
164 | : lo(static_cast<char_type>(char_encoding::tolower(ch))) | |
165 | , hi(static_cast<char_type>(char_encoding::toupper(ch))) {} | |
166 | ||
167 | template <typename Context, typename Iterator> | |
168 | struct attribute | |
169 | { | |
170 | typedef typename mpl::if_c< | |
171 | no_attribute, unused_type, char_type>::type | |
172 | type; | |
173 | }; | |
174 | ||
175 | template <typename CharParam, typename Context> | |
176 | bool test(CharParam ch_, Context&) const | |
177 | { | |
178 | if (!traits::ischar<CharParam, char_encoding>::call(ch_)) | |
179 | return false; | |
180 | ||
181 | char_type ch = char_type(ch_); // optimize for token based parsing | |
182 | return this->lo == ch || this->hi == ch; | |
183 | } | |
184 | ||
185 | template <typename Context> | |
186 | info what(Context& /*context*/) const | |
187 | { | |
188 | return info("no-case-literal-char", char_encoding::toucs4(lo)); | |
189 | } | |
190 | ||
191 | char_type lo, hi; | |
192 | }; | |
193 | ||
194 | /////////////////////////////////////////////////////////////////////////// | |
195 | // Parser for a character range | |
196 | /////////////////////////////////////////////////////////////////////////// | |
197 | template <typename CharEncoding, bool no_case = false> | |
198 | struct char_range | |
199 | : char_parser<char_range<CharEncoding, false>, typename CharEncoding::char_type> | |
200 | { | |
201 | typedef typename CharEncoding::char_type char_type; | |
202 | typedef CharEncoding char_encoding; | |
203 | ||
204 | char_range(char_type from_, char_type to_) | |
205 | : from(from_), to(to_) {} | |
206 | ||
207 | template <typename CharParam, typename Context> | |
208 | bool test(CharParam ch_, Context&) const | |
209 | { | |
210 | if (!traits::ischar<CharParam, char_encoding>::call(ch_)) | |
211 | return false; | |
212 | ||
213 | char_type ch = char_type(ch_); // optimize for token based parsing | |
214 | return !(ch < from) && !(to < ch); | |
215 | } | |
216 | ||
217 | template <typename Context> | |
218 | info what(Context& /*context*/) const | |
219 | { | |
220 | info result("char-range", char_encoding::toucs4(from)); | |
221 | boost::get<std::string>(result.value) += '-'; | |
222 | boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to)); | |
223 | return result; | |
224 | } | |
225 | ||
226 | char_type from, to; | |
227 | }; | |
228 | ||
229 | template <typename CharEncoding> | |
230 | struct char_range<CharEncoding, true> // case insensitive | |
231 | : char_parser<char_range<CharEncoding, true>, typename CharEncoding::char_type> | |
232 | { | |
233 | typedef typename CharEncoding::char_type char_type; | |
234 | typedef CharEncoding char_encoding; | |
235 | ||
236 | char_range(char_type from, char_type to) | |
237 | : from_lo(static_cast<char_type>(char_encoding::tolower(from))) | |
238 | , to_lo(static_cast<char_type>(char_encoding::tolower(to))) | |
239 | , from_hi(static_cast<char_type>(char_encoding::toupper(from))) | |
240 | , to_hi(static_cast<char_type>(char_encoding::toupper(to))) | |
241 | {} | |
242 | ||
243 | template <typename CharParam, typename Context> | |
244 | bool test(CharParam ch_, Context&) const | |
245 | { | |
246 | if (!traits::ischar<CharParam, char_encoding>::call(ch_)) | |
247 | return false; | |
248 | ||
249 | char_type ch = char_type(ch_); // optimize for token based parsing | |
250 | return (!(ch < from_lo) && !(to_lo < ch)) | |
251 | || (!(ch < from_hi) && !(to_hi < ch)) | |
252 | ; | |
253 | } | |
254 | ||
255 | template <typename Context> | |
256 | info what(Context& /*context*/) const | |
257 | { | |
258 | info result("no-case-char-range", char_encoding::toucs4(from_lo)); | |
259 | boost::get<std::string>(result.value) += '-'; | |
260 | boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to_lo)); | |
261 | return result; | |
262 | } | |
263 | ||
264 | char_type from_lo, to_lo, from_hi, to_hi; | |
265 | }; | |
266 | ||
267 | /////////////////////////////////////////////////////////////////////////// | |
268 | // Parser for a character set | |
269 | /////////////////////////////////////////////////////////////////////////// | |
270 | template <typename CharEncoding, bool no_attribute, bool no_case = false> | |
271 | struct char_set | |
272 | : char_parser<char_set<CharEncoding, no_attribute, false> | |
273 | , typename mpl::if_c<no_attribute, unused_type | |
274 | , typename CharEncoding::char_type>::type> | |
275 | { | |
276 | typedef typename CharEncoding::char_type char_type; | |
277 | typedef CharEncoding char_encoding; | |
278 | ||
279 | template <typename String> | |
280 | char_set(String const& str) | |
281 | { | |
282 | using spirit::detail::cast_char; | |
283 | ||
284 | typedef typename | |
285 | remove_const< | |
286 | typename traits::char_type_of<String>::type | |
287 | >::type | |
288 | in_type; | |
289 | ||
290 | BOOST_SPIRIT_ASSERT_MSG(( | |
291 | (sizeof(char_type) >= sizeof(in_type)) | |
292 | ), cannot_convert_string, (String)); | |
293 | ||
294 | in_type const* definition = | |
295 | (in_type const*)traits::get_c_string(str); | |
296 | in_type ch = *definition++; | |
297 | while (ch) | |
298 | { | |
299 | in_type next = *definition++; | |
300 | if (next == '-') | |
301 | { | |
302 | next = *definition++; | |
303 | if (next == 0) | |
304 | { | |
305 | chset.set(cast_char<char_type>(ch)); | |
306 | chset.set('-'); | |
307 | break; | |
308 | } | |
309 | chset.set( | |
310 | cast_char<char_type>(ch), | |
311 | cast_char<char_type>(next) | |
312 | ); | |
313 | } | |
314 | else | |
315 | { | |
316 | chset.set(cast_char<char_type>(ch)); | |
317 | } | |
318 | ch = next; | |
319 | } | |
320 | } | |
321 | ||
322 | template <typename CharParam, typename Context> | |
323 | bool test(CharParam ch, Context&) const | |
324 | { | |
325 | return traits::ischar<CharParam, char_encoding>::call(ch) && | |
326 | chset.test(char_type(ch)); | |
327 | } | |
328 | ||
329 | template <typename Context> | |
330 | info what(Context& /*context*/) const | |
331 | { | |
332 | return info("char-set"); | |
333 | } | |
334 | ||
335 | support::detail::basic_chset<char_type> chset; | |
336 | }; | |
337 | ||
338 | template <typename CharEncoding, bool no_attribute> | |
339 | struct char_set<CharEncoding, no_attribute, true> // case insensitive | |
340 | : char_parser<char_set<CharEncoding, no_attribute, true> | |
341 | , typename mpl::if_c<no_attribute, unused_type | |
342 | , typename CharEncoding::char_type>::type> | |
343 | { | |
344 | typedef typename CharEncoding::char_type char_type; | |
345 | typedef CharEncoding char_encoding; | |
346 | ||
347 | template <typename String> | |
348 | char_set(String const& str) | |
349 | { | |
350 | typedef typename traits::char_type_of<String>::type in_type; | |
351 | ||
352 | BOOST_SPIRIT_ASSERT_MSG(( | |
353 | (sizeof(char_type) == sizeof(in_type)) | |
354 | ), cannot_convert_string, (String)); | |
355 | ||
356 | char_type const* definition = | |
357 | (char_type const*)traits::get_c_string(str); | |
358 | char_type ch = *definition++; | |
359 | while (ch) | |
360 | { | |
361 | char_type next = *definition++; | |
362 | if (next == '-') | |
363 | { | |
364 | next = *definition++; | |
365 | if (next == 0) | |
366 | { | |
367 | chset.set(static_cast<char_type>(CharEncoding::tolower(ch))); | |
368 | chset.set(static_cast<char_type>(CharEncoding::toupper(ch))); | |
369 | chset.set('-'); | |
370 | break; | |
371 | } | |
372 | chset.set(static_cast<char_type>(CharEncoding::tolower(ch)) | |
373 | , static_cast<char_type>(CharEncoding::tolower(next))); | |
374 | chset.set(static_cast<char_type>(CharEncoding::toupper(ch)) | |
375 | , static_cast<char_type>(CharEncoding::toupper(next))); | |
376 | } | |
377 | else | |
378 | { | |
379 | chset.set(static_cast<char_type>(CharEncoding::tolower(ch))); | |
380 | chset.set(static_cast<char_type>(CharEncoding::toupper(ch))); | |
381 | } | |
382 | ch = next; | |
383 | } | |
384 | } | |
385 | ||
386 | template <typename CharParam, typename Context> | |
387 | bool test(CharParam ch, Context&) const | |
388 | { | |
389 | return traits::ischar<CharParam, char_encoding>::call(ch) && | |
390 | chset.test(char_type(ch)); | |
391 | } | |
392 | ||
393 | template <typename Context> | |
394 | info what(Context& /*context*/) const | |
395 | { | |
396 | return info("no-case-char-set"); | |
397 | } | |
398 | ||
399 | support::detail::basic_chset<char_type> chset; | |
400 | }; | |
401 | ||
402 | /////////////////////////////////////////////////////////////////////////// | |
403 | // Parser generators: make_xxx function (objects) | |
404 | /////////////////////////////////////////////////////////////////////////// | |
405 | namespace detail | |
406 | { | |
407 | template <typename Modifiers, typename Encoding> | |
408 | struct basic_literal | |
409 | { | |
410 | static bool const no_case = | |
411 | has_modifier< | |
412 | Modifiers | |
413 | , tag::char_code_base<tag::no_case> | |
414 | >::value; | |
415 | ||
416 | static bool const no_attr = | |
417 | !has_modifier< | |
418 | Modifiers | |
419 | , tag::lazy_eval | |
420 | >::value; | |
421 | ||
422 | typedef literal_char< | |
423 | typename spirit::detail::get_encoding_with_case< | |
424 | Modifiers, Encoding, no_case>::type | |
425 | , no_attr | |
426 | , no_case> | |
427 | result_type; | |
428 | ||
429 | template <typename Char> | |
430 | result_type operator()(Char ch, unused_type) const | |
431 | { | |
432 | return result_type(ch); | |
433 | } | |
434 | ||
435 | template <typename Char> | |
436 | result_type operator()(Char const* str, unused_type) const | |
437 | { | |
438 | return result_type(str[0]); | |
439 | } | |
440 | }; | |
441 | } | |
442 | ||
443 | template <typename Modifiers> | |
444 | struct make_primitive<char, Modifiers> | |
445 | : detail::basic_literal<Modifiers, char_encoding::standard> {}; | |
446 | ||
447 | template <typename Modifiers> | |
448 | struct make_primitive<char const(&)[2], Modifiers> | |
449 | : detail::basic_literal<Modifiers, char_encoding::standard> {}; | |
450 | ||
451 | template <typename Modifiers> | |
452 | struct make_primitive<wchar_t, Modifiers> | |
453 | : detail::basic_literal<Modifiers, char_encoding::standard_wide> {}; | |
454 | ||
455 | template <typename Modifiers> | |
456 | struct make_primitive<wchar_t const(&)[2], Modifiers> | |
457 | : detail::basic_literal<Modifiers, char_encoding::standard_wide> {}; | |
458 | ||
459 | template <typename CharEncoding, typename Modifiers> | |
460 | struct make_primitive< | |
461 | terminal<tag::char_code<tag::char_, CharEncoding> >, Modifiers> | |
462 | { | |
463 | typedef typename | |
464 | spirit::detail::get_encoding<Modifiers, CharEncoding>::type | |
465 | char_encoding; | |
466 | ||
467 | typedef tag::char_code<tag::char_, char_encoding> tag; | |
468 | typedef char_class<tag> result_type; | |
469 | result_type operator()(unused_type, unused_type) const | |
470 | { | |
471 | return result_type(); | |
472 | } | |
473 | }; | |
474 | ||
475 | /////////////////////////////////////////////////////////////////////////// | |
476 | // char_('x') | |
477 | template <typename CharEncoding, typename Modifiers, typename A0> | |
478 | struct make_primitive< | |
479 | terminal_ex< | |
480 | tag::char_code<tag::char_, CharEncoding> | |
481 | , fusion::vector1<A0> > | |
482 | , Modifiers> | |
483 | { | |
484 | static bool const no_case = | |
485 | has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value; | |
486 | ||
487 | typedef typename | |
488 | spirit::detail::get_encoding<Modifiers, CharEncoding>::type | |
489 | char_encoding; | |
490 | ||
491 | typedef typename | |
492 | mpl::if_< | |
493 | traits::is_string<A0> | |
494 | , char_set<char_encoding, false, no_case> | |
495 | , literal_char<char_encoding, false, no_case> | |
496 | >::type | |
497 | result_type; | |
498 | ||
499 | template <typename Terminal> | |
500 | result_type operator()(Terminal const& term, unused_type) const | |
501 | { | |
502 | return result_type(fusion::at_c<0>(term.args)); | |
503 | } | |
504 | }; | |
505 | ||
506 | // lit('x') | |
507 | template <typename Modifiers, typename A0> | |
508 | struct make_primitive< | |
509 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
510 | , Modifiers | |
511 | , typename enable_if<traits::is_char<A0> >::type> | |
512 | { | |
513 | static bool const no_case = | |
514 | has_modifier< | |
515 | Modifiers | |
516 | , tag::char_code_base<tag::no_case> | |
517 | >::value; | |
518 | ||
519 | typedef typename traits::char_encoding_from_char< | |
520 | typename traits::char_type_of<A0>::type>::type encoding; | |
521 | ||
522 | typedef literal_char< | |
523 | typename spirit::detail::get_encoding_with_case< | |
524 | Modifiers, encoding, no_case>::type | |
525 | , true, no_case> | |
526 | result_type; | |
527 | ||
528 | template <typename Terminal> | |
529 | result_type operator()(Terminal const& term, unused_type) const | |
530 | { | |
531 | return result_type(fusion::at_c<0>(term.args)); | |
532 | } | |
533 | }; | |
534 | ||
535 | /////////////////////////////////////////////////////////////////////////// | |
536 | template <typename CharEncoding, typename Modifiers, typename Char> | |
537 | struct make_primitive< | |
538 | terminal_ex< | |
539 | tag::char_code<tag::char_, CharEncoding> | |
540 | , fusion::vector1<Char(&)[2]> // For single char strings | |
541 | > | |
542 | , Modifiers> | |
543 | { | |
544 | static bool const no_case = | |
545 | has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value; | |
546 | ||
547 | typedef typename | |
548 | spirit::detail::get_encoding<Modifiers, CharEncoding>::type | |
549 | char_encoding; | |
550 | ||
551 | typedef literal_char<char_encoding, false, no_case> result_type; | |
552 | ||
553 | template <typename Terminal> | |
554 | result_type operator()(Terminal const& term, unused_type) const | |
555 | { | |
556 | return result_type(fusion::at_c<0>(term.args)[0]); | |
557 | } | |
558 | }; | |
559 | ||
560 | template <typename CharEncoding, typename Modifiers, typename A0, typename A1> | |
561 | struct make_primitive< | |
562 | terminal_ex< | |
563 | tag::char_code<tag::char_, CharEncoding> | |
564 | , fusion::vector2<A0, A1> | |
565 | > | |
566 | , Modifiers> | |
567 | { | |
568 | static bool const no_case = | |
569 | has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value; | |
570 | ||
571 | typedef typename | |
572 | spirit::detail::get_encoding<Modifiers, CharEncoding>::type | |
573 | char_encoding; | |
574 | ||
575 | typedef char_range<char_encoding, no_case> result_type; | |
576 | ||
577 | template <typename Terminal> | |
578 | result_type operator()(Terminal const& term, unused_type) const | |
579 | { | |
580 | return result_type( | |
581 | fusion::at_c<0>(term.args) | |
582 | , fusion::at_c<1>(term.args) | |
583 | ); | |
584 | } | |
585 | }; | |
586 | ||
587 | template <typename CharEncoding, typename Modifiers, typename Char> | |
588 | struct make_primitive< | |
589 | terminal_ex< | |
590 | tag::char_code<tag::char_, CharEncoding> | |
591 | , fusion::vector2<Char(&)[2], Char(&)[2]> // For single char strings | |
592 | > | |
593 | , Modifiers> | |
594 | { | |
595 | static bool const no_case = | |
596 | has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value; | |
597 | ||
598 | typedef typename | |
599 | spirit::detail::get_encoding<Modifiers, CharEncoding>::type | |
600 | char_encoding; | |
601 | ||
602 | typedef char_range<char_encoding, no_case> result_type; | |
603 | ||
604 | template <typename Terminal> | |
605 | result_type operator()(Terminal const& term, unused_type) const | |
606 | { | |
607 | return result_type( | |
608 | fusion::at_c<0>(term.args)[0] | |
609 | , fusion::at_c<1>(term.args)[0] | |
610 | ); | |
611 | } | |
612 | }; | |
613 | }}} | |
614 | ||
615 | #endif |