text: /*=============================================================================
      Copyright (c) 2001-2010 Hartmut Kaiser
      http://spirit.sourceforge.net/
  
      Distributed under the Boost Software License, Version 1.0. (See accompanying
      file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  =============================================================================*/
  #include <boost/config/warning_disable.hpp>
  
  //[reference_karma_includes
  #include <boost/spirit/include/karma.hpp>
  #include <boost/spirit/include/phoenix_core.hpp>
  #include <boost/spirit/include/phoenix_operator.hpp>
  #include <boost/fusion/include/std_pair.hpp>
  #include <iostream>
  #include <string>
  //]
  
  //[reference_karma_includes_simple
  #include <boost/spirit/include/karma.hpp>
  #include <iostream>
  #include <string>
  //]
  
  //[reference_karma_output_iterator
  typedef std::back_insert_iterator<std::string> output_iterator_type;
  //]
  
  //[reference_karma_test
  template <typename G>
  void test_generator(char const* expected, G const& g)
  {
      std::string s;
      std::back_insert_iterator<std::string> out(s);
      if (boost::spirit::karma::generate(out, g) && s == expected)
          std::cout << "ok" << std::endl;
      else
          std::cout << "fail" << std::endl;
  }
  //]
  
  //[reference_karma_test_attr
  template <typename G, typename T>
  void test_generator_attr(char const* expected, G const& g, T const& attr)
  {
      std::string s;
      std::back_insert_iterator<std::string> out(s);
      if (boost::spirit::karma::generate(out, g, attr) && s == expected)
          std::cout << "ok" << std::endl;
      else
          std::cout << "fail" << std::endl;
  }
  //]
  
  //[reference_karma_test_attr2
  template <typename G, typename T1, typename T2>
  void test_generator_attr(char const* expected, G const& g, T1 const& attr1, 
      T2 const& attr2)
  {
      std::string s;
      std::back_insert_iterator<std::string> out(s);
      if (boost::spirit::karma::generate(out, g, attr1, attr2) && s == expected)
          std::cout << "ok" << std::endl;
      else
          std::cout << "fail" << std::endl;
  }
  //]
  
  //[reference_karma_test_attr_delim
  template <typename G, typename Delimiter, typename T>
  void test_generator_attr_delim(char const* expected, G const& g, Delimiter const& d, T const& attr)
  {
      std::string s;
      std::back_insert_iterator<std::string> out(s);
      if (boost::spirit::karma::generate_delimited(out, g, d, attr) && s == expected)
          std::cout << "ok" << std::endl;
      else
          std::cout << "fail" << std::endl;
  }
  //]
  
  //[reference_karma_binary_test
  template <typename G>
  void test_binary_generator(char const* expected, std::size_t size, G const& g)
  {
      std::string s;
      std::back_insert_iterator<std::string> out(s);
      if (boost::spirit::karma::generate(out, g) && !std::memcmp(s.c_str(), expected, size))
          std::cout << "ok" << std::endl;
      else
          std::cout << "fail" << std::endl;
  }
  //]
  
  //[reference_karma_binary_test_attr
  template <typename G, typename T>
  void test_binary_generator_attr(char const* expected, std::size_t size, G const& g, T const& attr)
  {
      std::string s;
      std::back_insert_iterator<std::string> out(s);
      if (boost::spirit::karma::generate(out, g, attr) && !std::memcmp(s.c_str(), expected, size))
          std::cout << "ok" << std::endl;
      else
          std::cout << "fail" << std::endl;
  }
  //]
  
  //[reference_karma_complex
  // a simple complex number representation z = a + bi
  struct complex
  {
      complex (double a, double b)
        : a(a), b(b)
      {}
  
      double a;
      double b;
  };
  //]
  
  //[reference_karma_stream_complex
  // define streaming operator for the type complex
  std::ostream& 
  operator<< (std::ostream& os, complex const& z)
  {
      os << "{" << z.a << "," << z.b << "}";
      return os;
  }
  //]
  
  //[reference_karma_auto_complex
  /*`The following construct is required to allow the `complex` data structure
     to be utilized as a __fusion__ sequence. This is required as we will 
     emit output for this data structure with a __karma__ sequence:
     `'{' << karma::double_ << ',' << karma::double_ << '}'`.
  */
  BOOST_FUSION_ADAPT_STRUCT(
      complex,
      (double, a)
      (double, b)
  )
  
  /*`We add a specialization for the create_generator customization point
     defining a custom output format for the complex type. Generally, any 
     specialization for create_generator is expected to return the proto 
     expression to be used to generate output for the type the customization 
     point has been specialized for.
   */
  /*`We need to utilize `proto::deep_copy` as the expression contains literals 
     (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto 
     expression by reference only. The deep copy converts the proto tree to 
     hold this by value. The deep copy operation can be left out for simpler 
     proto expressions (not containing references to temporaries). Alternatively
     you could use the `proto::make_expr` facility to build the required
     proto expression.
  */
  namespace boost { namespace spirit { namespace traits
  {
      template <>
      struct create_generator<complex>
      {
          typedef proto::result_of::deep_copy<
              BOOST_TYPEOF('{' << karma::double_ << ',' << karma::double_ << '}')
          >::type type;
  
          static type call()
          {
              return proto::deep_copy(
                  '{' << karma::double_ << ',' << karma::double_ << '}');
          }
      };
  }}}
  //]
  
  //[reference_karma_auxiliary_attr_cast_data1
  // this is just a test structure we want to use in place of an int
  struct int_data
  {
      int i;
  };
  
  // we provide a custom attribute transformation to allow its use as an int
  namespace boost { namespace spirit { namespace traits
  {
      template <>
      struct transform_attribute<int_data const, int, karma::domain>
      {
          typedef int type;
          static int pre(int_data const& d) { return d.i; }
      };
  }}}
  //]
  
  namespace client
  {
      using boost::spirit::karma::grammar;
      using boost::spirit::karma::rule;
      using boost::spirit::ascii::space_type;
  
      //[karma_reference_grammar_definition
      /*`Basic grammar usage:
       */
      struct num_list : grammar<output_iterator_type, space_type, std::vector<int>()>
      {
          num_list() : base_type(start)
          {
              using boost::spirit::int_;
              num = int_;
              start = num << *(',' << num);
          }
  
          rule<output_iterator_type, space_type, std::vector<int>()> start;
          rule<output_iterator_type, space_type, int()> num;
      };
      //]
  }
  
  int main()
  {
      ///////////////////////////////////////////////////////////////////////////
      // Operators
      ///////////////////////////////////////////////////////////////////////////
      {
          //[reference_karma_using_declarations_sequence
          using boost::spirit::karma::double_;
          //]
  
          //[reference_karma_sequence
          test_generator_attr("1.0,2.0", double_ << ',' << double_, std::make_pair(1.0, 2.0));
          //]
      }
  
      {
          //[reference_karma_using_declarations_alternative
          using boost::spirit::karma::double_;
          using boost::spirit::karma::ascii::string;
          //]
  
          //[reference_karma_alternative1
          boost::variant<std::string, double> v1(1.0);
          test_generator_attr("1.0", string | double_, v1);
          test_generator_attr("2.0", string | double_, 2.0);
          //]
  
          //[reference_karma_alternative2
          boost::variant<std::string, double> v2("example");
          test_generator_attr("example", string | double_, v2);
          test_generator_attr("example", string | double_, "example");
          //]
      }
  
      {
          //[reference_karma_using_declarations_kleene
          using boost::spirit::karma::double_;
          using boost::spirit::karma::space;
          //]
  
          //[reference_karma_kleene
          std::vector<double> v;
          v.push_back(1.0);
          v.push_back(2.0);
          v.push_back(3.0);
          test_generator_attr_delim("1.0 2.0 3.0 ", *double_, space, v);
          //]
      }
  
      {
          //[reference_karma_using_declarations_plus
          using boost::spirit::karma::double_;
          using boost::spirit::karma::space;
          //]
  
          //[reference_karma_plus1
          std::vector<double> v1;
          v1.push_back(1.0);
          v1.push_back(2.0);
          v1.push_back(3.0);
          test_generator_attr_delim("1.0 2.0 3.0 ", +double_, space, v1);
          //]
  
          //[reference_karma_plus2
          std::vector<double> v2;               // empty container
          test_generator_attr("empty", +double_ | "empty", v2);
          //]
      }
  
      {
          //[reference_karma_using_declarations_list
          using boost::spirit::karma::double_;
          //]
  
          //[reference_karma_list
          std::vector<double> v1;
          v1.push_back(1.0);
          test_generator_attr("1.0", double_ % ',', v1);
  
          v1.push_back(2.0);
          test_generator_attr("1.0,2.0", double_ % ',', v1);
          //]
      }
  
      {
          //[reference_karma_using_declarations_optional
          using boost::spirit::karma::double_;
          //]
  
          //[reference_karma_optional1
          boost::optional<double> val(1.0);
          test_generator_attr("1.0", -double_, val);
          test_generator_attr("2.0", -double_, 2.0);
          //]
      }
      {
          using boost::spirit::karma::double_;
  
          //[reference_karma_optional2
          boost::optional<double> val;          // empty optional
          test_generator_attr("", -double_, val);
          //]
      }
  
      {
          //[reference_karma_using_declarations_and_predicate
          using boost::spirit::karma::double_;
          using boost::spirit::karma::ascii::char_;
          using boost::spirit::karma::ascii::string;
          using boost::phoenix::ref;
          //]
  
          //[reference_karma_and_predicate
          test_generator_attr("b", &char_('a') << 'b' | 'c', 'a');
          test_generator_attr("c", &char_('a') << 'b' | 'c', 'x');
  
          test_generator_attr("abc", &string("123") << "abc" | "def", "123");
          test_generator_attr("def", &string("123") << "abc" | "def", "456");
          //]
      }
  
      {
          //[reference_karma_using_declarations_not_predicate
          using boost::spirit::karma::double_;
          using boost::spirit::karma::ascii::char_;
          using boost::spirit::karma::ascii::string;
          using boost::phoenix::ref;
          //]
  
          //[reference_karma_not_predicate
          test_generator_attr("c", !char_('a') << 'b' | 'c', 'a');
          test_generator_attr("b", !char_('a') << 'b' | 'c', 'x');
  
          test_generator_attr("def", !string("123") << "abc" | "def", "123");
          test_generator_attr("abc", !string("123") << "abc" | "def", "456");
          //]
      }
  
      ///////////////////////////////////////////////////////////////////////////
      //  Directives
      ///////////////////////////////////////////////////////////////////////////
      {
          //[reference_karma_using_declarations_alignment
          using boost::spirit::karma::double_;
          using boost::spirit::karma::left_align;
          using boost::spirit::karma::center;
          using boost::spirit::karma::right_align;
          //]
  
          //[reference_karma_alignment
          std::pair<double, double> p (1.0, 2.0);
          test_generator_attr("1.0     |2.0", left_align(8)[double_] << '|' << double_, p);
          test_generator_attr("   1.0  |2.0", center(8)[double_] << '|' << double_, p);
          test_generator_attr("     1.0|2.0", right_align(8)[double_] << '|' << double_, p);
          //]
      }
  
      {
          //[reference_karma_using_declarations_repeat
          using boost::spirit::karma::double_;
          using boost::spirit::karma::repeat;
          //]
  
          //[reference_karma_repeat
          std::vector<double> v;
          v.push_back(1.0);
          v.push_back(2.0);
          v.push_back(3.0);
  
          test_generator_attr("[1.0][2.0][3.0]", repeat['[' << double_ << ']'], v);
          test_generator_attr("[1.0][2.0]", repeat(2)['[' << double_ << ']'], v);
  
          // fails because of insufficient number of items
          test_generator_attr("", repeat(4)['[' << double_ << ']'], v);
          //]
      }
  
      {
          //[reference_karma_using_declarations_delimit
          using boost::spirit::karma::double_;
          using boost::spirit::karma::delimit;
          using boost::spirit::karma::verbatim;
          //]
  
          //[reference_karma_delimit
          test_generator_attr("[ 2.0 , 4.3 ] ", 
              delimit['[' << double_ << ',' << double_ << ']'], 2.0, 4.3);
          test_generator_attr("[*2.0*,*4.3*]*", 
              delimit('*')['[' << double_ << ',' << double_ << ']'], 2.0, 4.3);
          test_generator_attr("[2.0, 4.3 ] ", 
              delimit[verbatim['[' << double_ << ','] << double_ << ']'], 2.0, 4.3);
          //]
      }
  
      {
          //[reference_karma_using_declarations_upperlower
          using boost::spirit::karma::double_;
          using boost::spirit::ascii::upper;
          using boost::spirit::ascii::lower;
          //]
  
          //[reference_karma_upperlower
          test_generator_attr("abc:2.0e-06", lower["ABC:" << double_], 2e-6);
          test_generator_attr("ABC:2.0E-06", upper["abc:" << double_], 2e-6);
          //]
      }
  
      {
          //[reference_karma_using_declarations_maxwidth
          using boost::spirit::karma::double_;
          using boost::spirit::karma::maxwidth;
          using boost::spirit::karma::left_align;
          using boost::spirit::karma::right_align;
          //]
  
          //[reference_karma_maxwidth
          test_generator("01234", maxwidth(5)["0123456789"]);
          test_generator("  012", maxwidth(5)[right_align(12)["0123456789"]]);
          test_generator("0123    ", maxwidth(8)[left_align(8)["0123"]]);
          //]
      }
  
      {
          //[reference_karma_using_declarations_buffer
          using boost::spirit::karma::double_;
          using boost::spirit::karma::buffer;
          //]
  
          //[reference_karma_buffer
          std::vector<double> v;                // empty container
          test_generator_attr("", -buffer['[' << +double_ << ']'], v);
  
          v.push_back(1.0);                     // now, fill the container
          v.push_back(2.0);
          test_generator_attr("[1.02.0]", buffer['[' << +double_ << ']'], v);
          //]
      }
  
      {
          //[reference_karma_using_declarations_omit
          using boost::spirit::karma::double_;
          using boost::spirit::karma::omit;
          //]
  
          //[reference_karma_omit
          std::pair<double, double> p (1.0, 2.0);
          test_generator_attr("2.0", omit[double_] << double_, p);
          //]
      }
  
      {
          //[reference_karma_using_declarations_duplicate
          using boost::spirit::karma::double_;
          using boost::spirit::karma::duplicate;
          using boost::spirit::karma::space;
          //]
  
          //[reference_karma_duplicate
          test_generator_attr("2.02.0", duplicate[double_ << double_], 2.0);
          test_generator_attr_delim("2.0 2.0 ", duplicate[double_ << double_], space, 2.0);
          //]
      }
  
      {
          //[reference_karma_using_declarations_columns
          using boost::spirit::karma::double_;
          using boost::spirit::karma::columns;
          using boost::spirit::karma::space;
          //]
  
          //[reference_karma_columns
          std::vector<double> v;
          v.push_back(1.0);
          v.push_back(2.0);
          v.push_back(3.0);
          test_generator_attr("1.0\n2.0\n3.0\n", columns(1)[*double_], v);
          test_generator_attr_delim("1.0 2.0 \n3.0 \n", columns(2)[*double_], space, v);
          //]
      }
  
      {
          //[reference_karma_using_declarations_bool
          using boost::spirit::karma::bool_;
          using boost::spirit::karma::lit;
          //]
  
          //[reference_karma_bool
          test_generator("true", lit(true));
          test_generator("false", bool_(false));
          test_generator_attr("true", bool_(true), true);
          test_generator_attr("", bool_(true), false);    // fails (as true != false)!
          test_generator_attr("false", bool_, false);
          //]
      }
  
      {
          //[reference_karma_using_declarations_int
          using boost::spirit::karma::int_;
          using boost::spirit::karma::lit;
          //]
  
          //[reference_karma_int
          test_generator("-2", lit(-2));
          test_generator("-2", int_(-2));
          test_generator_attr("-2", int_(-2), -2);
          test_generator_attr("", int_(-2), 3);    // fails (as -2 != 3)!
          test_generator_attr("-2", int_, -2);
          //]
      }
  
      {
          //[reference_karma_using_declarations_uint
          using boost::spirit::karma::uint_;
          using boost::spirit::karma::lit;
          //]
  
          //[reference_karma_uint
          test_generator("2", lit(2U));
          test_generator("2", uint_(2));
          test_generator_attr("2", uint_(2), 2);
          test_generator_attr("", uint_(2), 3);    // fails (as 2 != 3)!
          test_generator_attr("2", uint_, 2);
          //]
      }
  
      {
          //[reference_karma_using_declarations_real
          using boost::spirit::karma::double_;
          using boost::spirit::karma::lit;
          //]
  
          //[reference_karma_real
          test_generator("2.0", lit(2.0));
          test_generator("2.0", double_(2));
          test_generator_attr("2.0", double_(2.0), 2.0);
          test_generator_attr("", double_(2.0), 3.0);    // fails (as 2.0 != 3.0)!
          test_generator_attr("-2.0", double_, -2.0);
  
          test_generator_attr("1.234e05", double_, 1234.0e2);
          test_generator_attr("1.234e-06", double_, 0.000001234);
          //]
      }
  
      {
          //[reference_karma_using_declarations_char
          using boost::spirit::karma::lit;
          using boost::spirit::ascii::char_;
          //]
  
          //[reference_karma_char
          test_generator("A", 'A');
          test_generator("A", lit('A'));
  
          test_generator_attr("a", char_, 'a');
          test_generator("A", char_('A'));
          test_generator_attr("A", char_('A'), 'A');
          test_generator_attr("", char_('A'), 'B');         // fails (as 'A' != 'B')
  
          test_generator_attr("A", char_('A', 'Z'), 'A');
          test_generator_attr("", char_('A', 'Z'), 'a');    // fails (as 'a' does not belong to 'A'...'Z')
  
          test_generator_attr("k", char_("a-z0-9"), 'k');
          test_generator_attr("", char_("a-z0-9"), 'A');    // fails (as 'A' does not belong to "a-z0-9")
          //]
      }
  
      {
          //[reference_karma_using_declarations_char_class
          using boost::spirit::karma::alpha;
          using boost::spirit::karma::upper;
          //]
  
          //[reference_karma_char_class
          test_generator_attr("a", alpha, 'a');
          test_generator_attr("A", alpha, 'A');
          test_generator_attr("", alpha, '1');          // fails (as isalpha('1') is false)
          test_generator_attr("A", upper[alpha], 'A');
          test_generator_attr("", upper[alpha], 'a');   // fails (as isupper('a') is false)
          //]
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // string
      {
          //[reference_karma_using_declarations_string
          using boost::spirit::karma::lit;
          using boost::spirit::ascii::string;
          //]
  
          //[reference_karma_string
          test_generator("abc", "abc");
          test_generator("abc", lit("abc"));
          test_generator("abc", lit(std::string("abc")));
  
          test_generator_attr("abc", string, "abc");
          test_generator("abc", string("abc"));
          test_generator("abc", string(std::string("abc")));
  
          test_generator_attr("abc", string("abc"), "abc");
          test_generator_attr("", string("abc"), "cba");     // fails (as "abc" != "cba")
          //]
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // auxiliary
      {
          //[reference_karma_using_declarations_eol
          using boost::spirit::karma::eol;
          //]
  
          //[reference_karma_eol
          test_generator("\n", eol);
          test_generator("abc\n", "abc" << eol);
          //]
      }
  
      {
          //[reference_karma_using_declarations_attr_cast
          using boost::spirit::karma::int_;
          //]
  
          //[reference_karma_attr_cast1
          int_data d = { 1 };
          test_generator_attr("1", boost::spirit::karma::attr_cast(int_), d);
          //]
      }
  
      {
          //[reference_karma_using_declarations_eps
          using boost::spirit::karma::eps;
          using boost::phoenix::val;
          //]
  
          //[reference_karma_eps
          test_generator("abc", eps[std::cout << val("starting eps example")] << "abc");
          test_generator("abc", eps(true) << "abc");
          test_generator("", eps(false) << "abc");      // fails as eps expression is 'false'
          //]
      }
  
      {
          //[reference_karma_using_declarations_lazy
          namespace karma = boost::spirit::karma;
          using boost::spirit::karma::_1;
          using boost::spirit::ascii::string;
          using boost::phoenix::val;
          //]
  
          //[reference_karma_lazy
          test_generator_attr("abc", karma::lazy(val(string)), "abc");
          test_generator("abc", karma::lazy(val(string))[_1 = "abc"]);
          //]
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // stream module
      {
          //[reference_karma_using_declarations_stream
          using boost::spirit::karma::stream;
          //]
  
          //[reference_karma_stream
          test_generator_attr("abc", stream, "abc");
          test_generator("abc", stream("abc"));
          test_generator_attr("{1.2,2.4}", stream, complex(1.2, 2.4));
          test_generator("{1.2,2.4}", stream(complex(1.2, 2.4)));
          //]
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // auto module
      {
          //[reference_karma_using_declarations_auto
          using boost::spirit::karma::auto_;
          //]
  
          //[reference_karma_auto
          /*`Emit a simple string using the `karma::string` generator:
           */
          test_generator_attr("abc", auto_, "abc");
          test_generator("abc", auto_("abc"));
  
          /*`Emit instances of the `complex` data type as defined above using the
             generator defined by the customization point for `complex`:
           */
          test_generator_attr("{1.2,2.4}", auto_, complex(1.2, 2.4));
          test_generator("{1.2,2.4}", auto_(complex(1.2, 2.4)));
          //]
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // binary module
      {
          //[reference_karma_using_declarations_native_binary
          using boost::spirit::karma::byte_;
          using boost::spirit::karma::word;
          using boost::spirit::karma::dword;
          using boost::spirit::karma::qword;
          //]
  
          //[reference_karma_native_binary_little
          test_binary_generator("\x01", 1, byte_(0x01));
          test_binary_generator("\x01\x02", 2, word(0x0201));
          test_binary_generator("\x01\x02\x03\x04", 4, dword(0x04030201));
          test_binary_generator("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword(0x0807060504030201LL));
  
          test_binary_generator_attr("\x01", 1, byte_, 0x01);
          test_binary_generator_attr("\x01\x02", 2, word, 0x0201);
          test_binary_generator_attr("\x01\x02\x03\x04", 4, dword, 0x04030201);
          test_binary_generator_attr("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword, 0x0807060504030201LL);
          //]
  
          //[reference_karma_native_binary_big
          test_binary_generator("\x01", 1, byte_(0x01));
          test_binary_generator("\x02\x01", 2, word(0x0201));
          test_binary_generator("\x04\x03\x02\x01", 4, dword(0x04030201));
          test_binary_generator("\x08\x07\x06\x05\x04\x03\x02\x01", 8, qword(0x0807060504030201LL));
  
          test_binary_generator_attr("\x01", 1, byte_, 0x01);
          test_binary_generator_attr("\x02\x01", 2, word, 0x0201);
          test_binary_generator_attr("\x04\x03\x02\x01", 4, dword, 0x04030201);
          test_binary_generator_attr("\x08\x07\x06\x05\x04\x03\x02\x01", 8, qword, 0x0807060504030201LL);
          //]
      }
  
      {
          //[reference_karma_using_declarations_little_binary
          using boost::spirit::karma::little_word;
          using boost::spirit::karma::little_dword;
          using boost::spirit::karma::little_qword;
          //]
  
          //[reference_karma_little_binary
          test_binary_generator("\x01\x02", 2, little_word(0x0201));
          test_binary_generator("\x01\x02\x03\x04", 4, little_dword(0x04030201));
          test_binary_generator("\x01\x02\x03\x04\x05\x06\x07\x08", 8, little_qword(0x0807060504030201LL));
  
          test_binary_generator_attr("\x01\x02", 2, little_word, 0x0201);
          test_binary_generator_attr("\x01\x02\x03\x04", 4, little_dword, 0x04030201);
          test_binary_generator_attr("\x01\x02\x03\x04\x05\x06\x07\x08", 8, little_qword, 0x0807060504030201LL);
          //]
      }
  
      {
          //[reference_karma_using_declarations_big_binary
          using boost::spirit::karma::big_word;
          using boost::spirit::karma::big_dword;
          using boost::spirit::karma::big_qword;
          //]
  
          //[reference_karma_big_binary
          test_binary_generator("\x02\x01", 2, big_word(0x0201));
          test_binary_generator("\x04\x03\x02\x01", 4, big_dword(0x04030201));
          test_binary_generator("\x08\x07\x06\x05\x04\x03\x02\x01", 8, big_qword(0x0807060504030201LL));
  
          test_binary_generator_attr("\x02\x01", 2, big_word, 0x0201);
          test_binary_generator_attr("\x04\x03\x02\x01", 4, big_dword, 0x04030201);
          test_binary_generator_attr("\x08\x07\x06\x05\x04\x03\x02\x01", 8, big_qword, 0x0807060504030201LL);
          //]
      }
  
      // action
      {
          //[reference_karma_using_declarations_action
          using boost::spirit::karma::int_;
          using boost::spirit::karma::string;
          using boost::spirit::karma::_1;
          using boost::phoenix::ref;
          using boost::phoenix::val;
          //]
  
          //[reference_karma_action
          int i = 42;
          test_generator("42", int_[_1 = ref(i)]);
          test_generator("abc", string[_1 = val("abc")]);
          //]
      }
  
      // rule
      {
          //[karma_reference_rule
          //`Some using declarations:
          using boost::spirit::karma::rule;
          using boost::spirit::karma::int_;
          using boost::spirit::ascii::space;
          using boost::spirit::ascii::space_type;
  
          /*`Basic rule:
           */
          rule<output_iterator_type> r;
          r = int_(123);
          test_generator("123", r);
  
          /*`Rule with consumed attribute:
           */
          rule<output_iterator_type, int()> ra;
          ra = int_;
          test_generator_attr("123", ra, 123);
  
          /*`Rule with delimiter and consumed attribute:
           */
          rule<output_iterator_type, std::vector<int>(), space_type> rs;
          rs = *int_;
          std::vector<int> v;
          v.push_back(123);
          v.push_back(456);
          v.push_back(789);
          test_generator_attr_delim("123 456 789", rs, space, v);
          //]
      }
  
      // grammar
      {
          using client::num_list;
  
          //[karma_reference_grammar_using
          //`Some using declarations:
          using boost::spirit::ascii::space_type;
          using boost::spirit::ascii::space;
          using boost::spirit::int_;
          using boost::spirit::karma::grammar;
          using boost::spirit::karma::rule;
          //]
  
          //[karma_reference_grammar
          //`How to use the example grammar:
          num_list nlist;
          std::vector<int> v;
          v.push_back(123);
          v.push_back(456);
          v.push_back(789);
          test_generator_attr_delim("123 , 456 , 789", nlist, space, v);
          //]
      }
  
      // symbols
      {
          //[reference_karma_using_declarations_symbols
          using boost::spirit::karma::symbols;
          //]
  
          //[reference_karma_symbols
          symbols<char, char const*> sym;
  
          sym.add
              ('a', "Apple")
              ('b', "Banana")
              ('o', "Orange")
          ;
  
          test_generator_attr("Banana", sym, 'b');
          //]
      }
  
      return 0;
  }
  