$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r56534 - in trunk/libs/spirit: example/karma example/qi test test/karma test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2009-10-02 17:19:11
Author: hkaiser
Date: 2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
New Revision: 56534
URL: http://svn.boost.org/trac/boost/changeset/56534
Log:
Spirit: restructured customization points, added qi::attr_cast, added phoenix expression support for Karma attributes, updated tests
Added:
   trunk/libs/spirit/test/qi/attribute.cpp   (contents, props changed)
Removed:
   trunk/libs/spirit/test/karma/functor.cpp
Text files modified: 
   trunk/libs/spirit/example/karma/reference.cpp      |     2                                         
   trunk/libs/spirit/example/qi/reference.cpp         |     2                                         
   trunk/libs/spirit/test/CMakeLists.txt              |     1                                         
   trunk/libs/spirit/test/Jamfile                     |     1                                         
   trunk/libs/spirit/test/karma/attribute.cpp         |   119 +++++++++++++++++++++++++++++++++++---- 
   trunk/libs/spirit/test/karma/binary.cpp            |    73 ++++++++++++++++++++++++                
   trunk/libs/spirit/test/karma/bool.cpp              |    34 ++++++++++                              
   trunk/libs/spirit/test/karma/char.cpp              |    15 +++++                                   
   trunk/libs/spirit/test/karma/format_manip_attr.cpp |     4 +                                       
   trunk/libs/spirit/test/karma/int_numerics.cpp      |    11 +++                                     
   trunk/libs/spirit/test/karma/kleene.cpp            |    11 ++-                                     
   trunk/libs/spirit/test/karma/plus.cpp              |     9 +-                                      
   trunk/libs/spirit/test/karma/real_numerics.cpp     |    15 +++++                                   
   trunk/libs/spirit/test/karma/repeat.cpp            |    14 ++++                                    
   trunk/libs/spirit/test/qi/bool.cpp                 |     7 +-                                      
   trunk/libs/spirit/test/qi/grammar_fail.cpp         |    15 ++---                                   
   trunk/libs/spirit/test/qi/omit.cpp                 |    13 +---                                    
   trunk/libs/spirit/test/qi/terminal_ex.cpp          |     6 +-                                      
   18 files changed, 298 insertions(+), 54 deletions(-)
Modified: trunk/libs/spirit/example/karma/reference.cpp
==============================================================================
--- trunk/libs/spirit/example/karma/reference.cpp	(original)
+++ trunk/libs/spirit/example/karma/reference.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -135,7 +135,7 @@
     template <>
     struct transform_attribute<int, int_data const>
     {
-        static int call(int_data const& d) { return d.i; }
+        static int pre(int_data const& d) { return d.i; }
     };
 }}}
 //]
Modified: trunk/libs/spirit/example/qi/reference.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/reference.cpp	(original)
+++ trunk/libs/spirit/example/qi/reference.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -187,7 +187,7 @@
         namespace qi = boost::spirit::qi;
         if (qi::detail::string_parse("eurt", first, last, qi::unused))
         {
-            qi::detail::assign_to(false, attr);    // result is false
+            spirit::traits::assign_to(false, attr);    // result is false
             return true;
         }
         return false;
Modified: trunk/libs/spirit/test/CMakeLists.txt
==============================================================================
--- trunk/libs/spirit/test/CMakeLists.txt	(original)
+++ trunk/libs/spirit/test/CMakeLists.txt	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -22,6 +22,7 @@
 boost_test_run(qi_actions qi/actions.cpp COMPILE_FLAGS ${test_compile_flags} BOOST_LIB spirit COMPILE_FLAGS ${test_compile_flags} )
 boost_test_run(qi_alternative qi/alternative.cpp COMPILE_FLAGS ${test_compile_flags})
 boost_test_run(qi_attr qi/attr.cpp COMPILE_FLAGS ${test_compile_flags})
+boost_test_run(qi_attribute qi/attribute.cpp COMPILE_FLAGS ${test_compile_flags})
 boost_test_run(qi_and_predicate qi/and_predicate.cpp COMPILE_FLAGS ${test_compile_flags})
 boost_test_run(qi_binary qi/binary.cpp COMPILE_FLAGS ${test_compile_flags})
 boost_test_run(qi_bool qi/bool.cpp COMPILE_FLAGS ${test_compile_flags})
Modified: trunk/libs/spirit/test/Jamfile
==============================================================================
--- trunk/libs/spirit/test/Jamfile	(original)
+++ trunk/libs/spirit/test/Jamfile	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -29,6 +29,7 @@
     [ run qi/actions.cpp                    : : : : ]
     [ run qi/alternative.cpp                : : : : ]
     [ run qi/attr.cpp                       : : : : ]
+    [ run qi/attribute.cpp                  : : : : ]
     [ run qi/and_predicate.cpp              : : : : ]
     [ run qi/binary.cpp                     : : : : ]
     [ run qi/bool.cpp                       : : : : ]
