Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58083 - in trunk/libs/spirit: example/karma test/karma test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2009-12-01 09:35:35


Author: hkaiser
Date: 2009-12-01 09:35:34 EST (Tue, 01 Dec 2009)
New Revision: 58083
URL: http://svn.boost.org/trac/boost/changeset/58083

Log:
Spirit: added new karma example (auto_facilities.cpp), tweaks to auto_ tests
Added:
   trunk/libs/spirit/example/karma/auto_facilities.cpp (contents, props changed)
Text files modified:
   trunk/libs/spirit/example/karma/Jamfile | 1 +
   trunk/libs/spirit/example/karma/escaped_string.cpp | 2 +-
   trunk/libs/spirit/test/karma/auto.cpp | 11 +++++++++++
   trunk/libs/spirit/test/qi/auto.cpp | 11 +++++++++++
   4 files changed, 24 insertions(+), 1 deletions(-)

Modified: trunk/libs/spirit/example/karma/Jamfile
==============================================================================
--- trunk/libs/spirit/example/karma/Jamfile (original)
+++ trunk/libs/spirit/example/karma/Jamfile 2009-12-01 09:35:34 EST (Tue, 01 Dec 2009)
@@ -10,6 +10,7 @@
     ;
 
 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 ;

Added: trunk/libs/spirit/example/karma/auto_facilities.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/auto_facilities.cpp 2009-12-01 09:35:34 EST (Tue, 01 Dec 2009)
@@ -0,0 +1,243 @@
+// Copyright (c) 2001-2009 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>
+#include <boost/mpl/print.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).
+ 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;
+}
+

Modified: trunk/libs/spirit/example/karma/escaped_string.cpp
==============================================================================
--- trunk/libs/spirit/example/karma/escaped_string.cpp (original)
+++ trunk/libs/spirit/example/karma/escaped_string.cpp 2009-12-01 09:35:34 EST (Tue, 01 Dec 2009)
@@ -46,7 +46,7 @@
     std::string generated;
     sink_type sink(generated);
 
- std::string str("string to esacpe: \n\r\t\"'\x19");
+ std::string str("string to escape: \n\r\t\"'\x19");
     char const* quote = "'''";
 
     client::escaped_string<sink_type> g;

Modified: trunk/libs/spirit/test/karma/auto.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/auto.cpp (original)
+++ trunk/libs/spirit/test/karma/auto.cpp 2009-12-01 09:35:34 EST (Tue, 01 Dec 2009)
@@ -20,6 +20,7 @@
 #include "test.hpp"
 
 namespace karma = boost::spirit::karma;
+namespace traits = boost::spirit::traits;
 
 ///////////////////////////////////////////////////////////////////////////////
 template <typename Char, typename T>
@@ -28,6 +29,7 @@
     std::basic_string<Char> generated;
     std::back_insert_iterator<std::basic_string<Char> > sink(generated);
 
+ BOOST_TEST((traits::meta_create_exists<karma::domain, T>::value));
     bool result = karma::generate(sink, karma::create_generator<T>(), t);
 
     spirit_test::print_if_failed("test_create_generator", result, generated, expected);
@@ -37,6 +39,8 @@
 template <typename Char, typename Attribute>
 bool test_rule(Char const *expected, Attribute const& attr)
 {
+ BOOST_TEST((traits::meta_create_exists<karma::domain, Attribute>::value));
+
     typedef spirit_test::output_iterator<Char>::type sink_type;
     karma::rule<sink_type, Attribute()> r =
         karma::create_generator<Attribute>();
@@ -47,6 +51,8 @@
 bool test_rule_delimited(Char const *expected, Attribute const& attr
   , Delimiter const& d)
 {
+ BOOST_TEST((traits::meta_create_exists<karma::domain, Attribute>::value));
+
     typedef spirit_test::output_iterator<Char>::type sink_type;
     karma::rule<sink_type, Attribute(), Delimiter> r =
         karma::create_generator<Attribute>();
@@ -57,6 +63,11 @@
 int main()
 {
     {
+ struct my_type {};
+ BOOST_TEST((!traits::meta_create_exists<karma::domain, my_type>::value));
+ }
+
+ {
         // test primitive types
         BOOST_TEST(test_create_generator("true", true));
         BOOST_TEST(test_create_generator("1", 1));

Modified: trunk/libs/spirit/test/qi/auto.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/auto.cpp (original)
+++ trunk/libs/spirit/test/qi/auto.cpp 2009-12-01 09:35:34 EST (Tue, 01 Dec 2009)
@@ -21,6 +21,7 @@
 #include "test.hpp"
 
 namespace qi = boost::spirit::qi;
+namespace traits = boost::spirit::traits;
 
 ///////////////////////////////////////////////////////////////////////////////
 template <typename Char, typename T>
@@ -30,12 +31,15 @@
     while (*last)
         last++;
 
+ BOOST_TEST((traits::meta_create_exists<qi::domain, T>::value));
     return qi::phrase_parse(in, last, qi::create_parser<T>(), qi::space, t);
 }
 
 template <typename Char, typename Attribute>
 bool test_rule(Char const* in, Attribute const& expected)
 {
+ BOOST_TEST((traits::meta_create_exists<qi::domain, Attribute>::value));
+
     Attribute attr = Attribute();
     qi::rule<Char const*, Attribute()> r = qi::create_parser<Attribute>();
     return spirit_test::test_attr(in, r, attr) && attr == expected;
@@ -44,6 +48,8 @@
 template <typename Char, typename Attribute, typename Skipper>
 bool test_rule(Char const* in, Attribute const& expected, Skipper const& skipper)
 {
+ BOOST_TEST((traits::meta_create_exists<qi::domain, Attribute>::value));
+
     Attribute attr = Attribute();
     qi::rule<Char const*, Attribute(), Skipper> r = qi::create_parser<Attribute>();
     return spirit_test::test_attr(in, r, attr, skipper) && attr == expected;
@@ -53,6 +59,11 @@
 int main()
 {
     {
+ struct my_type {};
+ BOOST_TEST((!traits::meta_create_exists<qi::domain, my_type>::value));
+ }
+
+ {
         // test primitive types
         bool b = false;
         BOOST_TEST(test_create_parser("true", b) && b == true);


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk