1 /*=============================================================================
2     Copyright (c) 2001-2011 Hartmut Kaiser
3     http://spirit.sourceforge.net/
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #include <boost/config/warning_disable.hpp>
9 
10 //[reference_karma_includes
11 #include <boost/spirit/include/karma.hpp>
12 #include <boost/spirit/include/support_utree.hpp>
13 #include <boost/spirit/include/phoenix_core.hpp>
14 #include <boost/spirit/include/phoenix_operator.hpp>
15 #include <boost/fusion/include/std_pair.hpp>
16 #include <iostream>
17 #include <string>
18 //]
19 
20 //[reference_karma_includes_simple
21 #include <boost/spirit/include/karma.hpp>
22 #include <iostream>
23 #include <string>
24 //]
25 
26 //[reference_karma_output_iterator
27 typedef std::back_insert_iterator<std::string> output_iterator_type;
28 //]
29 
30 //[reference_karma_test
31 template <typename G>
test_generator(char const * expected,G const & g)32 void test_generator(char const* expected, G const& g)
33 {
34     std::string s;
35     std::back_insert_iterator<std::string> out(s);
36     if (boost::spirit::karma::generate(out, g) && s == expected)
37         std::cout << "ok" << std::endl;
38     else
39         std::cout << "fail" << std::endl;
40 }
41 //]
42 
43 //[reference_karma_test_attr
44 template <typename G, typename T>
test_generator_attr(char const * expected,G const & g,T const & attr)45 void test_generator_attr(char const* expected, G const& g, T const& attr)
46 {
47     std::string s;
48     std::back_insert_iterator<std::string> out(s);
49     if (boost::spirit::karma::generate(out, g, attr) && s == expected)
50         std::cout << "ok" << std::endl;
51     else
52         std::cout << "fail" << std::endl;
53 }
54 //]
55 
56 //[reference_karma_test_attr2
57 template <typename G, typename T1, typename T2>
test_generator_attr(char const * expected,G const & g,T1 const & attr1,T2 const & attr2)58 void test_generator_attr(char const* expected, G const& g, T1 const& attr1,
59     T2 const& attr2)
60 {
61     std::string s;
62     std::back_insert_iterator<std::string> out(s);
63     if (boost::spirit::karma::generate(out, g, attr1, attr2) && s == expected)
64         std::cout << "ok" << std::endl;
65     else
66         std::cout << "fail" << std::endl;
67 }
68 //]
69 
70 //[reference_karma_test_attr_delim
71 template <typename G, typename Delimiter, typename T>
test_generator_attr_delim(char const * expected,G const & g,Delimiter const & d,T const & attr)72 void test_generator_attr_delim(char const* expected, G const& g, Delimiter const& d, T const& attr)
73 {
74     std::string s;
75     std::back_insert_iterator<std::string> out(s);
76     if (boost::spirit::karma::generate_delimited(out, g, d, attr) && s == expected)
77         std::cout << "ok" << std::endl;
78     else
79         std::cout << "fail" << std::endl;
80 }
81 //]
82 
83 //[reference_karma_binary_test
84 template <typename G>
test_binary_generator(char const * expected,std::size_t size,G const & g)85 void test_binary_generator(char const* expected, std::size_t size, G const& g)
86 {
87     std::string s;
88     std::back_insert_iterator<std::string> out(s);
89     if (boost::spirit::karma::generate(out, g) && !std::memcmp(s.c_str(), expected, size))
90         std::cout << "ok" << std::endl;
91     else
92         std::cout << "fail" << std::endl;
93 }
94 //]
95 
96 //[reference_karma_binary_test_attr
97 template <typename G, typename T>
test_binary_generator_attr(char const * expected,std::size_t size,G const & g,T const & attr)98 void test_binary_generator_attr(char const* expected, std::size_t size, G const& g, T const& attr)
99 {
100     std::string s;
101     std::back_insert_iterator<std::string> out(s);
102     if (boost::spirit::karma::generate(out, g, attr) && !std::memcmp(s.c_str(), expected, size))
103         std::cout << "ok" << std::endl;
104     else
105         std::cout << "fail" << std::endl;
106 }
107 //]
108 
109 //[reference_karma_complex
110 // a simple complex number representation z = a + bi
111 struct complex
112 {
complexcomplex113     complex (double a, double b)
114       : a(a), b(b)
115     {}
116 
117     double a;
118     double b;
119 };
120 //]
121 
122 //[reference_karma_stream_complex
123 // define streaming operator for the type complex
124 std::ostream&
operator <<(std::ostream & os,complex const & z)125 operator<< (std::ostream& os, complex const& z)
126 {
127     os << "{" << z.a << "," << z.b << "}";
128     return os;
129 }
130 //]
131 
132 //[reference_karma_auto_complex
133 /*`The following construct is required to allow the `complex` data structure
134    to be utilized as a __fusion__ sequence. This is required as we will
135    emit output for this data structure with a __karma__ sequence:
136    `'{' << karma::double_ << ',' << karma::double_ << '}'`.
137 */
138 BOOST_FUSION_ADAPT_STRUCT(
139     complex,
140     (double, a)
141     (double, b)
142 )
143 
144 /*`We add a specialization for the create_generator customization point
145    defining a custom output format for the complex type. Generally, any
146    specialization for create_generator is expected to return the proto
147    expression to be used to generate output for the type the customization
148    point has been specialized for.
149  */
150 /*`We need to utilize `proto::deep_copy` as the expression contains literals
151    (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto
152    expression by reference only. The deep copy converts the proto tree to
153    hold this by value. The deep copy operation can be left out for simpler
154    proto expressions (not containing references to temporaries). Alternatively
155    you could use the `proto::make_expr` facility to build the required
156    proto expression.
157 */
158 namespace boost { namespace spirit { namespace traits
159 {
160     template <>
161     struct create_generator<complex>
162     {
163         typedef proto::result_of::deep_copy<
164             BOOST_TYPEOF('{' << karma::double_ << ',' << karma::double_ << '}')
165         >::type type;
166 
callboost::spirit::traits::create_generator167         static type call()
168         {
169             return proto::deep_copy(
170                 '{' << karma::double_ << ',' << karma::double_ << '}');
171         }
172     };
173 }}}
174 //]
175 
176 //[reference_karma_auxiliary_attr_cast_data1
177 // this is just a test structure we want to use in place of an int
178 struct int_data
179 {
180     int i;
181 };
182 
183 // we provide a custom attribute transformation to allow its use as an int
184 namespace boost { namespace spirit { namespace traits
185 {
186     template <>
187     struct transform_attribute<int_data const, int, karma::domain>
188     {
189         typedef int type;
preboost::spirit::traits::transform_attribute190         static int pre(int_data const& d) { return d.i; }
191     };
192 }}}
193 //]
194 
195 namespace client
196 {
197     using boost::spirit::karma::grammar;
198     using boost::spirit::karma::rule;
199     using boost::spirit::ascii::space_type;
200 
201     //[karma_reference_grammar_definition
202     /*`Basic grammar usage:
203      */
204     struct num_list : grammar<output_iterator_type, space_type, std::vector<int>()>
205     {
num_listclient::num_list206         num_list() : base_type(start)
207         {
208             using boost::spirit::int_;
209             num = int_;
210             start = num << *(',' << num);
211         }
212 
213         rule<output_iterator_type, space_type, std::vector<int>()> start;
214         rule<output_iterator_type, space_type, int()> num;
215     };
216     //]
217 }
218 
main()219 int main()
220 {
221     ///////////////////////////////////////////////////////////////////////////
222     // Operators
223     ///////////////////////////////////////////////////////////////////////////
224     {
225         //[reference_karma_using_declarations_sequence
226         using boost::spirit::karma::double_;
227         //]
228 
229         //[reference_karma_sequence
230         test_generator_attr("1.0,2.0", double_ << ',' << double_, std::make_pair(1.0, 2.0));
231         //]
232     }
233 
234     {
235         //[reference_karma_using_declarations_alternative
236         using boost::spirit::karma::double_;
237         using boost::spirit::karma::ascii::string;
238         //]
239 
240         //[reference_karma_alternative1
241         boost::variant<std::string, double> v1(1.0);
242         test_generator_attr("1.0", string | double_, v1);
243         test_generator_attr("2.0", string | double_, 2.0);
244         //]
245 
246         //[reference_karma_alternative2
247         boost::variant<std::string, double> v2("example");
248         test_generator_attr("example", string | double_, v2);
249         test_generator_attr("example", string | double_, "example");
250         //]
251     }
252 
253     {
254         //[reference_karma_using_declarations_kleene
255         using boost::spirit::karma::double_;
256         using boost::spirit::karma::space;
257         //]
258 
259         //[reference_karma_kleene
260         std::vector<double> v;
261         v.push_back(1.0);
262         v.push_back(2.0);
263         v.push_back(3.0);
264         test_generator_attr_delim("1.0 2.0 3.0 ", *double_, space, v);
265         //]
266     }
267 
268     {
269         //[reference_karma_using_declarations_plus
270         using boost::spirit::karma::double_;
271         using boost::spirit::karma::space;
272         //]
273 
274         //[reference_karma_plus1
275         std::vector<double> v1;
276         v1.push_back(1.0);
277         v1.push_back(2.0);
278         v1.push_back(3.0);
279         test_generator_attr_delim("1.0 2.0 3.0 ", +double_, space, v1);
280         //]
281 
282         //[reference_karma_plus2
283         std::vector<double> v2;               // empty container
284         test_generator_attr("empty", +double_ | "empty", v2);
285         //]
286     }
287 
288     {
289         //[reference_karma_using_declarations_list
290         using boost::spirit::karma::double_;
291         //]
292 
293         //[reference_karma_list
294         std::vector<double> v1;
295         v1.push_back(1.0);
296         test_generator_attr("1.0", double_ % ',', v1);
297 
298         v1.push_back(2.0);
299         test_generator_attr("1.0,2.0", double_ % ',', v1);
300         //]
301     }
302 
303     {
304         //[reference_karma_using_declarations_optional
305         using boost::spirit::karma::double_;
306         //]
307 
308         //[reference_karma_optional1
309         boost::optional<double> val(1.0);
310         test_generator_attr("1.0", -double_, val);
311         test_generator_attr("2.0", -double_, 2.0);
312         //]
313     }
314     {
315         using boost::spirit::karma::double_;
316 
317         //[reference_karma_optional2
318         boost::optional<double> val;          // empty optional
319         test_generator_attr("", -double_, val);
320         //]
321     }
322 
323     {
324         //[reference_karma_using_declarations_and_predicate
325         using boost::spirit::karma::double_;
326         using boost::spirit::karma::ascii::char_;
327         using boost::spirit::karma::ascii::string;
328         using boost::phoenix::ref;
329         //]
330 
331         //[reference_karma_and_predicate
332         test_generator_attr("b", &char_('a') << 'b' | 'c', 'a');
333         test_generator_attr("c", &char_('a') << 'b' | 'c', 'x');
334 
335         test_generator_attr("abc", &string("123") << "abc" | "def", "123");
336         test_generator_attr("def", &string("123") << "abc" | "def", "456");
337         //]
338     }
339 
340     {
341         //[reference_karma_using_declarations_not_predicate
342         using boost::spirit::karma::double_;
343         using boost::spirit::karma::ascii::char_;
344         using boost::spirit::karma::ascii::string;
345         using boost::phoenix::ref;
346         //]
347 
348         //[reference_karma_not_predicate
349         test_generator_attr("c", !char_('a') << 'b' | 'c', 'a');
350         test_generator_attr("b", !char_('a') << 'b' | 'c', 'x');
351 
352         test_generator_attr("def", !string("123") << "abc" | "def", "123");
353         test_generator_attr("abc", !string("123") << "abc" | "def", "456");
354         //]
355     }
356 
357     ///////////////////////////////////////////////////////////////////////////
358     //  Directives
359     ///////////////////////////////////////////////////////////////////////////
360     {
361         //[reference_karma_using_declarations_alignment
362         using boost::spirit::karma::double_;
363         using boost::spirit::karma::left_align;
364         using boost::spirit::karma::center;
365         using boost::spirit::karma::right_align;
366         //]
367 
368         //[reference_karma_alignment
369         std::pair<double, double> p (1.0, 2.0);
370         test_generator_attr("1.0     |2.0", left_align(8)[double_] << '|' << double_, p);
371         test_generator_attr("   1.0  |2.0", center(8)[double_] << '|' << double_, p);
372         test_generator_attr("     1.0|2.0", right_align(8)[double_] << '|' << double_, p);
373         //]
374     }
375 
376     {
377         //[reference_karma_using_declarations_repeat
378         using boost::spirit::karma::double_;
379         using boost::spirit::karma::repeat;
380         //]
381 
382         //[reference_karma_repeat
383         std::vector<double> v;
384         v.push_back(1.0);
385         v.push_back(2.0);
386         v.push_back(3.0);
387 
388         test_generator_attr("[1.0][2.0][3.0]", repeat['[' << double_ << ']'], v);
389         test_generator_attr("[1.0][2.0]", repeat(2)['[' << double_ << ']'], v);
390 
391         // fails because of insufficient number of items
392         test_generator_attr("", repeat(4)['[' << double_ << ']'], v);
393         //]
394     }
395 
396     {
397         //[reference_karma_using_declarations_delimit
398         using boost::spirit::karma::double_;
399         using boost::spirit::karma::delimit;
400         using boost::spirit::karma::verbatim;
401         //]
402 
403         //[reference_karma_delimit
404         test_generator_attr("[ 2.0 , 4.3 ] ",
405             delimit['[' << double_ << ',' << double_ << ']'], 2.0, 4.3);
406         test_generator_attr("[*2.0*,*4.3*]*",
407             delimit('*')['[' << double_ << ',' << double_ << ']'], 2.0, 4.3);
408         test_generator_attr("[2.0, 4.3 ] ",
409             delimit[verbatim['[' << double_ << ','] << double_ << ']'], 2.0, 4.3);
410         //]
411     }
412 
413     {
414         //[reference_karma_using_declarations_upperlower
415         using boost::spirit::karma::double_;
416         using boost::spirit::ascii::upper;
417         using boost::spirit::ascii::lower;
418         //]
419 
420         //[reference_karma_upperlower
421         test_generator_attr("abc:2.0e-06", lower["ABC:" << double_], 2e-6);
422         test_generator_attr("ABC:2.0E-06", upper["abc:" << double_], 2e-6);
423         //]
424     }
425 
426     {
427         //[reference_karma_using_declarations_maxwidth
428         using boost::spirit::karma::double_;
429         using boost::spirit::karma::maxwidth;
430         using boost::spirit::karma::left_align;
431         using boost::spirit::karma::right_align;
432         //]
433 
434         //[reference_karma_maxwidth
435         test_generator("01234", maxwidth(5)["0123456789"]);
436         test_generator("  012", maxwidth(5)[right_align(12)["0123456789"]]);
437         test_generator("0123    ", maxwidth(8)[left_align(8)["0123"]]);
438         //]
439     }
440 
441     {
442         //[reference_karma_using_declarations_buffer
443         using boost::spirit::karma::double_;
444         using boost::spirit::karma::buffer;
445         //]
446 
447         //[reference_karma_buffer
448         std::vector<double> v;                // empty container
449         test_generator_attr("", -buffer['[' << +double_ << ']'], v);
450 
451         v.push_back(1.0);                     // now, fill the container
452         v.push_back(2.0);
453         test_generator_attr("[1.02.0]", buffer['[' << +double_ << ']'], v);
454         //]
455     }
456 
457     {
458         //[reference_karma_using_declarations_omit
459         using boost::spirit::karma::double_;
460         using boost::spirit::karma::omit;
461         //]
462 
463         //[reference_karma_omit
464         std::pair<double, double> p (1.0, 2.0);
465         test_generator_attr("2.0", omit[double_] << double_, p);
466         //]
467     }
468 
469     {
470         //[reference_karma_using_declarations_duplicate
471         using boost::spirit::karma::double_;
472         using boost::spirit::karma::duplicate;
473         using boost::spirit::karma::space;
474         //]
475 
476         //[reference_karma_duplicate
477         test_generator_attr("2.02.0", duplicate[double_ << double_], 2.0);
478         test_generator_attr_delim("2.0 2.0 ", duplicate[double_ << double_], space, 2.0);
479         //]
480     }
481 
482     {
483         //[reference_karma_using_declarations_columns
484         using boost::spirit::karma::double_;
485         using boost::spirit::karma::columns;
486         using boost::spirit::karma::space;
487         //]
488 
489         //[reference_karma_columns
490         std::vector<double> v;
491         v.push_back(1.0);
492         v.push_back(2.0);
493         v.push_back(3.0);
494         test_generator_attr("1.0\n2.0\n3.0\n", columns(1)[*double_], v);
495         test_generator_attr_delim("1.0 2.0 \n3.0 \n", columns(2)[*double_], space, v);
496         //]
497     }
498 
499     {
500         //[reference_karma_using_declarations_bool
501         using boost::spirit::karma::bool_;
502         using boost::spirit::karma::lit;
503         //]
504 
505         //[reference_karma_bool
506         test_generator("true", lit(true));
507         test_generator("false", bool_(false));
508         test_generator_attr("true", bool_(true), true);
509         test_generator_attr("", bool_(true), false);    // fails (as true != false)!
510         test_generator_attr("false", bool_, false);
511         //]
512     }
513 
514     {
515         //[reference_karma_using_declarations_int
516         using boost::spirit::karma::int_;
517         using boost::spirit::karma::lit;
518         //]
519 
520         //[reference_karma_int
521         test_generator("-2", lit(-2));
522         test_generator("-2", int_(-2));
523         test_generator_attr("-2", int_(-2), -2);
524         test_generator_attr("", int_(-2), 3);    // fails (as -2 != 3)!
525         test_generator_attr("-2", int_, -2);
526         //]
527     }
528 
529     {
530         //[reference_karma_using_declarations_uint
531         using boost::spirit::karma::uint_;
532         using boost::spirit::karma::lit;
533         //]
534 
535         //[reference_karma_uint
536         test_generator("2", lit(2U));
537         test_generator("2", uint_(2));
538         test_generator_attr("2", uint_(2), 2);
539         test_generator_attr("", uint_(2), 3);    // fails (as 2 != 3)!
540         test_generator_attr("2", uint_, 2);
541         //]
542     }
543 
544     {
545         //[reference_karma_using_declarations_real
546         using boost::spirit::karma::double_;
547         using boost::spirit::karma::lit;
548         //]
549 
550         //[reference_karma_real
551         test_generator("2.0", lit(2.0));
552         test_generator("2.0", double_(2));
553         test_generator_attr("2.0", double_(2.0), 2.0);
554         test_generator_attr("", double_(2.0), 3.0);    // fails (as 2.0 != 3.0)!
555         test_generator_attr("-2.0", double_, -2.0);
556 
557         test_generator_attr("1.234e05", double_, 1234.0e2);
558         test_generator_attr("1.234e-06", double_, 0.000001234);
559         //]
560     }
561 
562     {
563         //[reference_karma_using_declarations_char
564         using boost::spirit::karma::lit;
565         using boost::spirit::ascii::char_;
566         //]
567 
568         //[reference_karma_char
569         test_generator("A", 'A');
570         test_generator("A", lit('A'));
571 
572         test_generator_attr("a", char_, 'a');
573         test_generator("A", char_('A'));
574         test_generator_attr("A", char_('A'), 'A');
575         test_generator_attr("", char_('A'), 'B');         // fails (as 'A' != 'B')
576 
577         test_generator_attr("A", char_('A', 'Z'), 'A');
578         test_generator_attr("", char_('A', 'Z'), 'a');    // fails (as 'a' does not belong to 'A'...'Z')
579 
580         test_generator_attr("k", char_("a-z0-9"), 'k');
581         test_generator_attr("", char_("a-z0-9"), 'A');    // fails (as 'A' does not belong to "a-z0-9")
582         //]
583     }
584 
585     {
586         //[reference_karma_using_declarations_char_class
587         using boost::spirit::karma::alpha;
588         using boost::spirit::karma::upper;
589         //]
590 
591         //[reference_karma_char_class
592         test_generator_attr("a", alpha, 'a');
593         test_generator_attr("A", alpha, 'A');
594         test_generator_attr("", alpha, '1');          // fails (as isalpha('1') is false)
595         test_generator_attr("A", upper[alpha], 'A');
596         test_generator_attr("", upper[alpha], 'a');   // fails (as isupper('a') is false)
597         //]
598     }
599 
600     ///////////////////////////////////////////////////////////////////////////
601     // string
602     {
603         //[reference_karma_using_declarations_string
604         using boost::spirit::karma::lit;
605         using boost::spirit::ascii::string;
606         //]
607 
608         //[reference_karma_string
609         test_generator("abc", "abc");
610         test_generator("abc", lit("abc"));
611         test_generator("abc", lit(std::string("abc")));
612 
613         test_generator_attr("abc", string, "abc");
614         test_generator("abc", string("abc"));
615         test_generator("abc", string(std::string("abc")));
616 
617         test_generator_attr("abc", string("abc"), "abc");
618         test_generator_attr("", string("abc"), "cba");     // fails (as "abc" != "cba")
619         //]
620     }
621 
622     ///////////////////////////////////////////////////////////////////////////
623     // auxiliary
624     {
625         //[reference_karma_using_declarations_eol
626         using boost::spirit::karma::eol;
627         //]
628 
629         //[reference_karma_eol
630         test_generator("\n", eol);
631         test_generator("abc\n", "abc" << eol);
632         //]
633     }
634 
635     {
636         //[reference_karma_using_declarations_attr_cast
637         using boost::spirit::karma::int_;
638         //]
639 
640         //[reference_karma_attr_cast1
641         int_data d = { 1 };
642         test_generator_attr("1", boost::spirit::karma::attr_cast(int_), d);
643         //]
644     }
645 
646     {
647         //[reference_karma_using_declarations_eps
648         using boost::spirit::karma::eps;
649         using boost::phoenix::val;
650         //]
651 
652         //[reference_karma_eps
653         test_generator("abc", eps[std::cout << val("starting eps example")] << "abc");
654         test_generator("abc", eps(true) << "abc");
655         test_generator("", eps(false) << "abc");      // fails as eps expression is 'false'
656         //]
657     }
658 
659     {
660         //[reference_karma_using_declarations_lazy
661         namespace karma = boost::spirit::karma;
662         using boost::spirit::karma::_1;
663         using boost::spirit::ascii::string;
664         using boost::phoenix::val;
665         //]
666 
667         //[reference_karma_lazy
668         test_generator_attr("abc", karma::lazy(val(string)), "abc");
669         test_generator("abc", karma::lazy(val(string))[_1 = "abc"]);
670         //]
671     }
672 
673     ///////////////////////////////////////////////////////////////////////////
674     // stream module
675     {
676         //[reference_karma_using_declarations_stream
677         using boost::spirit::karma::stream;
678         //]
679 
680         //[reference_karma_stream
681         test_generator_attr("abc", stream, "abc");
682         test_generator("abc", stream("abc"));
683         test_generator_attr("{1.2,2.4}", stream, complex(1.2, 2.4));
684         test_generator("{1.2,2.4}", stream(complex(1.2, 2.4)));
685         //]
686     }
687 
688     ///////////////////////////////////////////////////////////////////////////
689     // auto module
690     {
691         //[reference_karma_using_declarations_auto
692         using boost::spirit::karma::auto_;
693         //]
694 
695         //[reference_karma_auto
696         /*`Emit a simple string using the `karma::string` generator:
697          */
698         test_generator_attr("abc", auto_, "abc");
699         test_generator("abc", auto_("abc"));
700 
701         /*`Emit instances of the `complex` data type as defined above using the
702            generator defined by the customization point for `complex`:
703          */
704         test_generator_attr("{1.2,2.4}", auto_, complex(1.2, 2.4));
705         test_generator("{1.2,2.4}", auto_(complex(1.2, 2.4)));
706         //]
707     }
708 
709     ///////////////////////////////////////////////////////////////////////////
710     // binary module
711     {
712         //[reference_karma_using_declarations_native_binary
713         using boost::spirit::karma::byte_;
714         using boost::spirit::karma::word;
715         using boost::spirit::karma::dword;
716         using boost::spirit::karma::qword;
717         //]
718 
719         //[reference_karma_native_binary_little
720         test_binary_generator("\x01", 1, byte_(0x01));
721         test_binary_generator("\x01\x02", 2, word(0x0201));
722         test_binary_generator("\x01\x02\x03\x04", 4, dword(0x04030201));
723         test_binary_generator("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword(0x0807060504030201LL));
724 
725         test_binary_generator_attr("\x01", 1, byte_, 0x01);
726         test_binary_generator_attr("\x01\x02", 2, word, 0x0201);
727         test_binary_generator_attr("\x01\x02\x03\x04", 4, dword, 0x04030201);
728         test_binary_generator_attr("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword, 0x0807060504030201LL);
729         //]
730 
731         //[reference_karma_native_binary_big
732         test_binary_generator("\x01", 1, byte_(0x01));
733         test_binary_generator("\x02\x01", 2, word(0x0201));
734         test_binary_generator("\x04\x03\x02\x01", 4, dword(0x04030201));
735         test_binary_generator("\x08\x07\x06\x05\x04\x03\x02\x01", 8, qword(0x0807060504030201LL));
736 
737         test_binary_generator_attr("\x01", 1, byte_, 0x01);
738         test_binary_generator_attr("\x02\x01", 2, word, 0x0201);
739         test_binary_generator_attr("\x04\x03\x02\x01", 4, dword, 0x04030201);
740         test_binary_generator_attr("\x08\x07\x06\x05\x04\x03\x02\x01", 8, qword, 0x0807060504030201LL);
741         //]
742     }
743 
744     {
745         //[reference_karma_using_declarations_little_binary
746         using boost::spirit::karma::little_word;
747         using boost::spirit::karma::little_dword;
748         using boost::spirit::karma::little_qword;
749         //]
750 
751         //[reference_karma_little_binary
752         test_binary_generator("\x01\x02", 2, little_word(0x0201));
753         test_binary_generator("\x01\x02\x03\x04", 4, little_dword(0x04030201));
754         test_binary_generator("\x01\x02\x03\x04\x05\x06\x07\x08", 8, little_qword(0x0807060504030201LL));
755 
756         test_binary_generator_attr("\x01\x02", 2, little_word, 0x0201);
757         test_binary_generator_attr("\x01\x02\x03\x04", 4, little_dword, 0x04030201);
758         test_binary_generator_attr("\x01\x02\x03\x04\x05\x06\x07\x08", 8, little_qword, 0x0807060504030201LL);
759         //]
760     }
761 
762     {
763         //[reference_karma_using_declarations_big_binary
764         using boost::spirit::karma::big_word;
765         using boost::spirit::karma::big_dword;
766         using boost::spirit::karma::big_qword;
767         //]
768 
769         //[reference_karma_big_binary
770         test_binary_generator("\x02\x01", 2, big_word(0x0201));
771         test_binary_generator("\x04\x03\x02\x01", 4, big_dword(0x04030201));
772         test_binary_generator("\x08\x07\x06\x05\x04\x03\x02\x01", 8, big_qword(0x0807060504030201LL));
773 
774         test_binary_generator_attr("\x02\x01", 2, big_word, 0x0201);
775         test_binary_generator_attr("\x04\x03\x02\x01", 4, big_dword, 0x04030201);
776         test_binary_generator_attr("\x08\x07\x06\x05\x04\x03\x02\x01", 8, big_qword, 0x0807060504030201LL);
777         //]
778     }
779 
780     // action
781     {
782         //[reference_karma_using_declarations_action
783         using boost::spirit::karma::int_;
784         using boost::spirit::karma::string;
785         using boost::spirit::karma::_1;
786         using boost::phoenix::ref;
787         using boost::phoenix::val;
788         //]
789 
790         //[reference_karma_action
791         int i = 42;
792         test_generator("42", int_[_1 = ref(i)]);
793         test_generator("abc", string[_1 = val("abc")]);
794         //]
795     }
796 
797     // rule
798     {
799         //[karma_reference_rule
800         //`Some using declarations:
801         using boost::spirit::karma::rule;
802         using boost::spirit::karma::int_;
803         using boost::spirit::ascii::space;
804         using boost::spirit::ascii::space_type;
805 
806         /*`Basic rule:
807          */
808         rule<output_iterator_type> r;
809         r = int_(123);
810         test_generator("123", r);
811 
812         /*`Rule with consumed attribute:
813          */
814         rule<output_iterator_type, int()> ra;
815         ra = int_;
816         test_generator_attr("123", ra, 123);
817 
818         /*`Rule with delimiter and consumed attribute:
819          */
820         rule<output_iterator_type, std::vector<int>(), space_type> rs;
821         rs = *int_;
822         std::vector<int> v;
823         v.push_back(123);
824         v.push_back(456);
825         v.push_back(789);
826         test_generator_attr_delim("123 456 789", rs, space, v);
827         //]
828     }
829 
830     // grammar
831     {
832         using client::num_list;
833 
834         //[karma_reference_grammar_using
835         //`Some using declarations:
836         using boost::spirit::ascii::space_type;
837         using boost::spirit::ascii::space;
838         using boost::spirit::int_;
839         using boost::spirit::karma::grammar;
840         using boost::spirit::karma::rule;
841         //]
842 
843         //[karma_reference_grammar
844         //`How to use the example grammar:
845         num_list nlist;
846         std::vector<int> v;
847         v.push_back(123);
848         v.push_back(456);
849         v.push_back(789);
850         test_generator_attr_delim("123 , 456 , 789", nlist, space, v);
851         //]
852     }
853 
854     // symbols
855     {
856         //[reference_karma_using_declarations_symbols
857         using boost::spirit::karma::symbols;
858         //]
859 
860         //[reference_karma_symbols
861         symbols<char, char const*> sym;
862 
863         sym.add
864             ('a', "Apple")
865             ('b', "Banana")
866             ('o', "Orange")
867         ;
868 
869         test_generator_attr("Banana", sym, 'b');
870         //]
871     }
872 
873     // as
874     {
875         //[reference_karma_using_declarations_as
876         using boost::spirit::utree;
877         using boost::spirit::utree_type;
878         using boost::spirit::utf8_symbol_type;
879         using boost::spirit::karma::as;
880         using boost::spirit::karma::as_string;
881         using boost::spirit::karma::char_;
882         using boost::spirit::karma::double_;
883         //]
884 
885         //[reference_karma_as
886         /*`To properly handle string concatenation with __utree__, we
887            make use of `as_string[]`. We also use `as<T>` to explicitly extract
888            a __utree__ symbol node.*/
889 
890         typedef as<utf8_symbol_type> as_symbol_type;
891         as_symbol_type const as_symbol = as_symbol_type();
892 
893         utree ut;
894         ut.push_back("xyz");
895         ut.push_back(1.23);
896 
897         test_generator_attr("xyz1.23", as_string[*char_] << double_, ut);
898         test_generator_attr("xyz1.23", as<std::string>()[*char_] << double_, ut);
899 
900         ut.clear();
901 
902         ut.push_back(utf8_symbol_type("xyz"));
903         ut.push_back(1.23);
904 
905         test_generator_attr("xyz1.23", as_symbol[*char_] << double_, ut);
906         test_generator_attr("xyz1.23", as<utf8_symbol_type>()[*char_] << double_, ut);
907         //]
908     }
909 
910     return 0;
911 }
912