Modified: trunk/libs/spirit/test/karma/attribute.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/attribute.cpp	(original)
+++ trunk/libs/spirit/test/karma/attribute.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -40,7 +40,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 // this is just a test structure we need to use in place of an int
-struct test_int_data
+struct test_int_data1
 {
     int i;
 };
@@ -49,9 +49,29 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
-    struct transform_attribute<int, test_int_data const>
+    struct transform_attribute<test_int_data1 const, int>
     {
-        static int call(test_int_data const& d) { return d.i; }
+        typedef int type;
+        static int pre(test_int_data1 const& d) { return d.i; }
+    };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+// this is another test structure we need to use in place of an int, but this
+// time we use a reference to the embedded element
+struct test_int_data2
+{
+    int i;
+};
+
+// so we provide a custom attribute transformation
+namespace boost { namespace spirit { namespace traits
+{
+    template <>
+    struct transform_attribute<test_int_data2 const, int>
+    {
+        typedef int const& type;
+        static int const& pre(test_int_data2 const& d) { return d.i; }
     };
 }}}
 
@@ -63,6 +83,7 @@
 
     test_data d1 = { "s11", "s12", 1, 2.5, "s13" };
     {
+
         BOOST_TEST(test("s121", 
             karma::string << karma::int_, 
             fusion::as_nview<2, 0>(d1)));
@@ -72,24 +93,94 @@
             fusion::as_nview<2, 0>(d1), ' '));
     }
 
-    test_data d2 = { "s21", "s22", 2, 3.4, "s23" };
-    typedef fusion::result_of::as_nview<test_data const, 1, 2, 4>::type 
-        test_view;
-    std::vector<test_data> v;
-    v.push_back(d1);
-    v.push_back(d2);
-
     {
-        karma::rule<output_iterator<char>::type, test_view()> r =
-            karma::string << karma::string << karma::double_;
+        test_data d2 = { "s21", "s22", 2, 3.4, "s23" };
+        typedef fusion::result_of::as_nview<test_data const, 1, 2, 4>::type 
+            test_view;
+        std::vector<test_data> v;
+        v.push_back(d1);
+        v.push_back(d2);
+
+        karma::rule<output_iterator<char>::type, test_data()> r =
+            karma::attr_cast<test_data, test_view>(
+                karma::string << karma::string << karma::double_
+            );
+
         BOOST_TEST(test("s11s122.5\ns21s223.4", r % karma::eol, v));
         BOOST_TEST(test_delimited("s11s122.5\n s21s223.4", 
             r % karma::eol, v, ' '));
     }
 
     {
-        test_int_data d = { 1 };
-        BOOST_TEST(test("1", karma::attr_cast<int>(karma::int_), d));
+        test_int_data1 d = { 1 };
+        BOOST_TEST(test("1", karma::attr_cast(karma::int_), d));
+        BOOST_TEST(test("1", karma::attr_cast<test_int_data1>(karma::int_), d));
+        BOOST_TEST(test("1", karma::attr_cast<test_int_data1, int>(karma::int_), d));
+    }
+
+    {
+        test_int_data1 d[] = {{ 1 }, { 2 }};
+        std::vector<test_int_data1> v;
+        v.push_back(d[0]);
+        v.push_back(d[1] );
+
+        BOOST_TEST(test("1,2", karma::attr_cast(karma::int_) % ',', v));
+        BOOST_TEST(test("1,2"
+          , karma::attr_cast<test_int_data1>(karma::int_) % ',', v));
+        BOOST_TEST(test("1,2"
+          , karma::attr_cast<test_int_data1, int>(karma::int_) % ',', v));
+    }
+
+    {
+        test_int_data1 d[] = {{ 1 }, { 2 }};
+        std::vector<test_int_data1> v;
+        v.push_back(d[0]);
+        v.push_back(d[1] );
+
+// this won't compile as there is no defined transformation for
+// test_int_data1 and double
+//      BOOST_TEST(test("1.0,2.0", karma::attr_cast(karma::double_) % ',', v));
+//      BOOST_TEST(test("1.0,2.0"
+//        , karma::attr_cast<test_int_data1>(karma::double_) % ',', v));
+
+        BOOST_TEST(test("1.0,2.0"
+          , karma::attr_cast<test_int_data1, int>(karma::double_) % ',', v));
+    }
+
+    {
+        test_int_data2 d = { 1 };
+        BOOST_TEST(test("1", karma::attr_cast(karma::int_), d));
+        BOOST_TEST(test("1", karma::attr_cast<test_int_data2>(karma::int_), d));
+        BOOST_TEST(test("1", karma::attr_cast<test_int_data2, int>(karma::int_), d));
+    }
+
+    {
+        test_int_data2 d[] = {{ 1 }, { 2 }};
+        std::vector<test_int_data2> v;
+        v.push_back(d[0]);
+        v.push_back(d[1] );
+
+        BOOST_TEST(test("1,2", karma::attr_cast(karma::int_) % ',', v));
+        BOOST_TEST(test("1,2"
+          , karma::attr_cast<test_int_data2>(karma::int_) % ',', v));
+        BOOST_TEST(test("1,2"
+          , karma::attr_cast<test_int_data2, int>(karma::int_) % ',', v));
+    }
+
+    {
+        test_int_data2 d[] = {{ 1 }, { 2 }};
+        std::vector<test_int_data2> v;
+        v.push_back(d[0]);
+        v.push_back(d[1] );
+
+// this won't compile as there is no defined transformation for
+// test_int_data2 and double
+//      BOOST_TEST(test("1.0,2.0", karma::attr_cast(karma::double_) % ',', v));
+//      BOOST_TEST(test("1.0,2.0"
+//        , karma::attr_cast<test_int_data2>(karma::double_) % ',', v));
+
+        BOOST_TEST(test("1.0,2.0"
+          , karma::attr_cast<test_int_data2, int>(karma::double_) % ',', v));
     }
 
     return boost::report_errors();
