summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/spirit/example/karma
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/spirit/example/karma')
-rw-r--r--src/boost/libs/spirit/example/karma/Jamfile38
-rw-r--r--src/boost/libs/spirit/example/karma/actions.cpp131
-rw-r--r--src/boost/libs/spirit/example/karma/auto_facilities.cpp244
-rw-r--r--src/boost/libs/spirit/example/karma/basic_facilities.cpp229
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast.hpp177
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp170
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp172
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp248
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp190
-rw-r--r--src/boost/libs/spirit/example/karma/classify_char.cpp103
-rw-r--r--src/boost/libs/spirit/example/karma/complex_number.cpp132
-rw-r--r--src/boost/libs/spirit/example/karma/complex_number_adapt.cpp153
-rw-r--r--src/boost/libs/spirit/example/karma/complex_number_easier.cpp133
-rw-r--r--src/boost/libs/spirit/example/karma/customize_counter.cpp127
-rw-r--r--src/boost/libs/spirit/example/karma/customize_embedded_container.cpp108
-rw-r--r--src/boost/libs/spirit/example/karma/customize_use_as_container.cpp164
-rw-r--r--src/boost/libs/spirit/example/karma/escaped_string.cpp66
-rw-r--r--src/boost/libs/spirit/example/karma/generate_code.cpp80
-rw-r--r--src/boost/libs/spirit/example/karma/key_value_sequence.cpp74
-rw-r--r--src/boost/libs/spirit/example/karma/mini_xml_karma.cpp222
-rw-r--r--src/boost/libs/spirit/example/karma/num_list1.cpp121
-rw-r--r--src/boost/libs/spirit/example/karma/num_list2.cpp117
-rw-r--r--src/boost/libs/spirit/example/karma/num_list3.cpp150
-rw-r--r--src/boost/libs/spirit/example/karma/num_matrix.cpp114
-rw-r--r--src/boost/libs/spirit/example/karma/printf_style_double_format.cpp282
-rw-r--r--src/boost/libs/spirit/example/karma/quick_start1.cpp119
-rw-r--r--src/boost/libs/spirit/example/karma/quoted_strings.cpp70
-rw-r--r--src/boost/libs/spirit/example/karma/reference.cpp911
-rw-r--r--src/boost/libs/spirit/example/karma/reorder_struct.cpp105
-rw-r--r--src/boost/libs/spirit/example/karma/simple_columns_directive.cpp49
-rw-r--r--src/boost/libs/spirit/example/karma/simple_columns_directive.hpp133
31 files changed, 5132 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/example/karma/Jamfile b/src/boost/libs/spirit/example/karma/Jamfile
new file mode 100644
index 00000000..a93cbb7a
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/Jamfile
@@ -0,0 +1,38 @@
+#==============================================================================
+# Copyright (c) 2001-2009 Hartmut Kaiser
+# Copyright (c) 2001-2009 Joel de Guzman
+#
+# 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)
+#==============================================================================
+project spirit-karma-example
+ : requirements
+ <c++-template-depth>300
+ :
+ :
+ ;
+
+exe actions_example : actions.cpp ;
+exe auto_facilities : auto_facilities.cpp ;
+exe basic_facilities : basic_facilities.cpp /boost//date_time ;
+exe karma_calc2_ast_dump : calc2_ast_dump.cpp ;
+exe karma_calc2_ast_rpn : calc2_ast_rpn.cpp ;
+exe karma_calc2_ast_vm : calc2_ast_vm.cpp ;
+exe classify_char : classify_char.cpp ;
+exe karma_complex_number : complex_number.cpp ;
+exe karma_complex_number_easier : complex_number_easier.cpp ;
+exe karma_complex_number_adapt : complex_number_adapt.cpp ;
+exe karma_num_list1 : num_list1.cpp ;
+exe karma_num_list2 : num_list2.cpp ;
+exe karma_num_list3 : num_list3.cpp ;
+exe karma_num_matrix : num_matrix.cpp ;
+exe key_value_sequence : key_value_sequence.cpp ;
+exe mini_xml_karma : mini_xml_karma.cpp ;
+exe printf_style_double_format : printf_style_double_format.cpp ;
+exe quick_start1 : quick_start1.cpp ;
+exe karma_reference : reference.cpp ;
+exe karma_reorder_struct : reorder_struct.cpp ;
+exe karma_escaped_string : escaped_string.cpp ;
+exe simple_columns_directive : simple_columns_directive.cpp ;
+exe quoted_strings : quoted_strings.cpp ;
+
diff --git a/src/boost/libs/spirit/example/karma/actions.cpp b/src/boost/libs/spirit/example/karma/actions.cpp
new file mode 100644
index 00000000..d5b5efe2
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/actions.cpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Hartmut Kaiser
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/bind.hpp>
+
+#include <iostream>
+#include <sstream>
+
+// Presented are various ways to attach semantic actions
+// * Using plain function pointer
+// * Using simple function object
+// * Using boost.bind
+// * Using boost.lambda
+
+using boost::spirit::unused_type;
+
+//[karma_tutorial_semantic_action_functions
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+
+ // A plain function
+ void read_function(int& i)
+ {
+ i = 42;
+ }
+
+ // A member function
+ struct reader
+ {
+ void print(int& i) const
+ {
+ i = 42;
+ }
+ };
+
+ // A function object
+ struct read_action
+ {
+ void operator()(int& i, unused_type, unused_type) const
+ {
+ i = 42;
+ }
+ };
+}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ using boost::spirit::karma::int_;
+ using boost::spirit::karma::generate;
+ using client::read_function;
+ using client::reader;
+ using client::read_action;
+
+ { // example using plain functions
+ using namespace boost::spirit;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions1
+ generate(outiter, '{' << int_[&read_function] << '}');
+ //]
+
+ std::cout << "Simple function: " << generated << std::endl;
+ }
+
+ { // example using simple function object
+ using namespace boost::spirit;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions2
+ generate(outiter, '{' << int_[read_action()] << '}');
+ //]
+
+ std::cout << "Simple function object: " << generated << std::endl;
+ }
+
+ { // example using plain function with boost.bind
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions3
+ generate(outiter, '{' << int_[boost::bind(&read_function, _1)] << '}');
+ //]
+
+ std::cout << "Simple function with Boost.Bind: " << generated << std::endl;
+ }
+
+ { // example using member function with boost.bind
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions4
+ reader r;
+ generate(outiter, '{' << int_[boost::bind(&reader::print, &r, _1)] << '}');
+ //]
+
+ std::cout << "Member function: " << generated << std::endl;
+ }
+
+ { // example using boost.lambda
+ namespace lambda = boost::lambda;
+ using namespace boost::spirit;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions5
+ std::stringstream strm("42");
+ generate(outiter, '{' << int_[strm >> lambda::_1] << '}');
+ //]
+
+ std::cout << "Boost.Lambda: " << generated << std::endl;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/auto_facilities.cpp b/src/boost/libs/spirit/example/karma/auto_facilities.cpp
new file mode 100644
index 00000000..b094f40a
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/auto_facilities.cpp
@@ -0,0 +1,244 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The main purpose of this example is to show the uniform and easy way of
+// output formatting for different container types.
+//
+// The 'auto_' primitive used below is very similar to the 'stream' primitive
+// demonstrated in the example 'basic_facilities.cpp' as it allows to generate
+// output from a multitude of data types. The main difference is that it is
+// mapped to the correct Karma generator instead of using any available
+// operator<<() for the contained data type. Additionally this means, that
+// the format descriptions used below will be usable for any contained type as
+// long as this type has a defined mapping to a Karma generator.
+
+// use a larger value for the alignment field width (default is 10)
+#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 25
+
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+#include <algorithm>
+#include <cstdlib>
+
+#include <boost/range.hpp>
+#include <boost/array.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+#include <boost/fusion/include/array.hpp>
+
+#include <boost/spirit/include/karma.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace traits
+{
+ // We add a specialization for the create_generator customization point
+ // defining a custom output format for the value type of the std::map used
+ // below (std::pair<int const, std::string>). 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 a literal
+ // (the ':') which normally gets 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.
+ template <>
+ struct create_generator<std::pair<int const, std::string> >
+ {
+ typedef proto::result_of::deep_copy<
+ BOOST_TYPEOF(int_ << ':' << string)
+ >::type type;
+
+ static type call()
+ {
+ return proto::deep_copy(int_ << ':' << string);
+ }
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+// Output the given containers in list format
+// Note: the format description does not depend on the type of the sequence
+// nor does it depend on the type of the elements contained in the
+// sequence
+///////////////////////////////////////////////////////////////////////////////
+template <typename Container>
+void output_container(std::ostream& os, Container const& c)
+{
+ // output the container as a sequence without separators
+ os <<
+ karma::format(
+ auto_, // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ *auto_, // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a space separated sequence
+ os <<
+ karma::format_delimited(
+ auto_, // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format_delimited(
+ *auto_, // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format_delimited(
+ '[' << *auto_ << ']', // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list
+ os <<
+ karma::format(
+ auto_ % ", ", // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (auto_ % ", ") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << -(auto_ % ", ") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (+auto_ | "empty") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list of items enclosed in '()'
+ os <<
+ karma::format(
+ ('(' << auto_ << ')') % ", ", // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (
+ ('(' << auto_ << ')') % ", "
+ ) << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a HTML list
+ os <<
+ karma::format_delimited(
+ "<ol>" <<
+ *verbatim["<li>" << auto_ << "</li>"]
+ << "</ol>", // format description
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ // output the container as right aligned column
+ os <<
+ karma::format_delimited(
+ *verbatim[
+ "|" << right_align[auto_] << "|"
+ ], // format description
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ os << std::endl;
+}
+
+int main()
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // C-style array
+ int i[4] = { 3, 6, 9, 12 };
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "int i[]" << std::endl;
+ output_container(std::cout, boost::make_iterator_range(i, i+4));
+
+ ///////////////////////////////////////////////////////////////////////////
+ // vector
+ std::vector<int> v (5);
+ std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::vector<int>" << std::endl;
+ output_container(std::cout, v);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // list
+ std::list<char> l;
+ l.push_back('A');
+ l.push_back('B');
+ l.push_back('C');
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::list<char>" << std::endl;
+ output_container(std::cout, l);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // strings
+ std::string str("Hello world!");
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::string" << std::endl;
+ output_container(std::cout, str);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // boost::array
+ boost::array<long, 5> arr;
+ std::generate(arr.begin(), arr.end(), std::rand); // randomly fill the array
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "boost::array<long, 5>" << std::endl;
+ output_container(std::cout, arr);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // map of int --> string mappings
+ std::map<int, std::string> mappings;
+ mappings.insert(std::make_pair(0, "zero"));
+ mappings.insert(std::make_pair(1, "one"));
+ mappings.insert(std::make_pair(2, "two"));
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::map<int, std::string>" << std::endl;
+ output_container(std::cout, mappings);
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/basic_facilities.cpp b/src/boost/libs/spirit/example/karma/basic_facilities.cpp
new file mode 100644
index 00000000..63514032
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/basic_facilities.cpp
@@ -0,0 +1,229 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The main purpose of this example is to show the uniform and easy way of
+// output formatting for different container types.
+//
+// Since the 'stream' primitive used below uses the streaming operator defined
+// for the container value_type, you must make sure to have a corresponding
+// operator<<() available for this contained data type. OTOH this means, that
+// the format descriptions used below will be usable for any contained type as
+// long as this type has an associated streaming operator defined.
+
+// use a larger value for the alignment field width (default is 10)
+#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 25
+
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+#include <algorithm>
+#include <cstdlib>
+
+#include <boost/range.hpp>
+#include <boost/array.hpp>
+#include <boost/date_time/gregorian/gregorian.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// This streaming operator is needed to generate the output from the map below
+// Yes, it's heresy, but this operator has to live in namespace std to be
+// picked up by the compiler.
+namespace std {
+ inline std::ostream&
+ operator<<(std::ostream& os, std::pair<int const, std::string> v)
+ {
+ os << v.first << ": " << v.second;
+ return os;
+ }
+}
+
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_format.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// Output the given containers in list format
+// Note: the format description does not depend on the type of the sequence
+// nor does it depend on the type of the elements contained in the
+// sequence
+///////////////////////////////////////////////////////////////////////////////
+template <typename Container>
+void output_container(std::ostream& os, Container const& c)
+{
+ // output the container as a space separated sequence
+ os <<
+ karma::format(
+ *stream, // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a space separated sequence
+ os <<
+ karma::format_delimited(
+ *stream, // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format_delimited(
+ '[' << *stream << ']', // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list
+ os <<
+ karma::format(
+ stream % ", ", // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (stream % ", ") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << -(stream % ", ") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (+stream | "empty") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list of items enclosed in '()'
+ os <<
+ karma::format(
+ ('(' << stream << ')') % ", ", // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (
+ ('(' << stream << ')') % ", "
+ ) << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a HTML list
+ os <<
+ karma::format_delimited(
+ "<ol>" <<
+ *verbatim["<li>" << stream << "</li>"]
+ << "</ol>", // format description
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ // output the container as right aligned column
+ os <<
+ karma::format_delimited(
+ *verbatim[
+ "|" << right_align[stream] << "|"
+ ], // format description
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ os << std::endl;
+}
+
+int main()
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // C-style array
+ int i[4] = { 3, 6, 9, 12 };
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "int i[]" << std::endl;
+ output_container(std::cout, boost::make_iterator_range(i, i+4));
+
+ ///////////////////////////////////////////////////////////////////////////
+ // vector
+ std::vector<int> v (5);
+ std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::vector<int>" << std::endl;
+ output_container(std::cout, v);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // list
+ std::list<char> l;
+ l.push_back('A');
+ l.push_back('B');
+ l.push_back('C');
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::list<char>" << std::endl;
+ output_container(std::cout, l);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // strings
+ std::string str("Hello world!");
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::string" << std::endl;
+ output_container(std::cout, str);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // boost::array
+ boost::array<long, 5> arr;
+ std::generate(arr.begin(), arr.end(), std::rand); // randomly fill the array
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "boost::array<long, 5>" << std::endl;
+ output_container(std::cout, arr);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // vector of boost::date objects
+ // Note: any registered facets get used!
+ using namespace boost::gregorian;
+ std::vector<date> dates;
+ dates.push_back(date(2005, Jun, 25));
+ dates.push_back(date(2006, Jan, 13));
+ dates.push_back(date(2007, May, 03));
+
+ date_facet* facet(new date_facet("%A %B %d, %Y"));
+ std::cout.imbue(std::locale(std::cout.getloc(), facet));
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::vector<boost::date>" << std::endl;
+ output_container(std::cout, dates);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // map of int --> string mappings
+ std::map<int, std::string> mappings;
+ mappings.insert(std::make_pair(0, "zero"));
+ mappings.insert(std::make_pair(1, "one"));
+ mappings.insert(std::make_pair(2, "two"));
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::map<int, std::string>" << std::endl;
+ output_container(std::cout, mappings);
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast.hpp b/src/boost/libs/spirit/example/karma/calc2_ast.hpp
new file mode 100644
index 00000000..d1ee92e8
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast.hpp
@@ -0,0 +1,177 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a human readable format afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#if !defined(SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM)
+#define SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM
+
+#include <boost/variant.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/karma_domain.hpp>
+#include <boost/spirit/include/support_attributes_fwd.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op;
+struct unary_op;
+struct nil {};
+
+struct expression_ast
+{
+ typedef
+ boost::variant<
+ nil // can't happen!
+ , int
+ , boost::recursive_wrapper<binary_op>
+ , boost::recursive_wrapper<unary_op>
+ >
+ type;
+
+ // expose variant types
+ typedef type::types types;
+
+ // expose variant functionality
+ int which() const { return expr.which(); }
+
+ // constructors
+ expression_ast()
+ : expr(nil()) {}
+
+ expression_ast(unary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(binary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(unsigned int expr)
+ : expr(expr) {}
+
+ expression_ast(type const& expr)
+ : expr(expr) {}
+
+ expression_ast& operator+=(expression_ast const& rhs);
+ expression_ast& operator-=(expression_ast const& rhs);
+ expression_ast& operator*=(expression_ast const& rhs);
+ expression_ast& operator/=(expression_ast const& rhs);
+
+ type expr;
+};
+
+// expose variant functionality
+namespace boost
+{
+ // this function has to live in namespace boost for ADL to correctly find it
+ template <typename T>
+ inline T get(expression_ast const& expr)
+ {
+ return boost::get<T>(expr.expr);
+ }
+
+ namespace spirit { namespace traits
+ {
+ // the specialization below tells Spirit to handle expression_ast as
+ // if it where a 'real' variant (if used with Spirit.Karma)
+ template <>
+ struct not_is_variant<expression_ast, karma::domain>
+ : mpl::false_ {};
+
+ // the specialization of variant_which allows to generically extract
+ // the current type stored in the given variant like type
+ template <>
+ struct variant_which<expression_ast>
+ {
+ static int call(expression_ast const& v)
+ {
+ return v.which();
+ }
+ };
+ }}
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op
+{
+ binary_op() {}
+
+ binary_op(
+ char op
+ , expression_ast const& left
+ , expression_ast const& right)
+ : op(op), left(left), right(right) {}
+
+ char op;
+ expression_ast left;
+ expression_ast right;
+};
+
+struct unary_op
+{
+ unary_op(
+ char op
+ , expression_ast const& right)
+ : op(op), right(right) {}
+
+ char op;
+ expression_ast right;
+};
+
+inline expression_ast& expression_ast::operator+=(expression_ast const& rhs)
+{
+ expr = binary_op('+', expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator-=(expression_ast const& rhs)
+{
+ expr = binary_op('-', expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator*=(expression_ast const& rhs)
+{
+ expr = binary_op('*', expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator/=(expression_ast const& rhs)
+{
+ expr = binary_op('/', expr, rhs);
+ return *this;
+}
+
+// We should be using expression_ast::operator-. There's a bug
+// in phoenix type deduction mechanism that prevents us from
+// doing so. Phoenix will be switching to BOOST_TYPEOF. In the
+// meantime, we will use a phoenix::function below:
+template <char Op>
+struct unary_expr
+{
+ template <typename T>
+ struct result { typedef T type; };
+
+ expression_ast operator()(expression_ast const& expr) const
+ {
+ return unary_op(Op, expr);
+ }
+};
+
+boost::phoenix::function<unary_expr<'+'> > pos;
+boost::phoenix::function<unary_expr<'-'> > neg;
+
+#endif
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp b/src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp
new file mode 100644
index 00000000..ac15c7ca
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp
@@ -0,0 +1,170 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a human readable format afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "calc2_ast.hpp"
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// Our calculator parser grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator
+ : qi::grammar<Iterator, expression_ast(), space_type>
+{
+ calculator() : calculator::base_type(expression)
+ {
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [_val += _1])
+ | ('-' >> term [_val -= _1])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [_val *= _1])
+ | ('/' >> factor [_val /= _1])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [_val = neg(_1)])
+ | ('+' >> factor [_val = pos(_1)])
+ ;
+ }
+
+ qi::rule<Iterator, expression_ast(), space_type> expression, term, factor;
+};
+
+// We need to tell fusion about our binary_op and unary_op structs
+// to make them a first-class fusion citizen
+//
+// Note: we register the members exactly in the same sequence as we need them
+// in the grammar
+BOOST_FUSION_ADAPT_STRUCT(
+ binary_op,
+ (expression_ast, left)
+ (char, op)
+ (expression_ast, right)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ unary_op,
+ (char, op)
+ (expression_ast, right)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST grammar for the generator, this just dumps the AST as a expression
+///////////////////////////////////////////////////////////////////////////////
+template <typename OuputIterator>
+struct dump_ast
+ : karma::grammar<OuputIterator, expression_ast(), space_type>
+{
+ dump_ast() : dump_ast::base_type(ast_node)
+ {
+ ast_node %= int_ | binary_node | unary_node;
+ binary_node %= '(' << ast_node << char_ << ast_node << ')';
+ unary_node %= '(' << char_ << ast_node << ')';
+ }
+
+ karma::rule<OuputIterator, expression_ast(), space_type> ast_node;
+ karma::rule<OuputIterator, binary_op(), space_type> binary_node;
+ karma::rule<OuputIterator, unary_op(), space_type> unary_node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Dump AST's for simple expressions...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ // Our parser grammar definitions
+ typedef std::string::const_iterator iterator_type;
+ typedef calculator<iterator_type> calculator;
+
+ calculator calc;
+
+ // Our generator grammar definitions
+ typedef std::back_insert_iterator<std::string> output_iterator_type;
+ typedef dump_ast<output_iterator_type> dump_ast;
+
+ dump_ast ast_grammar;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ expression_ast ast;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = qi::phrase_parse(iter, end, calc, space, ast);
+
+ if (r && iter == end)
+ {
+ std::string generated;
+ output_iterator_type outit(generated);
+ r = karma::generate_delimited(outit, ast_grammar, space, ast);
+
+ if (r)
+ {
+ std::cout << "Got AST:" << std::endl << generated
+ << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp b/src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp
new file mode 100644
index 00000000..955f2467
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp
@@ -0,0 +1,172 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a reverse polish notation afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "calc2_ast.hpp"
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// Our calculator parser grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator
+ : qi::grammar<Iterator, expression_ast(), space_type>
+{
+ calculator() : calculator::base_type(expression)
+ {
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [_val += _1])
+ | ('-' >> term [_val -= _1])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [_val *= _1])
+ | ('/' >> factor [_val /= _1])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [_val = neg(_1)])
+ | ('+' >> factor [_val = pos(_1)])
+ ;
+ }
+
+ qi::rule<Iterator, expression_ast(), space_type> expression, term, factor;
+};
+
+// We need to tell fusion about our binary_op and unary_op structs
+// to make them a first-class fusion citizen
+//
+// Note: we register the members exactly in the same sequence as we need them
+// in the grammar
+BOOST_FUSION_ADAPT_STRUCT(
+ binary_op,
+ (expression_ast, left)
+ (expression_ast, right)
+ (char, op)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ unary_op,
+ (expression_ast, right)
+ (char, op)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST grammar for the generator, this prints the AST in reverse polish
+// notation
+///////////////////////////////////////////////////////////////////////////////
+template <typename OuputIterator>
+struct ast_rpn
+ : karma::grammar<OuputIterator, expression_ast(), space_type>
+{
+ ast_rpn() : ast_rpn::base_type(ast_node)
+ {
+ ast_node %= int_ | binary_node | unary_node;
+ binary_node %= ast_node << ast_node << char_;
+ unary_node %= '(' << ast_node << char_ << ')';
+ }
+
+ karma::rule<OuputIterator, expression_ast(), space_type> ast_node;
+ karma::rule<OuputIterator, binary_op(), space_type> binary_node;
+ karma::rule<OuputIterator, unary_op(), space_type> unary_node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "RPN generator for simple expressions...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ // Our parser grammar definitions
+ typedef std::string::const_iterator iterator_type;
+ typedef calculator<iterator_type> calculator;
+
+ calculator calc;
+
+ // Our generator grammar definitions
+ typedef std::back_insert_iterator<std::string> output_iterator_type;
+ typedef ast_rpn<output_iterator_type> ast_rpn;
+
+ ast_rpn ast_grammar;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ expression_ast ast; // this will hold the generated AST
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = qi::phrase_parse(iter, end, calc, space, ast);
+
+ if (r && iter == end)
+ {
+ std::string generated;
+ output_iterator_type outit(generated);
+ r = karma::generate_delimited(outit, ast_grammar, space, ast);
+
+ if (r)
+ {
+ std::cout << "RPN for '" << str << "': \n" << generated
+ << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp b/src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp
new file mode 100644
index 00000000..77fab096
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp
@@ -0,0 +1,248 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST from which we generate
+// a simple byte code representation being interpreted by a similar virtual
+// machine.
+//
+// [ JDG April 28, 2008 ]
+// [ HK May 05, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "calc2_ast_vm.hpp"
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// Our calculator parser grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator
+ : qi::grammar<Iterator, expression_ast(), space_type>
+{
+ calculator() : calculator::base_type(expression)
+ {
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [_val += _1])
+ | ('-' >> term [_val -= _1])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [_val *= _1])
+ | ('/' >> factor [_val /= _1])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [_val = neg(_1)])
+ | ('+' >> factor [_val = pos(_1)])
+ ;
+ }
+
+ qi::rule<Iterator, expression_ast(), space_type> expression, term, factor;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// The Virtual Machine
+///////////////////////////////////////////////////////////////////////////////
+class vmachine
+{
+public:
+ union element {
+ int code;
+ char bytes[sizeof(int)];
+ };
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ int top() const { return stack_ptr[-1]; };
+ void execute(std::vector<element> const& code);
+
+private:
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+};
+
+void vmachine::execute(std::vector<element> const& code)
+{
+ std::vector<element>::const_iterator pc = code.begin();
+ stack_ptr = stack.begin();
+
+ while ((*pc).code && pc != code.end())
+ {
+ switch ((*pc++).code)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = (*pc++).code;
+ break;
+ }
+ }
+}
+
+// We need to tell fusion about our binary_op and unary_op structs
+// to make them a first-class fusion citizen
+//
+// Note: we register the members exactly in the same sequence as we need them
+// in the grammar
+BOOST_FUSION_ADAPT_STRUCT(
+ binary_op,
+ (expression_ast, left)
+ (expression_ast, right)
+ (int, op)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ unary_op,
+ (expression_ast, right)
+ (int, op)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST grammar for the generator, this just dumps the AST as a expression
+///////////////////////////////////////////////////////////////////////////////
+template <typename OuputIterator, typename Delimiter>
+struct generate_byte_code
+ : karma::grammar<OuputIterator, expression_ast(), Delimiter>
+{
+ generate_byte_code() : generate_byte_code::base_type(ast_node)
+ {
+ ast_node %= int_node | binary_node | unary_node;
+ int_node %= dword(op_int) << dword;
+ binary_node %= ast_node << ast_node << byte_;
+ unary_node %= ast_node << byte_;
+ }
+
+ karma::rule<OuputIterator, expression_ast(), Delimiter> ast_node;
+ karma::rule<OuputIterator, int(), Delimiter> int_node;
+ karma::rule<OuputIterator, binary_op(), Delimiter> binary_node;
+ karma::rule<OuputIterator, unary_op(), Delimiter> unary_node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// helper function helping to deduce the delimiter type
+template <typename Delimiter>
+bool generate_vm_code(expression_ast const& ast,
+ std::vector<vmachine::element>& code, Delimiter const& d)
+{
+ // Our generator grammar definitions
+ typedef char* output_iterator_type;
+ typedef generate_byte_code<output_iterator_type, Delimiter> generate_byte_code;
+
+ char* outbuffer = (*code.begin()).bytes;
+ generate_byte_code gen_vm;
+ return karma::generate_delimited(outbuffer, gen_vm, d, ast);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Compile simple expressions to bytecode...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ // Our parser grammar definitions
+ typedef std::string::const_iterator iterator_type;
+ typedef calculator<iterator_type> calculator;
+
+ calculator calc;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ expression_ast ast;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = qi::phrase_parse(iter, end, calc, space, ast);
+
+ if (r && iter == end)
+ {
+ // we assume a vm code size of 4096 is sufficient
+ std::vector<vmachine::element> code (4096);
+ r = generate_vm_code(ast, code, pad(4));
+
+ if (r)
+ {
+ vmachine vm;
+ vm.execute(code);
+ std::cout << "\nresult = " << vm.top() << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp b/src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp
new file mode 100644
index 00000000..b3a51149
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp
@@ -0,0 +1,190 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a human readable format afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#if !defined(SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM)
+#define SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM
+
+#include <boost/variant.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/karma_domain.hpp>
+#include <boost/spirit/include/support_attributes_fwd.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op;
+struct unary_op;
+struct nil {};
+
+struct expression_ast
+{
+ typedef
+ boost::variant<
+ nil // can't happen!
+ , int
+ , boost::recursive_wrapper<binary_op>
+ , boost::recursive_wrapper<unary_op>
+ >
+ type;
+
+ // expose variant types
+ typedef type::types types;
+
+ // expose variant functionality
+ int which() const { return expr.which(); }
+
+ // constructors
+ expression_ast()
+ : expr(nil()) {}
+
+ expression_ast(unary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(binary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(unsigned int expr)
+ : expr(expr) {}
+
+ expression_ast(type const& expr)
+ : expr(expr) {}
+
+ expression_ast& operator+=(expression_ast const& rhs);
+ expression_ast& operator-=(expression_ast const& rhs);
+ expression_ast& operator*=(expression_ast const& rhs);
+ expression_ast& operator/=(expression_ast const& rhs);
+
+ type expr;
+};
+
+// expose variant functionality
+namespace boost
+{
+ // this function has to live in namespace boost for ADL to correctly find it
+ template <typename T>
+ inline T get(expression_ast const& expr)
+ {
+ return boost::get<T>(expr.expr);
+ }
+
+ // the specialization below tells Spirit to handle expression_ast as if it
+ // where a 'real' variant
+ namespace spirit { namespace traits
+ {
+ // the specialization below tells Spirit to handle expression_ast as
+ // if it where a 'real' variant (if used with Spirit.Karma)
+ template <>
+ struct not_is_variant<expression_ast, karma::domain>
+ : mpl::false_ {};
+
+ // the specialization of variant_which allows to generically extract
+ // the current type stored in the given variant like type
+ template <>
+ struct variant_which<expression_ast>
+ {
+ static int call(expression_ast const& v)
+ {
+ return v.which();
+ }
+ };
+ }}
+}
+
+enum byte_code
+{
+ op_neg = 1, // negate the top stack entry
+ op_pos, // essentially a no-op (unary plus)
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+ op_int, // push constant integer into the stack
+};
+
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op
+{
+ binary_op() {}
+
+ binary_op(
+ int op
+ , expression_ast const& left
+ , expression_ast const& right)
+ : op(op), left(left), right(right) {}
+
+ int op;
+ expression_ast left;
+ expression_ast right;
+};
+
+struct unary_op
+{
+ unary_op(
+ int op
+ , expression_ast const& right)
+ : op(op), right(right) {}
+
+ int op;
+ expression_ast right;
+};
+
+inline expression_ast& expression_ast::operator+=(expression_ast const& rhs)
+{
+ expr = binary_op(op_add, expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator-=(expression_ast const& rhs)
+{
+ expr = binary_op(op_sub, expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator*=(expression_ast const& rhs)
+{
+ expr = binary_op(op_mul, expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator/=(expression_ast const& rhs)
+{
+ expr = binary_op(op_div, expr, rhs);
+ return *this;
+}
+
+// We should be using expression_ast::operator-. There's a bug
+// in phoenix type deduction mechanism that prevents us from
+// doing so. Phoenix will be switching to BOOST_TYPEOF. In the
+// meantime, we will use a phoenix::function below:
+template <char Op>
+struct unary_expr
+{
+ template <typename T>
+ struct result { typedef T type; };
+
+ expression_ast operator()(expression_ast const& expr) const
+ {
+ return unary_op(Op, expr);
+ }
+};
+
+boost::phoenix::function<unary_expr<op_pos> > pos;
+boost::phoenix::function<unary_expr<op_neg> > neg;
+
+#endif
diff --git a/src/boost/libs/spirit/example/karma/classify_char.cpp b/src/boost/libs/spirit/example/karma/classify_char.cpp
new file mode 100644
index 00000000..df113f33
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/classify_char.cpp
@@ -0,0 +1,103 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A character classification example
+//
+// [ HK August 12, 2009 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#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>
+#include <complex>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our character classification generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number
+ template <typename OutputIterator>
+ bool classify_character(OutputIterator sink, char c)
+ {
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::digit;
+ using boost::spirit::ascii::xdigit;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::ascii::punct;
+ using boost::spirit::ascii::space;
+ using boost::spirit::ascii::cntrl;
+ using boost::spirit::karma::omit;
+ using boost::spirit::karma::generate;
+
+ if (!boost::spirit::char_encoding::ascii::isascii_(c))
+ return false;
+
+ return generate(sink,
+ // Begin grammar
+ (
+ "The character '" << char_ << "' is "
+ << ( &digit << "a digit"
+ | &xdigit << "a xdigit"
+ | &alpha << "a alpha"
+ | &punct << "a punct"
+ | &space << "a space"
+ | &cntrl << "a cntrl"
+ | "of unknown type"
+ )
+ ),
+ // End grammar
+ c, c
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA character classification micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a character to classify\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::classify_character(sink, str[0]))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << generated << "\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/complex_number.cpp b/src/boost/libs/spirit/example/karma/complex_number.cpp
new file mode 100644
index 00000000..d832553b
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/complex_number.cpp
@@ -0,0 +1,132 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+// Copyright (c) 2001-2010 Joel de Guzman
+//
+// 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)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro generator.
+//
+// [ HK July 7, 2009 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#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>
+#include <complex>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number parser/compiler (that's just a copy of the complex
+ // number example from Qi (see examples/qi/complex_number.cpp)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number
+ template <typename OutputIterator>
+ bool generate_complex(OutputIterator sink, std::complex<double> const& c)
+ {
+ using boost::spirit::karma::eps;
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::_1;
+ using boost::spirit::karma::generate;
+
+ return generate(sink,
+ // Begin grammar
+ (
+ eps(c.imag() != 0) <<
+ '(' << double_[_1 = c.real()] << ", " << double_[_1 = c.imag()] << ')'
+ | double_[_1 = c.real()]
+ )
+ // End grammar
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_complex(sink, c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/complex_number_adapt.cpp b/src/boost/libs/spirit/example/karma/complex_number_adapt.cpp
new file mode 100644
index 00000000..25135e08
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/complex_number_adapt.cpp
@@ -0,0 +1,153 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+// Copyright (c) 2001-2010 Joel de Guzman
+//
+// 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)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro generator - take 3.
+//
+// Look'ma, still no semantic actions! And no explicit access to member
+// functions any more.
+//
+// [ HK April 6, 2010 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#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 <boost/fusion/include/adapt_adt.hpp>
+#include <boost/spirit/include/support_adapt_adt_attributes.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+///////////////////////////////////////////////////////////////////////////////
+// The following macro adapts the type std::complex<double> as a fusion
+// sequence.
+//[tutorial_karma_complex_number_adapt_class
+// We can leave off the setters as Karma does not need them.
+BOOST_FUSION_ADAPT_ADT(
+ std::complex<double>,
+ (bool, bool, obj.imag() != 0, /**/)
+ (double, double, obj.real(), /**/)
+ (double, double, obj.imag(), /**/)
+)
+//]
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number parser/compiler (that's just a copy of the complex
+ // number example from Qi (see examples/qi/complex_number.cpp)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number_adapt
+ template <typename OutputIterator>
+ bool generate_complex(OutputIterator sink, std::complex<double> const& c)
+ {
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::bool_;
+ using boost::spirit::karma::true_;
+ using boost::spirit::karma::omit;
+ using boost::spirit::karma::generate;
+
+ return generate(sink,
+
+ // Begin grammar
+ (
+ &true_ << '(' << double_ << ", " << double_ << ')'
+ | omit[bool_] << double_
+ ),
+ // End grammar
+
+ c // Data to output
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_complex(sink, c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/complex_number_easier.cpp b/src/boost/libs/spirit/example/karma/complex_number_easier.cpp
new file mode 100644
index 00000000..0fe05149
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/complex_number_easier.cpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+// Copyright (c) 2001-2010 Joel de Guzman
+//
+// 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)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro generator - take 2. Look'ma no semantic actions!
+//
+// [ HK July 26, 2009 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#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>
+#include <complex>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number parser/compiler (that's just a copy of the complex
+ // number example from Qi (see examples/qi/complex_number.cpp)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number_easier
+ template <typename OutputIterator>
+ bool generate_complex(OutputIterator sink, std::complex<double> const& c)
+ {
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::omit;
+ using boost::spirit::karma::generate;
+
+ return generate(sink,
+
+ // Begin grammar
+ (
+ !double_(0.0) << '(' << double_ << ", " << double_ << ')'
+ | omit[double_] << double_
+ ),
+ // End grammar
+
+ c.imag(), c.real(), c.imag() // Data to output
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_complex(sink, c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/customize_counter.cpp b/src/boost/libs/spirit/example/karma/customize_counter.cpp
new file mode 100644
index 00000000..62506928
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/customize_counter.cpp
@@ -0,0 +1,127 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 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>
+
+//[customize_karma_counter_includes
+#include <boost/spirit/include/karma.hpp>
+#include <iostream>
+#include <vector>
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[customize_karma_counter_data
+namespace client
+{
+ struct counter
+ {
+ // expose the current value of the counter as our iterator
+ typedef int iterator;
+
+ // expose 'int' as the type of each generated element
+ typedef int type;
+
+ counter(int max_count)
+ : counter_(0), max_count_(max_count)
+ {}
+
+ int counter_;
+ int max_count_;
+ };
+}
+//]
+
+//[customize_karma_counter_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+//
+// Note that all templates below are specialized using the 'const' type.
+// This is necessary as all attributes in Karma are 'const'.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'is_container<>' will tell the
+ // library to treat the type 'client::counter' as a container providing
+ // the items to generate output from.
+ template <>
+ struct is_container<client::counter const>
+ : mpl::true_
+ {};
+
+ // The specialization of the template 'container_iterator<>' will be
+ // invoked by the library to evaluate the iterator type to be used
+ // for iterating the data elements in the container.
+ template <>
+ struct container_iterator<client::counter const>
+ {
+ typedef client::counter::iterator type;
+ };
+
+ // The specialization of the templates 'begin_container<>' and
+ // 'end_container<>' below will be used by the library to get the iterators
+ // pointing to the begin and the end of the data to generate output from.
+ // These specializations respectively return the initial and maximum
+ // counter values.
+ //
+ // The passed argument refers to the attribute instance passed to the list
+ // generator.
+ template <>
+ struct begin_container<client::counter const>
+ {
+ static client::counter::iterator
+ call(client::counter const& c)
+ {
+ return c.counter_;
+ }
+ };
+
+ template <>
+ struct end_container<client::counter const>
+ {
+ static client::counter::iterator
+ call(client::counter const& c)
+ {
+ return c.max_count_;
+ }
+ };
+}}}
+//]
+
+//[customize_karma_counter_iterator_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'deref_iterator<>' will be used to
+ // dereference the iterator associated with our counter data structure.
+ // Since we expose the current value as the iterator we just return the
+ // current iterator as the return value.
+ template <>
+ struct deref_iterator<client::counter::iterator>
+ {
+ typedef client::counter::type type;
+
+ static type call(client::counter::iterator const& it)
+ {
+ return it;
+ }
+ };
+}}}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ //[customize_karma_counter
+ // use the instance of a 'client::counter' instead of a STL vector
+ client::counter count(4);
+ std::cout << karma::format(karma::int_ % ", ", count) << std::endl; // prints: '0, 1, 2, 3'
+ //]
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/customize_embedded_container.cpp b/src/boost/libs/spirit/example/karma/customize_embedded_container.cpp
new file mode 100644
index 00000000..c0c071b4
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/customize_embedded_container.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 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>
+
+//[customize_karma_embedded_container_includes
+#include <boost/spirit/include/karma.hpp>
+#include <iostream>
+#include <vector>
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[customize_karma_embedded_container_data
+namespace client
+{
+ struct embedded_container
+ {
+ // expose the iterator of the embedded vector as our iterator
+ typedef std::vector<int>::const_iterator iterator;
+
+ // expose the type of the held data elements as our type
+ typedef std::vector<int>::value_type type;
+
+ // this is the vector holding the actual elements we need to generate
+ // output from
+ std::vector<int> data;
+ };
+}
+//]
+
+//[customize_karma_embedded_container_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+//
+// Note that all templates below are specialized using the 'const' type.
+// This is necessary as all attributes in Karma are 'const'.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'is_container<>' will tell the
+ // library to treat the type 'client::embedded_container' as a
+ // container holding the items to generate output from.
+ template <>
+ struct is_container<client::embedded_container const>
+ : mpl::true_
+ {};
+
+ // The specialization of the template 'container_iterator<>' will be
+ // invoked by the library to evaluate the iterator type to be used
+ // for iterating the data elements in the container. We simply return
+ // the type of the iterator exposed by the embedded 'std::vector<int>'.
+ template <>
+ struct container_iterator<client::embedded_container const>
+ {
+ typedef client::embedded_container::iterator type;
+ };
+
+ // The specialization of the templates 'begin_container<>' and
+ // 'end_container<>' below will be used by the library to get the iterators
+ // pointing to the begin and the end of the data to generate output from.
+ // These specializations simply return the 'begin' and 'end' iterators as
+ // exposed by the embedded 'std::vector<int>'.
+ //
+ // The passed argument refers to the attribute instance passed to the list
+ // generator.
+ template <>
+ struct begin_container<client::embedded_container const>
+ {
+ static client::embedded_container::iterator
+ call(client::embedded_container const& d)
+ {
+ return d.data.begin();
+ }
+ };
+
+ template <>
+ struct end_container<client::embedded_container const>
+ {
+ static client::embedded_container::iterator
+ call(client::embedded_container const& d)
+ {
+ return d.data.end();
+ }
+ };
+}}}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ //[customize_karma_embedded_container
+ client::embedded_container d1; // create some test data
+ d1.data.push_back(1);
+ d1.data.push_back(2);
+ d1.data.push_back(3);
+
+ // use the instance of an 'client::embedded_container' instead of a
+ // STL vector
+ std::cout << karma::format(karma::int_ % ", ", d1) << std::endl; // prints: '1, 2, 3'
+ //]
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/customize_use_as_container.cpp b/src/boost/libs/spirit/example/karma/customize_use_as_container.cpp
new file mode 100644
index 00000000..c0116c8a
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/customize_use_as_container.cpp
@@ -0,0 +1,164 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 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>
+
+//[customize_karma_use_as_container_includes
+#include <boost/spirit/include/karma.hpp>
+#include <iostream>
+#include <string>
+#include <vector>
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[customize_karma_use_as_container_data
+namespace client
+{
+ struct use_as_container
+ {
+ // Expose a pair holding a pointer to the use_as_container and to the
+ // current element as our iterator.
+ // We intentionally leave out having it a 'operator==()' to demonstrate
+ // the use of the 'compare_iterators' customization point.
+ struct iterator
+ {
+ iterator(use_as_container const* container, int const* current)
+ : container_(container), current_(current)
+ {}
+
+ use_as_container const* container_;
+ int const* current_;
+ };
+
+ // expose 'int' as the type of each generated element
+ typedef int type;
+
+ use_as_container(int value1, int value2, int value3)
+ : value1_(value1), value2_(value2), value3_(value3)
+ {}
+
+ int value1_;
+ std::string dummy1_; // insert some unrelated data
+ int value2_;
+ std::string dummy2_; // insert some more unrelated data
+ int value3_;
+ };
+}
+//]
+
+//[customize_karma_use_as_container_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+//
+// Note that all templates below are specialized using the 'const' type.
+// This is necessary as all attributes in Karma are 'const'.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'is_container<>' will tell the
+ // library to treat the type 'client::use_as_container' as a
+ // container holding the items to generate output from.
+ template <>
+ struct is_container<client::use_as_container const>
+ : mpl::true_
+ {};
+
+ // The specialization of the template 'container_iterator<>' will be
+ // invoked by the library to evaluate the iterator type to be used
+ // for iterating the data elements in the container. We simply return
+ // the type of the iterator exposed by the embedded 'std::vector<int>'.
+ template <>
+ struct container_iterator<client::use_as_container const>
+ {
+ typedef client::use_as_container::iterator type;
+ };
+
+ // The specialization of the templates 'begin_container<>' and
+ // 'end_container<>' below will be used by the library to get the iterators
+ // pointing to the begin and the end of the data to generate output from.
+ //
+ // The passed argument refers to the attribute instance passed to the list
+ // generator.
+ template <>
+ struct begin_container<client::use_as_container const>
+ {
+ static client::use_as_container::iterator
+ call(client::use_as_container const& c)
+ {
+ return client::use_as_container::iterator(&c, &c.value1_);
+ }
+ };
+
+ template <>
+ struct end_container<client::use_as_container const>
+ {
+ static client::use_as_container::iterator
+ call(client::use_as_container const& c)
+ {
+ return client::use_as_container::iterator(&c, (int const*)0);
+ }
+ };
+}}}
+//]
+
+//[customize_karma_use_as_container_iterator_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'deref_iterator<>' will be used to
+ // dereference the iterator associated with our counter data structure.
+ template <>
+ struct deref_iterator<client::use_as_container::iterator>
+ {
+ typedef client::use_as_container::type type;
+
+ static type call(client::use_as_container::iterator const& it)
+ {
+ return *it.current_;
+ }
+ };
+
+ template <>
+ struct next_iterator<client::use_as_container::iterator>
+ {
+ static void call(client::use_as_container::iterator& it)
+ {
+ if (it.current_ == &it.container_->value1_)
+ it.current_ = &it.container_->value2_;
+ else if (it.current_ == &it.container_->value2_)
+ it.current_ = &it.container_->value3_;
+ else
+ it.current_ = 0;
+ }
+ };
+
+ template <>
+ struct compare_iterators<client::use_as_container::iterator>
+ {
+ static bool call(client::use_as_container::iterator const& it1
+ , client::use_as_container::iterator const& it2)
+ {
+ return it1.current_ == it2.current_ &&
+ it1.container_ == it2.container_;
+ }
+ };
+}}}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ //[customize_karma_use_as_container
+ client::use_as_container d2 (1, 2, 3);
+ // use the instance of a 'client::use_as_container' instead of a STL vector
+ std::cout << karma::format(karma::int_ % ", ", d2) << std::endl; // prints: '1, 2, 3'
+ //]
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/escaped_string.cpp b/src/boost/libs/spirit/example/karma/escaped_string.cpp
new file mode 100644
index 00000000..f3c2fe6f
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/escaped_string.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The purpose of this example is to show how any character sequence can be
+// printed while being properly quoted.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+
+ template <typename OutputIterator>
+ struct escaped_string
+ : karma::grammar<OutputIterator, std::string(char const*)>
+ {
+ escaped_string()
+ : escaped_string::base_type(esc_str)
+ {
+ esc_char.add('\a', "\\a")('\b', "\\b")('\f', "\\f")('\n', "\\n")
+ ('\r', "\\r")('\t', "\\t")('\v', "\\v")('\\', "\\\\")
+ ('\'', "\\\'")('\"', "\\\"")
+ ;
+
+ esc_str = karma::lit(karma::_r1)
+ << *(esc_char | karma::print | "\\x" << karma::hex)
+ << karma::lit(karma::_r1)
+ ;
+ }
+
+ karma::rule<OutputIterator, std::string(char const*)> esc_str;
+ karma::symbols<char, char const*> esc_char;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::back_insert_iterator<std::string> sink_type;
+
+ std::string generated;
+ sink_type sink(generated);
+
+ std::string str("string to escape: \n\r\t\"'\x19");
+ char const* quote = "'''";
+
+ client::escaped_string<sink_type> g;
+ if (!karma::generate(sink, g(quote), str))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/generate_code.cpp b/src/boost/libs/spirit/example/karma/generate_code.cpp
new file mode 100644
index 00000000..3a409a77
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/generate_code.cpp
@@ -0,0 +1,80 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Several small snippets generating different C++ code constructs
+//
+// [ HK October 08, 2009 ] Spirit V2.2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+ namespace phoenix = boost::phoenix;
+
+ // create for instance: int name[5] = { 1, 2, 3, 4, 5 };
+ template <typename Iterator>
+ struct int_array : karma::grammar<Iterator, std::vector<int>()>
+ {
+ int_array(char const* name) : int_array::base_type(start)
+ {
+ using karma::int_;
+ using karma::uint_;
+ using karma::eol;
+ using karma::lit;
+ using karma::_val;
+ using karma::_r1;
+
+ start = array_def(phoenix::size(_val)) << " = " << initializer
+ << ';' << eol;
+ array_def = "int " << lit(name) << "[" << uint_(_r1) << "]";
+ initializer = "{ " << -(int_ % ", ") << " }";
+ }
+
+ karma::rule<Iterator, void(unsigned)> array_def;
+ karma::rule<Iterator, std::vector<int>()> initializer;
+ karma::rule<Iterator, std::vector<int>()> start;
+ };
+
+ typedef std::back_insert_iterator<std::string> iterator_type;
+ bool generate_array(char const* name, std::vector<int> const& v)
+ {
+ std::string generated;
+ iterator_type sink(generated);
+ int_array<iterator_type> g(name);
+ if (karma::generate(sink, g, v))
+ {
+ std::cout << generated;
+ return true;
+ }
+ return false;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ // generate an array of integers with initializers
+ std::vector<int> v;
+ v.push_back(1);
+ v.push_back(2);
+ v.push_back(3);
+ v.push_back(4);
+ client::generate_array("array1", v);
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/key_value_sequence.cpp b/src/boost/libs/spirit/example/karma/key_value_sequence.cpp
new file mode 100644
index 00000000..db2de2cc
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/key_value_sequence.cpp
@@ -0,0 +1,74 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The main purpose of this example is to show how we can generate output from
+// a container holding key/value pairs.
+//
+// For more information see here: http://spirit.sourceforge.net/home/?p=400
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_stream.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+#include <algorithm>
+#include <cstdlib>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::pair<std::string, boost::optional<std::string> > pair_type;
+
+ template <typename OutputIterator>
+ struct keys_and_values
+ : karma::grammar<OutputIterator, std::vector<pair_type>()>
+ {
+ keys_and_values()
+ : keys_and_values::base_type(query)
+ {
+ query = pair << *('&' << pair);
+ pair = karma::string << -('=' << karma::string);
+ }
+
+ karma::rule<OutputIterator, std::vector<pair_type>()> query;
+ karma::rule<OutputIterator, pair_type()> pair;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::vector<client::pair_type>::value_type value_type;
+ typedef std::back_insert_iterator<std::string> sink_type;
+
+ std::vector<client::pair_type> v;
+ v.push_back(value_type("key1", boost::optional<std::string>("value1")));
+ v.push_back(value_type("key2", boost::optional<std::string>()));
+ v.push_back(value_type("key3", boost::optional<std::string>("")));
+
+ std::string generated;
+ sink_type sink(generated);
+ client::keys_and_values<sink_type> g;
+ if (!karma::generate(sink, g, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/mini_xml_karma.cpp b/src/boost/libs/spirit/example/karma/mini_xml_karma.cpp
new file mode 100644
index 00000000..596fd78c
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/mini_xml_karma.cpp
@@ -0,0 +1,222 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A mini XML-like parser, Karma is used to print out the generated AST
+//
+// [ JDG March 25, 2007 ] spirit2
+// [ HK April 02, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+namespace fusion = boost::fusion;
+namespace phoenix = boost::phoenix;
+
+using phoenix::at_c;
+using phoenix::push_back;
+
+///////////////////////////////////////////////////////////////////////////////
+// Our mini XML tree representation
+///////////////////////////////////////////////////////////////////////////////
+struct mini_xml;
+
+typedef
+ boost::variant<
+ boost::recursive_wrapper<mini_xml>
+ , std::string
+ >
+mini_xml_node;
+
+struct mini_xml
+{
+ std::string name; // tag name
+ std::vector<mini_xml_node> children; // children
+};
+
+// We need to tell fusion about our mini_xml struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(
+ mini_xml,
+ (std::string, name)
+ (std::vector<mini_xml_node>, children)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// Our mini XML grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct mini_xml_parser :
+ qi::grammar<Iterator, mini_xml(), space_type>
+{
+ mini_xml_parser() : mini_xml_parser::base_type(xml)
+ {
+ text = lexeme[+(char_ - '<') [_val += _1]];
+ node = (xml | text) [_val = _1];
+
+ start_tag =
+ '<'
+ >> !lit('/')
+ >> lexeme[+(char_ - '>') [_val += _1]]
+ >> '>'
+ ;
+
+ end_tag =
+ "</"
+ >> lit(_r1)
+ >> '>'
+ ;
+
+ xml =
+ start_tag [at_c<0>(_val) = _1]
+ >> *node [push_back(at_c<1>(_val), _1)]
+ >> end_tag(at_c<0>(_val))
+ ;
+ }
+
+ qi::rule<Iterator, mini_xml(), space_type> xml;
+ qi::rule<Iterator, mini_xml_node(), space_type> node;
+ qi::rule<Iterator, std::string(), space_type> text;
+ qi::rule<Iterator, std::string(), space_type> start_tag;
+ qi::rule<Iterator, void(std::string), space_type> end_tag;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// A couple of phoenix functions helping to access the elements of the
+// generated AST
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+struct get_element
+{
+ template <typename T1>
+ struct result { typedef T const& type; };
+
+ T const& operator()(mini_xml_node const& node) const
+ {
+ return boost::get<T>(node);
+ }
+};
+
+phoenix::function<get_element<std::string> > _string;
+phoenix::function<get_element<mini_xml> > _xml;
+
+///////////////////////////////////////////////////////////////////////////////
+// The output grammar defining the format of the generated data
+///////////////////////////////////////////////////////////////////////////////
+template <typename OutputIterator>
+struct mini_xml_generator
+ : karma::grammar<OutputIterator, mini_xml()>
+{
+ mini_xml_generator() : mini_xml_generator::base_type(xml)
+ {
+ node %= string | xml;
+ xml =
+ '<' << string[_1 = at_c<0>(_val)] << '>'
+ << (*node)[_1 = at_c<1>(_val)]
+ << "</" << string[_1 = at_c<0>(_val)] << '>'
+ ;
+ }
+
+ karma::rule<OutputIterator, mini_xml()> xml;
+ karma::rule<OutputIterator, mini_xml_node()> node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string storage; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(storage));
+
+ typedef mini_xml_parser<std::string::const_iterator> mini_xml_parser;
+ mini_xml_parser xmlin; // Our grammar definition
+ mini_xml ast; // our tree
+
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = qi::phrase_parse(iter, end, xmlin, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+
+ typedef std::back_insert_iterator<std::string> outiter_type;
+ typedef mini_xml_generator<outiter_type> mini_xml_generator;
+
+ mini_xml_generator xmlout; // Our grammar definition
+
+ std::string generated;
+ outiter_type outit(generated);
+ bool r = karma::generate(outit, xmlout, ast);
+
+ if (r)
+ std::cout << generated << std::endl;
+ return 0;
+ }
+ else
+ {
+ std::string::const_iterator begin = storage.begin();
+ std::size_t dist = std::distance(begin, iter);
+ std::string::const_iterator some =
+ iter + (std::min)(storage.size()-dist, std::size_t(30));
+ std::string context(iter, some);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << context << "...\"\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_list1.cpp b/src/boost/libs/spirit/example/karma/num_list1.cpp
new file mode 100644
index 00000000..7b079b04
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_list1.cpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator for a comma separated list of numbers.
+// No actions. It is based on the example qi/num_lists.cpp for reading in
+// some numbers to generate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace karma = boost::spirit::karma;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser, please see the example qi/numlist1.cpp for
+ // more information
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::list<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using ascii::space;
+
+ bool r = phrase_parse(first, last, double_ >> *(',' >> double_), space, v);
+ if (first != last)
+ return false;
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_numlist1
+ template <typename OutputIterator>
+ bool generate_numbers(OutputIterator& sink, std::list<double> const& v)
+ {
+ using karma::double_;
+ using karma::generate_delimited;
+ using ascii::space;
+
+ bool r = generate_delimited(
+ sink, // destination: output iterator
+ double_ << *(',' << double_), // the generator
+ space, // the delimiter-generator
+ v // the data to output
+ );
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::list<double> v; // here we put the data to generate
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ // ok, we got some numbers, now print them back out
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_numbers(sink, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_list2.cpp b/src/boost/libs/spirit/example/karma/num_list2.cpp
new file mode 100644
index 00000000..ce16fafe
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_list2.cpp
@@ -0,0 +1,117 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator for a comma separated list of numbers.
+// No actions. It is based on the example qi/num_lists.cpp for reading in
+// some numbers to generate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser, please see the example qi/numlist1.cpp for
+ // more information
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+
+ bool r = phrase_parse(first, last, double_ % ',', space, v);
+ if (first != last)
+ return false;
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_numlist2
+ template <typename OutputIterator, typename Container>
+ bool generate_numbers(OutputIterator& sink, Container const& v)
+ {
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::generate_delimited;
+ using boost::spirit::ascii::space;
+
+ bool r = generate_delimited(
+ sink, // destination: output iterator
+ double_ % ',', // the generator
+ space, // the delimiter-generator
+ v // the data to output
+ );
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v; // here we put the data to generate
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ // ok, we got some numbers, now print them back out
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_numbers(sink, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_list3.cpp b/src/boost/libs/spirit/example/karma/num_list3.cpp
new file mode 100644
index 00000000..253de1b4
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_list3.cpp
@@ -0,0 +1,150 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator for a comma separated list of numbers.
+// No actions. It is based on the example qi/num_lists.cpp for reading in
+// some numbers to generate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser, please see the example qi/numlist1.cpp for
+ // more information
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+
+ bool r = phrase_parse(first, last, double_ % ',', space, v);
+ if (first != last)
+ return false;
+ return r;
+ }
+
+ //[tutorial_karma_numlist3_complex
+ // a simple complex number representation z = a + bi
+ struct complex
+ {
+ complex (double a, double b = 0.0) : a(a), b(b) {}
+
+ double a;
+ double b;
+ };
+
+ // the streaming operator for the type complex
+ std::ostream&
+ operator<< (std::ostream& os, complex const& z)
+ {
+ os << "{" << z.a << "," << z.b << "}";
+ return os;
+ }
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_numlist3
+ template <typename OutputIterator, typename Container>
+ bool generate_numbers(OutputIterator& sink, Container const& v)
+ {
+ using boost::spirit::karma::stream;
+ using boost::spirit::karma::generate;
+ using boost::spirit::karma::eol;
+
+ bool r = generate(
+ sink, // destination: output iterator
+ stream % eol, // the generator
+ v // the data to output
+ );
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\tA comma separated list generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v; // here we put the data gotten from input
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ // ok, we got some numbers, fill a vector of client::complex
+ // instances and print them back out
+ std::vector<client::complex> vc;
+ std::vector<double>::const_iterator end = v.end();
+ for (std::vector<double>::const_iterator it = v.begin();
+ it != end; ++it)
+ {
+ double real(*it);
+ if (++it != end)
+ vc.push_back(client::complex(real, *it));
+ else {
+ vc.push_back(client::complex(real));
+ break;
+ }
+ }
+
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_numbers(sink, vc))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated:\n" << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_matrix.cpp b/src/boost/libs/spirit/example/karma/num_matrix.cpp
new file mode 100644
index 00000000..0622e096
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_matrix.cpp
@@ -0,0 +1,114 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator formatting and printing a matrix
+// of integers taken from a simple vector of vectors. The size and the
+// contents of the printed matrix is generated randomly.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <ctime>
+
+namespace karma = boost::spirit::karma;
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our matrix generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_nummatrix_grammar
+ template <typename OutputIterator>
+ struct matrix_grammar
+ : karma::grammar<OutputIterator, std::vector<std::vector<int> >()>
+ {
+ matrix_grammar()
+ : matrix_grammar::base_type(matrix)
+ {
+ using karma::int_;
+ using karma::right_align;
+ using karma::eol;
+
+ element = right_align(10)[int_];
+ row = '|' << *element << '|';
+ matrix = row % eol;
+ }
+
+ karma::rule<OutputIterator, std::vector<std::vector<int> >()> matrix;
+ karma::rule<OutputIterator, std::vector<int>()> row;
+ karma::rule<OutputIterator, int()> element;
+ };
+ //]
+
+ //[tutorial_karma_nummatrix
+ template <typename OutputIterator>
+ bool generate_matrix(OutputIterator& sink
+ , std::vector<std::vector<int> > const& v)
+ {
+ matrix_grammar<OutputIterator> matrix;
+ return karma::generate(
+ sink, // destination: output iterator
+ matrix, // the generator
+ v // the data to output
+ );
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\tPrinting integers in a matrix using Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ // here we put the data to generate
+ std::vector<std::vector<int> > v;
+
+ // now, generate the size and the contents for the matrix
+ std::srand((unsigned int)std::time(NULL));
+ std::size_t rows = std::rand() / (RAND_MAX / 10);
+ std::size_t columns = std::rand() / (RAND_MAX / 10);
+
+ v.resize(rows);
+ for (std::size_t row = 0; row < rows; ++row)
+ {
+ v[row].resize(columns);
+ std::generate(v[row].begin(), v[row].end(), std::rand);
+ }
+
+ // ok, we got the matrix, now print it out
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_matrix(sink, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated:\n" << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/printf_style_double_format.cpp b/src/boost/libs/spirit/example/karma/printf_style_double_format.cpp
new file mode 100644
index 00000000..b1c094da
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/printf_style_double_format.cpp
@@ -0,0 +1,282 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The main purpose of this example is to show how a single container type can
+// be formatted using different output grammars.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <cmath>
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+// This policy allows to use printf style formatting specifiers for Karma
+// floating point generators. This policy understands the following format:
+//
+// The format string must conform to the following format, otherwise a
+// std::runtime_error will be thrown:
+//
+// %[flags][fill][width][.precision]type
+//
+// where:
+// flags (only one possible):
+// +: Always denote the sign '+' or '-' of a number
+// -: Left-align the output
+// fill:
+// 0: Uses 0 instead of spaces to left-fill a fixed-length field
+// width:
+// number: Left-pad the output with spaces until it is at least number
+// characters wide. if number has a leading '0', that is
+// interpreted as a 'fill', the padding is done with '0'
+// characters instead of spaces.
+// precision:
+// number: Causes the decimal portion of the output to be expressed
+// in at least number digits
+// type (only one possible):
+// e: force scientific notation, with a lowercase "e"
+// E: force scientific notation, with a uppercase "E"
+// f: floating point format
+// g: use %e or %f, whichever is shorter
+// G: use %E or %f, whichever is shorter
+//
+
+///////////////////////////////////////////////////////////////////////////////
+// define a data structure and a corresponding parser to hold the formatting
+// information extracted from the format specification string
+namespace client
+{
+ struct format_data
+ {
+ char flag;
+ char fill;
+ int width;
+ int precision;
+ char type;
+ };
+}
+
+// We need to tell fusion about our format_data struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(
+ client::format_data,
+ (char, flag)
+ (char, fill)
+ (int, width)
+ (int, precision)
+ (char, type)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Grammar for format specification string as described above
+ template <typename Iterator>
+ struct format_grammar : qi::grammar<Iterator, format_data()>
+ {
+ format_grammar() : format_grammar::base_type(format)
+ {
+ using qi::uint_;
+ using qi::attr;
+ using ascii::char_;
+ using ascii::no_case;
+
+ format %= '%' >> flags >> fill >> width >> prec >> type;
+
+ // default flags is right aligned
+ flags = char_('+') | char_('-') | attr(' ');
+ fill = char_('0') | attr(' '); // default fill is space
+ width = uint_ | attr(-1);
+ prec = '.' >> uint_ | attr(3); // default is 3 digits
+ type = no_case[char_('e')] | char_('f') | no_case[char_('g')];
+ };
+
+ qi::rule<Iterator, format_data()> format;
+ qi::rule<Iterator, char()> flags;
+ qi::rule<Iterator, char()> fill;
+ qi::rule<Iterator, int()> width;
+ qi::rule<Iterator, int()> prec;
+ qi::rule<Iterator, char()> type;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// real_policies implementation allowing to use a printf style format
+// specification for Karma floating pointing number generators
+template <typename T>
+struct format_policies : karma::real_policies<T>
+{
+ typedef karma::real_policies<T> base_policy_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // This real_policies implementation requires the output_iterator to
+ // implement buffering and character counting. This needs to be reflected
+ // in the properties exposed by the generator
+ typedef boost::mpl::int_<
+ karma::generator_properties::countingbuffer
+ > properties;
+
+ ///////////////////////////////////////////////////////////////////////////
+ format_policies(char const* fmt = "%f")
+ {
+ char const* last = fmt;
+ while (*last)
+ last++;
+
+ client::format_grammar<char const*> g;
+ if (!qi::parse(fmt, last, g, format_))
+ throw std::runtime_error("bad format string");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // returns the overall format: scientific or fixed
+ int floatfield(T n) const
+ {
+ if (format_.type == 'e' || format_.type == 'E')
+ return base_policy_type::fmtflags::scientific;
+
+ if (format_.type == 'f')
+ return base_policy_type::fmtflags::fixed;
+
+ BOOST_ASSERT(format_.type == 'g' || format_.type == 'G');
+ return this->base_policy_type::floatfield(n);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // returns whether to emit a sign even for non-negative numbers
+ bool const force_sign(T) const
+ {
+ return format_.flag == '+';
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // returns the number of required digits for the fractional part
+ unsigned precision(T) const
+ {
+ return format_.precision;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // emit the decimal dot
+ template <typename OutputIterator>
+ static bool dot (OutputIterator& sink, T n, unsigned precision)
+ {
+ // don't print the dot if no fractional digits are to be emitted
+ if (precision == 0)
+ return true;
+ return base_policy_type::dot(sink, n, precision);
+ }
+
+ template <typename CharEncoding, typename Tag, typename OutputIterator>
+ bool exponent (OutputIterator& sink, long n) const
+ {
+ if (format_.type == 'E' || format_.type == 'G') {
+ // print exponent symbol in upper case
+ return this->base_policy_type::
+ template exponent<char_encoding::ascii, tag::upper>(sink, n);
+ }
+ return this->base_policy_type::
+ template exponent<CharEncoding, Tag>(sink, n);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // this gets called by the numeric generators at the top level, it allows
+ // to do alignment and other high level things
+ template <typename Inserter, typename OutputIterator, typename Policies>
+ bool call (OutputIterator& sink, T n, Policies const& p) const
+ {
+ bool r = false;
+ if (format_.flag == '-') { // left align
+ // wrap the given output iterator to allow counting
+ karma::detail::enable_counting<OutputIterator> counting(sink);
+
+ // first generate the actual floating point number
+ r = Inserter::call_n(sink, n, p);
+
+ // pad the output until the max width is reached
+ while(r && int(counting.count()) < format_.width)
+ r = karma::generate(sink, ' ');
+ }
+ else { // right align
+ // wrap the given output iterator to allow left padding
+ karma::detail::enable_buffering<OutputIterator> buffering(
+ sink, format_.width);
+
+ // first generate the actual floating point number
+ {
+ karma::detail::disable_counting<OutputIterator> nocounting(sink);
+ r = Inserter::call_n(sink, n, p);
+ }
+
+ buffering.disable(); // do not perform buffering any more
+
+ // generate the left padding
+ karma::detail::enable_counting<OutputIterator> counting(
+ sink, buffering.buffer_size());
+ while(r && int(counting.count()) < format_.width)
+ r = karma::generate(sink, format_.fill);
+
+ // copy the buffered output to the target output iterator
+ if (r)
+ buffering.buffer_copy();
+ }
+ return r;
+ }
+
+ client::format_data format_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// This is the generator usable in any Karma output format expression, it needs
+// to be utilized as
+//
+// generate(sink, real("%6.3f"), 3.1415926536); // prints: ' 3.142'
+//
+// and it supports the format specification as described above.
+typedef karma::real_generator<double, format_policies<double> > real;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////////\n\n";
+ std::cout << "A format driven floating point number generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a printf style format\n";
+ std::cout << "Type [enter] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+
+ try {
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!karma::generate(sink, real(str.c_str()), 4*std::atan(1.0)))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << ">" << generated << "<\n";
+ }
+ }
+ catch (std::runtime_error const&) {
+ std::cout << "-------------------------\n";
+ std::cout << "Invalid format specified!\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/quick_start1.cpp b/src/boost/libs/spirit/example/karma/quick_start1.cpp
new file mode 100644
index 00000000..4a99b95c
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/quick_start1.cpp
@@ -0,0 +1,119 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The main purpose of this example is to show how a single container type can
+// be formatted using different output grammars.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_stream.hpp>
+
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <cstdlib>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // vector
+ std::vector<int> v (8);
+ std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector
+
+ std::cout << "Output 8 integers from a std::vector<int>..." << std::endl;
+
+ // output the container as a sequence without any separation
+ std::cout << "...without any separation" << std::endl;
+ std::cout <<
+ karma::format(
+ *int_, // format description
+ v // data
+ ) << std::endl << std::endl;
+
+ // output the container as a space separated sequence
+ std::cout << "...as space delimited list" << std::endl;
+ std::cout <<
+ karma::format_delimited(
+ *int_, // format description
+ space, // delimiter
+ v // data
+ ) << std::endl << std::endl;
+
+ std::cout <<
+ karma::format_delimited(
+ '[' << *int_ << ']', // format description
+ space, // delimiter
+ v // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list
+ std::cout << "...as comma separated list" << std::endl;
+ std::cout <<
+ karma::format(
+ int_ % ", ", // format description
+ v // data
+ ) << std::endl << std::endl;
+
+ std::cout <<
+ karma::format(
+ '[' << (int_ % ", ") << ']', // format description
+ v // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list of double's
+ std::cout << "...as comma separated list of doubles" << std::endl;
+ std::cout <<
+ karma::format(
+ double_ % ", ", // format description
+ v // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list of items enclosed in '()'
+ std::cout << "..as list of ints enclosed in '()'" << std::endl;
+ std::cout <<
+ karma::format(
+ ('(' << int_ << ')') % ", ", // format description
+ v // data
+ ) << std::endl << std::endl;
+
+ std::cout <<
+ karma::format(
+ '[' << (
+ ('(' << int_ << ')') % ", "
+ ) << ']', // format description
+ v // data
+ ) << std::endl << std::endl;
+
+ // output the container as a HTML list
+ std::cout << "...as HTML bullet list" << std::endl;
+ std::cout <<
+ karma::format_delimited(
+ "<ol>" <<
+ // no delimiting within verbatim
+ *verbatim[" <li>" << int_ << "</li>"]
+ << "</ol>", // format description
+ '\n', // delimiter
+ v // data
+ ) << std::endl;
+
+ // output the container as right aligned column
+ std::cout << "...right aligned in a column" << std::endl;
+ std::cout <<
+ karma::format_delimited(
+ *verbatim[
+ "|" << right_align[int_] << "|"
+ ], // format description
+ '\n', // delimiter
+ v // data
+ ) << std::endl;
+
+ std::cout << std::endl;
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/quoted_strings.cpp b/src/boost/libs/spirit/example/karma/quoted_strings.cpp
new file mode 100644
index 00000000..ecbdd969
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/quoted_strings.cpp
@@ -0,0 +1,70 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The purpose of this example is to demonstrate how to utilize alternatives
+// and the built in matching capabilities of Karma generators to emit output
+// in different formats based on the content of an attribute (not its type).
+
+#include <boost/config/warning_disable.hpp>
+
+#include <string>
+#include <vector>
+
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+ namespace phx = boost::phoenix;
+
+ template <typename OutputIterator>
+ struct quoted_strings
+ : karma::grammar<OutputIterator, std::vector<std::string>()>
+ {
+ quoted_strings()
+ : quoted_strings::base_type(strings)
+ {
+ strings = (bareword | qstring) % ' ';
+ bareword = karma::repeat(phx::size(karma::_val))
+ [ karma::alnum | karma::char_("-.,_$") ];
+ qstring = '"' << karma::string << '"';
+ }
+
+ karma::rule<OutputIterator, std::vector<std::string>()> strings;
+ karma::rule<OutputIterator, std::string()> bareword, qstring;
+ };
+}
+
+int main()
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::back_insert_iterator<std::string> sink_type;
+
+ std::string generated;
+ sink_type sink(generated);
+
+ std::vector<std::string> v;
+ v.push_back("foo");
+ v.push_back("bar baz");
+ v.push_back("hello");
+
+ client::quoted_strings<sink_type> g;
+ if (!karma::generate(sink, g, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/reference.cpp b/src/boost/libs/spirit/example/karma/reference.cpp
new file mode 100644
index 00000000..dd11f26e
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/reference.cpp
@@ -0,0 +1,911 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 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/support_utree.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');
+ //]
+ }
+
+ // as
+ {
+ //[reference_karma_using_declarations_as
+ using boost::spirit::utree;
+ using boost::spirit::utree_type;
+ using boost::spirit::utf8_symbol_type;
+ using boost::spirit::karma::as;
+ using boost::spirit::karma::as_string;
+ using boost::spirit::karma::char_;
+ using boost::spirit::karma::double_;
+ //]
+
+ //[reference_karma_as
+ /*`To properly handle string concatenation with __utree__, we
+ make use of `as_string[]`. We also use `as<T>` to explicitly extract
+ a __utree__ symbol node.*/
+
+ typedef as<utf8_symbol_type> as_symbol_type;
+ as_symbol_type const as_symbol = as_symbol_type();
+
+ utree ut;
+ ut.push_back("xyz");
+ ut.push_back(1.23);
+
+ test_generator_attr("xyz1.23", as_string[*char_] << double_, ut);
+ test_generator_attr("xyz1.23", as<std::string>()[*char_] << double_, ut);
+
+ ut.clear();
+
+ ut.push_back(utf8_symbol_type("xyz"));
+ ut.push_back(1.23);
+
+ test_generator_attr("xyz1.23", as_symbol[*char_] << double_, ut);
+ test_generator_attr("xyz1.23", as<utf8_symbol_type>()[*char_] << double_, ut);
+ //]
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/reorder_struct.cpp b/src/boost/libs/spirit/example/karma/reorder_struct.cpp
new file mode 100644
index 00000000..8e5b0149
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/reorder_struct.cpp
@@ -0,0 +1,105 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The main purpose of this example is to show how a single fusion sequence
+// can be used to generate output of the elements in different sequences
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/struct.hpp>
+#include <boost/fusion/include/nview.hpp>
+#include <boost/assign/std/vector.hpp>
+
+namespace fusion = boost::fusion;
+namespace karma = boost::spirit::karma;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ // Our employee struct
+ struct employee
+ {
+ std::string surname;
+ std::string forename;
+ int age;
+ double salary;
+ std::string department;
+ };
+
+ // define iterator type
+ typedef std::back_insert_iterator<std::string> iterator_type;
+
+ // This is the output routine taking a format description and the data to
+ // print
+ template <typename Generator, typename Sequence>
+ void generate(Generator const& g, Sequence const& s)
+ {
+ std::string generated;
+ iterator_type sink(generated);
+ karma::generate(sink, g, s);
+ std::cout << generated << std::endl;
+ }
+}
+
+// We need to tell fusion about our employee struct to make it a first-class
+// fusion citizen. This has to be in global scope. Note that we don't need to
+// list the members of our struct in the same sequence a they are defined
+BOOST_FUSION_ADAPT_STRUCT(
+ client::employee,
+ (int, age)
+ (std::string, surname)
+ (std::string, forename)
+ (std::string, department)
+ (double, salary)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::string str;
+
+ // some employees
+ client::employee john = { "John", "Smith", 25, 2000.50, "Sales" };
+ client::employee mary = { "Mary", "Higgins", 23, 2200.36, "Marketing" };
+ client::employee tom = { "Tom", "Taylor", 48, 3200.00, "Boss" };
+
+ // print data about employees in different formats
+ {
+ // print forename and age
+ client::generate(
+ karma::string << ", " << karma::int_,
+ fusion::as_nview<2, 0>(john));
+
+ // print surname, forename, and salary
+ client::generate(
+ karma::string << ' ' << karma::string << ": " << karma::double_,
+ fusion::as_nview<1, 2, 4>(mary));
+
+ // print forename, age, and department
+ client::generate(
+ karma::string << ": " << karma::int_ << " (" << karma::string << ')',
+ fusion::as_nview<2, 0, 3>(tom));
+ }
+
+ // now make a list of all employees and print them all
+ std::vector<client::employee> employees;
+ {
+ using namespace boost::assign;
+ employees += john, mary, tom;
+ }
+
+ // print surname, forename, and salary for all employees
+ {
+ typedef
+ fusion::result_of::as_nview<client::employee const, 1, 2, 4>::type
+ names_and_salary;
+
+ karma::rule<client::iterator_type, names_and_salary()> r =
+ karma::string << ' ' << karma::string << ": " << karma::double_;
+
+ client::generate(r % karma::eol, employees);
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/simple_columns_directive.cpp b/src/boost/libs/spirit/example/karma/simple_columns_directive.cpp
new file mode 100644
index 00000000..3a5348af
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/simple_columns_directive.cpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+// The purpose of this example is to show how a simple custom generator
+// directive can be written. We develop a custom generator allowing to wrap
+// the generated output after each 5th column.
+//
+// For more information see: http://boost-spirit.com/home/?page_id=659
+
+#include <boost/spirit/include/karma_generate_attr.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+
+#include <string>
+#include "simple_columns_directive.hpp"
+
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ using custom_generator::columns;
+
+ std::vector<int> v;
+ for (int i = 0; i < 17; ++i)
+ v.push_back(i);
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+
+ bool result = karma::generate_delimited(
+ sink, columns[*karma::int_], karma::space, v);
+ if (result)
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Generation succeeded\n";
+ std::cout << "generated output: " << "\n" << generated << "\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Generation failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/simple_columns_directive.hpp b/src/boost/libs/spirit/example/karma/simple_columns_directive.hpp
new file mode 100644
index 00000000..56403f33
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/simple_columns_directive.hpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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)
+
+#if !defined(COLUMNS_DEC_05_2009_0716PM)
+#define COLUMNS_DEC_05_2009_0716PM
+
+#include <boost/spirit/include/karma_generate.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// definition the place holder
+namespace custom_generator
+{
+ BOOST_SPIRIT_TERMINAL(columns)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation the enabler
+namespace boost { namespace spirit
+{
+ // We want custom_generator::columns to be usable as a directive only,
+ // and only for generator expressions (karma::domain).
+ template <>
+ struct use_directive<karma::domain, custom_generator::tag::columns>
+ : mpl::true_ {};
+}}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation of the generator
+namespace custom_generator
+{
+ // special delimiter wrapping the original one while additionally emitting
+ // the column delimiter after each 5th invocation
+ template <typename Delimiter>
+ struct columns_delimiter
+ {
+ columns_delimiter(Delimiter const& delim)
+ : delimiter(delim), count(0) {}
+
+ // This function is called during the actual delimiter output
+ template <typename OutputIterator, typename Context
+ , typename Delimiter_, typename Attribute>
+ bool generate(OutputIterator& sink, Context&, Delimiter_ const&
+ , Attribute const&) const
+ {
+ // first invoke the wrapped delimiter
+ if (!karma::delimit_out(sink, delimiter))
+ return false;
+
+ // now we count the number of invocations and emit the column
+ // delimiter after each 5th column
+ if ((++count % 5) == 0)
+ *sink++ = '\n';
+ return true;
+ }
+
+ // Generate a final column delimiter if the last invocation didn't
+ // emit one
+ template <typename OutputIterator>
+ bool final_delimit_out(OutputIterator& sink) const
+ {
+ if (count % 5)
+ *sink++ = '\n';
+ return true;
+ }
+
+ Delimiter const& delimiter; // wrapped delimiter
+ mutable unsigned int count; // invocation counter
+ };
+
+ // That's the actual columns generator
+ template <typename Subject>
+ struct simple_columns_generator
+ : boost::spirit::karma::unary_generator<
+ simple_columns_generator<Subject> >
+ {
+ // Define required output iterator properties
+ typedef typename Subject::properties properties;
+
+ // Define the attribute type exposed by this parser component
+ template <typename Context, typename Iterator>
+ struct attribute
+ : boost::spirit::traits::attribute_of<Subject, Context, Iterator>
+ {};
+
+ simple_columns_generator(Subject const& s)
+ : subject(s)
+ {}
+
+ // This function is called during the actual output generation process.
+ // It dispatches to the embedded generator while supplying a new
+ // delimiter to use, wrapping the outer delimiter.
+ template <typename OutputIterator, typename Context
+ , typename Delimiter, typename Attribute>
+ bool generate(OutputIterator& sink, Context& ctx
+ , Delimiter const& delimiter, Attribute const& attr) const
+ {
+ columns_delimiter<Delimiter> d(delimiter);
+ return subject.generate(sink, ctx, d, attr) && d.final_delimit_out(sink);
+ }
+
+ // This function is called during error handling to create
+ // a human readable string for the error context.
+ template <typename Context>
+ boost::spirit::info what(Context& ctx) const
+ {
+ return boost::spirit::info("columns", subject.what(ctx));
+ }
+
+ Subject subject;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// instantiation of the generator
+namespace boost { namespace spirit { namespace karma
+{
+ // This is the factory function object invoked in order to create
+ // an instance of our simple_columns_generator.
+ template <typename Subject, typename Modifiers>
+ struct make_directive<custom_generator::tag::columns, Subject, Modifiers>
+ {
+ typedef custom_generator::simple_columns_generator<Subject> result_type;
+
+ result_type operator()(unused_type, Subject const& s, unused_type) const
+ {
+ return result_type(s);
+ }
+ };
+}}}
+
+#endif