Modified: trunk/libs/spirit/test/karma/binary.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/binary.cpp	(original)
+++ trunk/libs/spirit/test/karma/binary.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -8,6 +8,11 @@
 
 #include <boost/spirit/include/karma_binary.hpp>
 #include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_phoenix_attributes.hpp>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
 
 #include "test.hpp"
 
@@ -150,7 +155,7 @@
 #endif
     }
 
-    {   // test native endian binaries
+    {   // test optional attributes
 
 #ifdef BOOST_LITTLE_ENDIAN
         boost::optional<boost::uint8_t> v8 (0x01);
@@ -180,5 +185,71 @@
 #endif
     }
 
+    {   // test Phoenix expression attributes, only supported if 
+        // karma_phoenix_attributes.hpp is included
+        namespace phoenix = boost::phoenix;
+
+#ifdef BOOST_LITTLE_ENDIAN
+        BOOST_TEST(binary_test("\x01", 1, byte_, phoenix::val(0x01)));
+        BOOST_TEST(binary_test("\x01\0x02", 2, byte_, phoenix::val(0x0201)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword, 
+            phoenix::val(0x04030201)));
+
+        boost::uint8_t v8 (0x01);
+        BOOST_TEST(binary_test("\x01", 1, byte_, phoenix::ref(v8)));
+        BOOST_TEST(binary_test("\x02", 1, byte_, ++phoenix::ref(v8)));
+
+        boost::uint16_t v16 (0x0201);
+        BOOST_TEST(binary_test("\x01\x02", 2, word, phoenix::ref(v16)));
+        BOOST_TEST(binary_test("\x02\x02", 2, word, ++phoenix::ref(v16)));
+
+        boost::uint32_t v32 (0x04030201);
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword, phoenix::ref(v32)));
+        BOOST_TEST(binary_test("\x02\x02\x03\x04", 4, dword, ++phoenix::ref(v32)));
+
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword, 
+            phoenix::val(0x0807060504030201LL)));
+
+        boost::uint64_t v64 (0x0807060504030201LL);
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword, 
+            phoenix::ref(v64)));
+        BOOST_TEST(binary_test("\x02\x02\x03\x04\x05\x06\x07\x08", 8, qword, 
+            ++phoenix::ref(v64)));
+#endif
+
+#else // BOOST_LITTLE_ENDIAN
+
+        BOOST_TEST(binary_test("\x01", 1, byte_, phoenix::val(0x01)));
+        BOOST_TEST(binary_test("\x01\x02", 2, byte_, phoenix::val(0x0102)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword, 
+            phoenix::val(0x01020304)));
+
+        boost::uint8_t v8 (0x01);
+        BOOST_TEST(binary_test("\x01", 1, byte_, phoenix::ref(v8)));
+        BOOST_TEST(binary_test("\x02", 1, byte_, ++phoenix::ref(v8)));
+
+        boost::uint16_t v16 (0x0102);
+        BOOST_TEST(binary_test("\x01\x02", 2, word, phoenix::ref(v16)));
+        BOOST_TEST(binary_test("\x01\x03", 2, word, ++phoenix::ref(v16)));
+
+        boost::uint32_t v32 (0x01020304);
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword, phoenix::ref(v32)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x05", 4, dword, ++phoenix::ref(v32)));
+
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword, 
+            phoenix::val(0x0102030405060708LL)));
+
+        boost::uint64_t v64 (0x0102030405060708LL);
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword, 
+            phoenix::ref(v64)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x09", 8, qword, 
+            ++phoenix::ref(v64)));
+#endif
+
+#endif
+    }
+
     return boost::report_errors();
 }
Modified: trunk/libs/spirit/test/karma/bool.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/bool.cpp	(original)
+++ trunk/libs/spirit/test/karma/bool.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -12,8 +12,14 @@
 #include <boost/spirit/include/karma_string.hpp>
 #include <boost/spirit/include/karma_numeric.hpp>
 #include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_phoenix_attributes.hpp>
+
 #include <boost/spirit/home/support/safe_bool.hpp>
 
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
 #include "test.hpp"
 
 using namespace spirit_test;
@@ -68,6 +74,7 @@
     using boost::spirit::karma::lower;
     using boost::spirit::karma::upper;
 
+    // testing plain bool
     {
         BOOST_TEST(test("false", bool_, false));
         BOOST_TEST(test("true", bool_, true));
@@ -81,6 +88,28 @@
         BOOST_TEST(test("true", lit(true)));
     }
 
+    // test optional attributes
+    {
+        boost::optional<bool> optbool;
+
+        BOOST_TEST(!test("", bool_, optbool));
+        optbool = false;
+        BOOST_TEST(test("false", bool_, optbool));
+        optbool = true;
+        BOOST_TEST(test("true", bool_, optbool));
+    }
+
+    // test Phoenix expression attributes (include karma_phoenix_attributes.hpp)
+    {
+        namespace phoenix = boost::phoenix;
+
+        BOOST_TEST(test("true", bool_, phoenix::val(true)));
+
+        bool b = false;
+        BOOST_TEST(test("false", bool_, phoenix::ref(b)));
+        BOOST_TEST(test("true", bool_, ++phoenix::ref(b)));
+    }
+
     {
         BOOST_TEST(test("false", lower[bool_], false));
         BOOST_TEST(test("true", lower[bool_], true));
@@ -110,7 +139,7 @@
     {
         typedef boost::spirit::karma::bool_generator<bool, special_bool_policy> 
             backwards_bool_type;
-        backwards_bool_type const backwards_bool;
+        backwards_bool_type const backwards_bool = backwards_bool_type();
 
         BOOST_TEST(test("eurt", backwards_bool, false));
         BOOST_TEST(test("true", backwards_bool, true));
@@ -125,7 +154,8 @@
     {
         typedef boost::spirit::karma::bool_generator<
             test_bool_data, test_bool_policy> test_bool_type;
-        test_bool_type const test_bool;
+        test_bool_type const test_bool = test_bool_type();
+
         test_bool_data const test_false = test_bool_data(false);
         test_bool_data const test_true = test_bool_data(true);
 
Modified: trunk/libs/spirit/test/karma/char.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/char.cpp	(original)
+++ trunk/libs/spirit/test/karma/char.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -11,6 +11,7 @@
 #include <boost/spirit/include/karma_char.hpp>
 #include <boost/spirit/include/karma_generate.hpp>
 #include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/karma_phoenix_attributes.hpp>
 
 #include <boost/spirit/include/phoenix_core.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
@@ -252,6 +253,7 @@
         BOOST_TEST((!test(L"", wide::char_(val(L'y')), L'x')));
     }
 
+    // we can pass optionals as attributes to any generator
     {
         namespace ascii = boost::spirit::ascii;
         namespace wide = boost::spirit::standard_wide;
@@ -281,5 +283,18 @@
         BOOST_TEST(!test(L"", wide::char_(L'y'), w));
     }
 
+    // yes, we can use phoenix expressions as attributes as well
+    // but only if we include karma_phoenix_attributes.hpp
+    {
+        namespace ascii = boost::spirit::ascii;
+        namespace phoenix = boost::phoenix;
+
+        BOOST_TEST(test("x", ascii::char_, phoenix::val('x')));
+
+        char c = 'x';
+        BOOST_TEST(test("x", ascii::char_, phoenix::ref(c)));
+        BOOST_TEST(test("y", ascii::char_, ++phoenix::ref(c)));
+    }
+
     return boost::report_errors();
 }
Modified: trunk/libs/spirit/test/karma/format_manip_attr.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/format_manip_attr.cpp	(original)
+++ trunk/libs/spirit/test/karma/format_manip_attr.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -18,7 +18,9 @@
 
 #include "test_manip_attr.hpp"
 
-using namespace spirit_test;
+using spirit_test::test;
+using spirit_test::test_delimited;
+using spirit_test::test_predelimited;
 
 ///////////////////////////////////////////////////////////////////////////////
 int
Deleted: trunk/libs/spirit/test/karma/functor.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/functor.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
+++ (empty file)
@@ -1,60 +0,0 @@
-/*=============================================================================
-    Copyright (c) 2001-2007 Joel de Guzman
-    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)
-=============================================================================*/
-
-#include <boost/config/warning_disable.hpp>
-#include <boost/detail/lightweight_test.hpp>
-#include <boost/spirit/include/karma_char.hpp>
-#include <boost/spirit/include/karma_auxiliary.hpp>
-#include <boost/spirit/include/karma_action.hpp>
-#include <boost/spirit/include/support_argument.hpp>
-#include <boost/spirit/include/phoenix_core.hpp>
-#include <boost/spirit/include/phoenix_operator.hpp>
-
-#include <iostream>
-#include "test.hpp"
-
-///////////////////////////////////////////////////////////////////////////////
-struct number_generator : public boost::spirit::karma::functor_base
-{
-    template <typename Context>
-    struct apply
-    {
-        typedef int type;
-    };
-
-    template <typename Parameter, typename Context, typename OutputIterator>
-    bool operator()(Parameter v, Context& ctx, OutputIterator& sink) const
-    {
-        char ch = v % 10 + '0';
-        v /= 10;
-        
-        if (0 != v) 
-            (*this)(v, ctx, sink);
-            
-        *sink = ch;
-        ++sink;
-        return true;
-    }
-};
-
-boost::spirit::karma::functor_generator<number_generator> number;
-
-///////////////////////////////////////////////////////////////////////////////
-int main()
-{
-    using spirit_test::test;
-    using namespace boost::spirit;
-    using namespace boost::spirit::karma;
-
-    {
-        BOOST_TEST(test("0", number));
-        BOOST_TEST(test("1234", number, 1234));
-    }
-        
-    return boost::report_errors();
-}
Modified: trunk/libs/spirit/test/karma/int_numerics.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/int_numerics.cpp	(original)
+++ trunk/libs/spirit/test/karma/int_numerics.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -21,6 +21,7 @@
 #include <boost/spirit/include/karma_numeric.hpp>
 #include <boost/spirit/include/karma_directive.hpp>
 #include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/karma_phoenix_attributes.hpp>
 
 #include <limits>
 #include "test.hpp"
@@ -90,6 +91,16 @@
         BOOST_TEST(test(expected_maxval, gen, optmax));
         BOOST_TEST(test(expected_minval, gen(minval), optmin));
         BOOST_TEST(test(expected_maxval, gen(maxval), optmax));
+
+    // Phoenix expression tests (only supported while including
+    // karma_phoenix_attributes.hpp
+        namespace phoenix = boost::phoenix;
+
+        BOOST_TEST(test("1", gen, phoenix::val(1)));
+
+        T val = 1;
+        BOOST_TEST(test("1", gen, phoenix::ref(val)));
+        BOOST_TEST(test("2", gen, ++phoenix::ref(val)));
     }
 };
 
Modified: trunk/libs/spirit/test/karma/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/kleene.cpp	(original)
+++ trunk/libs/spirit/test/karma/kleene.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -64,11 +64,12 @@
 
         BOOST_TEST(test("10,20,30,", *(int_ << ','), v));
         BOOST_TEST(test_delimited("10 , 20 , 30 , ", *(int_ << ','), v, lit(" ")));
- 
-        fusion::vector<char, char> cc ('a', 'c');
-        BOOST_TEST(test("ac", char_ << *(lit(' ') << ',') << char_, cc));
-        BOOST_TEST(test_delimited("a c ", 
-            char_ << *(lit(' ') << ',') << char_, cc, " "));
+
+// leads to infinite loops
+//         fusion::vector<char, char> cc ('a', 'c');
+//         BOOST_TEST(test("ac", char_ << *(lit(' ') << ',') << char_, cc));
+//         BOOST_TEST(test_delimited("a c ", 
+//             char_ << *(lit(' ') << ',') << char_, cc, " "));
     }
 
     { // actions
Modified: trunk/libs/spirit/test/karma/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/plus.cpp	(original)
+++ trunk/libs/spirit/test/karma/plus.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -69,10 +69,11 @@
         BOOST_TEST(test("10,20,30,", +(int_ << ','), v));
         BOOST_TEST(test_delimited("10 , 20 , 30 , ", +(int_ << ','), v, lit(" ")));
  
-        fusion::vector<char, char> cc ('a', 'c');
-        BOOST_TEST(test("ac", char_ << !+(lit(' ') << ',') << char_, cc));
-        BOOST_TEST(test_delimited("a c ", 
-            char_ << !+(lit(' ') << ',') << char_, cc, " "));
+// leads to infinite loops
+//         fusion::vector<char, char> cc ('a', 'c');
+//         BOOST_TEST(test("ac", char_ << !+(lit(' ') << ',') << char_, cc));
+//         BOOST_TEST(test_delimited("a c ", 
+//             char_ << !+(lit(' ') << ',') << char_, cc, " "));
     }
 
     { // actions
Modified: trunk/libs/spirit/test/karma/real_numerics.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/real_numerics.cpp	(original)
+++ trunk/libs/spirit/test/karma/real_numerics.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -14,6 +14,11 @@
 #include <boost/spirit/include/karma_numeric.hpp>
 #include <boost/spirit/include/karma_generate.hpp>
 #include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_phoenix_attributes.hpp>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
 
 #include <limits>
 #include "test.hpp"
@@ -533,5 +538,15 @@
         BOOST_TEST(test("1.0", double_(1.0), v));
     }
 
+    {   // Phoenix expression tests (include karma_phoenix_attributes.hpp)
+        namespace phoenix = boost::phoenix;
+
+        BOOST_TEST(test("1.0", double_, phoenix::val(1.0)));
+
+        double d = 1.2;
+        BOOST_TEST(test("1.2", double_, phoenix::ref(d)));
+        BOOST_TEST(test("2.2", double_, ++phoenix::ref(d)));
+    }
+
     return boost::report_errors();
 }
Modified: trunk/libs/spirit/test/karma/repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/repeat.cpp	(original)
+++ trunk/libs/spirit/test/karma/repeat.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -16,9 +16,11 @@
 #include <boost/spirit/include/karma_action.hpp>
 #include <boost/spirit/include/karma_nonterminal.hpp>
 #include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_phoenix_attributes.hpp>
 #include <boost/spirit/include/support_argument.hpp>
 #include <boost/spirit/include/phoenix_core.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
 #include <boost/fusion/include/std_pair.hpp>
 
 #include <string>
@@ -29,6 +31,7 @@
 
 using namespace spirit_test;
 
+///////////////////////////////////////////////////////////////////////////////
 int main()
 {
     using namespace boost::spirit::ascii;
@@ -158,6 +161,17 @@
         BOOST_TEST(!test("", repeat(4, inf)[r], v3));
     }
 
+    {
+        namespace ascii = boost::spirit::ascii;
+        namespace phoenix = boost::phoenix;
+
+        char c = 'a';
+        BOOST_TEST(test("bcd", repeat(3)[ascii::char_[_1 = ++phoenix::ref(c)]]));
+
+        c = 'a';
+        BOOST_TEST(test("bcd", repeat(3)[ascii::char_], ++phoenix::ref(c)));
+    }
+
     return boost::report_errors();
 }
 
Added: trunk/libs/spirit/test/qi/attribute.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/attribute.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -0,0 +1,233 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/fusion/include/struct.hpp>
+#include <boost/fusion/include/nview.hpp>
+#include <boost/mpl/print.hpp>
+
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+struct test_data
+{
+    std::string s1;
+    std::string s2;
+    int i1;
+    double d1;
+    std::string s3;
+};
+
+BOOST_FUSION_ADAPT_STRUCT(
+    test_data,
+    (int, i1)
+    (std::string, s1)
+    (std::string, s2)
+    (std::string, s3)
+    (double, d1)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+struct test_int_data1
+{
+    int i;
+};
+
+// we provide a custom attribute transformation taking copy of the actual 
+// attribute value, simulating more complex type transformations
+namespace boost { namespace spirit { namespace traits
+{
+    template <>
+    struct transform_attribute<test_int_data1, int>
+    {
+        typedef int type;
+        static int pre(test_int_data1& d) { return d.i; }
+        static void post(test_int_data1& d, int i) { d.i = i; }
+    };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+struct test_int_data2
+{
+    int i;
+};
+
+// we provide a simple custom attribute transformation utilizing passing the 
+// actual attribute by reference
+namespace boost { namespace spirit { namespace traits
+{
+    template <>
+    struct transform_attribute<test_int_data2, int>
+    {
+        typedef int& type;
+        static int& pre(test_int_data2& d) { return d.i; }
+        static void post(test_int_data2& d, int const& i) {}
+    };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using spirit_test::test_attr;
+    namespace qi = boost::spirit::qi;
+    namespace fusion = boost::fusion;
+
+    // testing attribute reordering in a fusion sequence as explicit attribute
+    {
+        typedef fusion::result_of::as_nview<test_data, 1, 0, 4>::type 
+            test_view;
+
+        test_data d1 = { "", "", 0, 0.0, "" };
+        test_view v1 = fusion::as_nview<1, 0, 4>(d1);
+        BOOST_TEST(test_attr("s1,2,1.5", 
+            *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_, v1));
+        BOOST_TEST(d1.i1 == 2 && d1.s1 == "s1" && d1.d1 == 1.5);
+
+        test_data d2 = { "", "", 0, 0.0, "" };
+        test_view v2 = fusion::as_nview<1, 0, 4>(d2);
+        BOOST_TEST(test_attr("s1, 2, 1.5 ", 
+            *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_, 
+            v2, qi::space));
+        BOOST_TEST(d2.i1 == 2 && d2.s1 == "s1" && d2.d1 == 1.5);
+    }
+
+    {
+        // this won't work without the second template argument as *digit
+        // exposes a vector<char> as its attribute
+        std::string str;
+        BOOST_TEST(test_attr("123"
+          , qi::attr_cast<std::string, std::string>(*qi::digit), str));
+        BOOST_TEST(str == "123");
+    }
+
+    // testing attribute reordering in a fusion sequence involving a rule
+    {
+        typedef fusion::result_of::as_nview<test_data, 1, 0, 4>::type 
+            test_view;
+        std::vector<test_data> v;
+
+        qi::rule<char const*, test_data()> r1 = 
+            qi::attr_cast<test_data, test_view>(
+                *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_
+            );
+
+        BOOST_TEST(test_attr("s1,2,1.5\ns2,4,3.5", r1 % qi::eol, v));
+        BOOST_TEST(v.size() == 2 &&
+            v[0].i1 == 2 && v[0].s1 == "s1" && v[0].d1 == 1.5 &&
+            v[1].i1 == 4 && v[1].s1 == "s2" && v[1].d1 == 3.5);
+
+        qi::rule<char const*, test_data(), qi::blank_type> r2 =
+            qi::attr_cast<test_data, test_view>(
+                *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_
+            );
+
+        v.clear();
+        BOOST_TEST(test_attr("s1, 2, 1.5 \n s2, 4, 3.5", r2 % qi::eol, v, qi::blank));
+        BOOST_TEST(v.size() == 2 &&
+            v[0].i1 == 2 && v[0].s1 == "s1" && v[0].d1 == 1.5 &&
+            v[1].i1 == 4 && v[1].s1 == "s2" && v[1].d1 == 3.5);
+    }
+
+    // testing explicit transformation if attribute needs to be copied
+    {
+        test_int_data1 d = { 0 };
+        BOOST_TEST(test_attr("1", qi::attr_cast(qi::int_), d));
+        BOOST_TEST(d.i == 1);
+        BOOST_TEST(test_attr("2", qi::attr_cast<test_int_data1>(qi::int_), d));
+        BOOST_TEST(d.i == 2);
+        BOOST_TEST(test_attr("3", qi::attr_cast<test_int_data1, int>(qi::int_), d));
+        BOOST_TEST(d.i == 3);
+    }
+
+    {
+        std::vector<test_int_data1> v;
+
+        BOOST_TEST(test_attr("1,2", qi::attr_cast(qi::int_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+
+        v.clear();
+        BOOST_TEST(test_attr("1,2"
+          , qi::attr_cast<test_int_data1>(qi::int_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+
+        v.clear();
+        BOOST_TEST(test_attr("1,2"
+          , qi::attr_cast<test_int_data1, int>(qi::int_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+    }
+
+    {
+        std::vector<test_int_data1> v;
+
+// this won't compile as there is no defined transformation for
+// test_int_data1 and double
+//      BOOST_TEST(test_attr("1.0,2.2", qi::attr_cast(qi::double_) % ',', v));
+//      BOOST_TEST(test_attr("1.0,2.2"
+//        , qi::attr_cast<test_int_data1>(qi::double_) % ',', v));
+
+        BOOST_TEST(test_attr("1.0,2.2"
+          , qi::attr_cast<test_int_data1, int>(qi::double_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+    }
+
+    // testing explicit transformation if attribute is taken by reference
+    {
+        test_int_data2 d = { 0 };
+        BOOST_TEST(test_attr("1", qi::attr_cast(qi::int_), d));
+        BOOST_TEST(d.i == 1);
+        BOOST_TEST(test_attr("2", qi::attr_cast<test_int_data2>(qi::int_), d));
+        BOOST_TEST(d.i == 2);
+        BOOST_TEST(test_attr("3", qi::attr_cast<test_int_data2, int>(qi::int_), d));
+        BOOST_TEST(d.i == 3);
+    }
+
+    {
+        std::vector<test_int_data2> v;
+
+        BOOST_TEST(test_attr("1,2", qi::attr_cast(qi::int_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+
+        v.clear();
+        BOOST_TEST(test_attr("1,2"
+          , qi::attr_cast<test_int_data2>(qi::int_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+
+        v.clear();
+        BOOST_TEST(test_attr("1,2"
+          , qi::attr_cast<test_int_data2, int>(qi::int_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+    }
+
+    {
+        std::vector<test_int_data2> v;
+
+// this won't compile as there is no defined transformation for
+// test_int_data2 and double
+//      BOOST_TEST(test_attr("1.0,2.2", qi::attr_cast(qi::double_) % ',', v));
+//      BOOST_TEST(test_attr("1.0,2.2"
+//        , qi::attr_cast<test_int_data2>(qi::double_) % ',', v));
+
+        BOOST_TEST(test_attr("1.0,2.2"
+          , qi::attr_cast<test_int_data2, int>(qi::double_) % ',', v));
+        BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
+    }
+
+    return boost::report_errors();
+}
Modified: trunk/libs/spirit/test/qi/bool.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/bool.cpp	(original)
+++ trunk/libs/spirit/test/qi/bool.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -19,10 +19,11 @@
     static bool
     parse_false(Iterator& first, Iterator const& last, Attribute& attr)
     {
+        namespace spirit = boost::spirit;
         namespace qi = boost::spirit::qi;
         if (qi::detail::string_parse("eurt", first, last, qi::unused))
         {
-            qi::detail::assign_to(false, attr);    // result is false
+            spirit::traits::assign_to(false, attr);    // result is false
             return true;
         }
         return false;
@@ -59,7 +60,7 @@
     {
         typedef boost::spirit::qi::bool_parser<bool, backwards_bool_policies> 
             backwards_bool_type;
-        backwards_bool_type const backwards_bool;
+        backwards_bool_type const backwards_bool = backwards_bool_type();
 
         BOOST_TEST(test("true", backwards_bool));
         BOOST_TEST(test("eurt", backwards_bool));
@@ -76,7 +77,7 @@
     {
         typedef boost::spirit::qi::bool_parser<test_bool_type> 
             bool_test_type;
-        bool_test_type const test_bool;
+        bool_test_type const test_bool = bool_test_type();
 
         BOOST_TEST(test("true", test_bool));
         BOOST_TEST(test("false", test_bool));
Modified: trunk/libs/spirit/test/qi/grammar_fail.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/grammar_fail.cpp	(original)
+++ trunk/libs/spirit/test/qi/grammar_fail.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -12,20 +12,17 @@
 #include <boost/spirit/include/qi_nonterminal.hpp>
 #include <boost/spirit/include/qi_parse.hpp>
 
-using namespace boost::spirit;
-using namespace boost::spirit::qi;
-using namespace boost::spirit::ascii;
+namespace qi = boost::spirit::qi;
 
-struct num_list : grammar<char const*, rule<char const*> >
+struct num_list : qi::grammar<char const*, qi::rule<char const*> >
 {
     num_list() : base_type(start)
     {
-        using boost::spirit::int_;
-        num = int_;
+        num = qi::int_;
         start = num >> *(',' >> num);
     }
 
-    rule<char const*, rule<char const*> > start, num;
+    qi::rule<char const*, qi::rule<char const*> > start, num;
 };
 
 // this test must fail compiling
@@ -35,8 +32,8 @@
     char const* end = &input[strlen(input)+1];
 
     num_list g;
-    bool r = phrase_parse(input, end, g,
-        space | ('%' >> *~char_('\n') >> '\n'));
+    bool r = qi::phrase_parse(input, end, g,
+        qi::space | ('%' >> *~qi::char_('\n') >> '\n'));
 
     return 0;
 }
Modified: trunk/libs/spirit/test/qi/omit.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/omit.cpp	(original)
+++ trunk/libs/spirit/test/qi/omit.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -41,9 +41,9 @@
 
     {
         // omit[] means we don't receive the attribute
-        vector<char> attr;
+        char attr;
         BOOST_TEST((test_attr("abc", omit[char_] >> omit['b'] >> char_, attr)));
-        BOOST_TEST((at_c<0>(attr) == 'c'));
+        BOOST_TEST((attr == 'c'));
     }
 
     {
@@ -89,15 +89,8 @@
     }
 
     {
-        // omit[] means we don't receive the attribute
-        vector<char> attr;
-        BOOST_TEST((test_attr("a hello c", char_ >> "hello" >> omit[char_], attr, space)));
-        BOOST_TEST((at_c<0>(attr) == 'a'));
-    }
-
-    {
         // if only one node in a sequence is left (all the others are omitted),
-        // then we should also allow "naked" attributes (unwraped in a tuple)
+        // then we need "naked" attributes (not wraped in a tuple)
         int attr;
         BOOST_TEST((test_attr("a 123 c", omit['a'] >> int_ >> omit['c'], attr, space)));
         BOOST_TEST((attr == 123));
Modified: trunk/libs/spirit/test/qi/terminal_ex.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/terminal_ex.cpp	(original)
+++ trunk/libs/spirit/test/qi/terminal_ex.cpp	2009-10-02 17:19:08 EDT (Fri, 02 Oct 2009)
@@ -56,7 +56,7 @@
                 if (it == last || *it++ != Char('+'))
                     return false;
 
-            boost::spirit::qi::detail::assign_to(count, attr);
+            boost::spirit::traits::assign_to(count, attr);
             first = it;
             return true;
         }
@@ -104,7 +104,7 @@
                 if (it == last || *it++ != Char('-'))
                     return false;
 
-            boost::spirit::qi::detail::assign_to(count, attr);
+            boost::spirit::traits::assign_to(count, attr);
             first = it;
             return true;
         }
@@ -157,7 +157,7 @@
                 if (it == last || *it++ != Char('*'))
                     return false;
 
-            boost::spirit::qi::detail::assign_to(count, attr);
+            boost::spirit::traits::assign_to(count, attr);
             first = it;
             return true;
         }