Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r67442 - in trunk: boost/spirit/home/karma/string boost/spirit/home/lex/lexer/lexertl boost/spirit/home/qi/detail boost/spirit/home/support libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2010-12-23 21:12:13


Author: hkaiser
Date: 2010-12-23 21:12:10 EST (Thu, 23 Dec 2010)
New Revision: 67442
URL: http://svn.boost.org/trac/boost/changeset/67442

Log:
Spirit: fixing Qi sequence attribute handling
Text files modified:
   trunk/boost/spirit/home/karma/string/lit.hpp | 3
   trunk/boost/spirit/home/lex/lexer/lexertl/token.hpp | 53 +++++++++++++++++++++++
   trunk/boost/spirit/home/qi/detail/assign_to.hpp | 90 +++++++++++++++++++++++++++++++++++++++
   trunk/boost/spirit/home/support/attributes_fwd.hpp | 3 +
   trunk/libs/spirit/test/qi/sequence.cpp | 22 +++++++++
   5 files changed, 169 insertions(+), 2 deletions(-)

Modified: trunk/boost/spirit/home/karma/string/lit.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/string/lit.hpp (original)
+++ trunk/boost/spirit/home/karma/string/lit.hpp 2010-12-23 21:12:10 EST (Thu, 23 Dec 2010)
@@ -166,7 +166,8 @@
 
             using spirit::traits::get_c_string;
             if (!detail::string_compare(
- get_c_string<extracted_string_type>::call(traits::extract_from<attribute_type>(attr, context))
+ get_c_string<extracted_string_type>::call(
+ traits::extract_from<attribute_type>(attr, context))
                   , get_c_string<string_type>::call(str_), char_encoding(), Tag()))
             {
                 return false;

Modified: trunk/boost/spirit/home/lex/lexer/lexertl/token.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/lexer/lexertl/token.hpp (original)
+++ trunk/boost/spirit/home/lex/lexer/lexertl/token.hpp 2010-12-23 21:12:10 EST (Thu, 23 Dec 2010)
@@ -487,6 +487,25 @@
         }
     };
 
+ template <typename Attribute, typename Iterator, typename AttributeTypes
+ , typename HasState, typename Idtype>
+ struct assign_to_container_from_value<Attribute
+ , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
+ : assign_to_attribute_from_value<Attribute
+ , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
+ {};
+
+ template <typename Iterator>
+ struct assign_to_container_from_value<
+ iterator_range<Iterator>, iterator_range<Iterator> >
+ {
+ static void
+ call(iterator_range<Iterator> const& val, iterator_range<Iterator>& attr)
+ {
+ attr = val;
+ }
+ };
+
     // These are called from the parse function of token_def if the token type
     // has no special attribute type assigned
     template <typename Attribute, typename Iterator, typename HasState
@@ -505,6 +524,14 @@
         }
     };
 
+ template <typename Attribute, typename Iterator, typename HasState
+ , typename Idtype>
+ struct assign_to_container_from_value<Attribute
+ , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
+ : assign_to_attribute_from_value<Attribute
+ , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
+ {};
+
     // same as above but using mpl::vector<> instead of mpl::vector0<>
     template <typename Attribute, typename Iterator, typename HasState
       , typename Idtype>
@@ -522,6 +549,14 @@
         }
     };
 
+ template <typename Attribute, typename Iterator, typename HasState
+ , typename Idtype>
+ struct assign_to_container_from_value<Attribute
+ , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
+ : assign_to_attribute_from_value<Attribute
+ , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
+ {};
+
     // This is called from the parse function of token_def if the token type
     // has been explicitly omitted (i.e. no attribute value is used), which
     // essentially means that every attribute gets initialized using default
@@ -539,6 +574,14 @@
         }
     };
 
+ template <typename Attribute, typename Iterator, typename HasState
+ , typename Idtype>
+ struct assign_to_container_from_value<Attribute
+ , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
+ : assign_to_attribute_from_value<Attribute
+ , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
+ {};
+
     // This is called from the parse function of lexer_def_
     template <typename Iterator, typename AttributeTypes, typename HasState
       , typename Idtype_, typename Idtype>
@@ -562,6 +605,16 @@
         }
     };
 
+ template <typename Iterator, typename AttributeTypes, typename HasState
+ , typename Idtype_, typename Idtype>
+ struct assign_to_container_from_value<
+ fusion::vector2<Idtype_, iterator_range<Iterator> >
+ , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
+ : assign_to_attribute_from_value<
+ fusion::vector2<Idtype_, iterator_range<Iterator> >
+ , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
+ {};
+
     ///////////////////////////////////////////////////////////////////////////
     // Overload debug output for a single token, this integrates lexer tokens
     // with Qi's simple_trace debug facilities

Modified: trunk/boost/spirit/home/qi/detail/assign_to.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/assign_to.hpp (original)
+++ trunk/boost/spirit/home/qi/detail/assign_to.hpp 2010-12-23 21:12:10 EST (Thu, 23 Dec 2010)
@@ -158,11 +158,99 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename T, typename Enable>
+ struct assign_to_container_from_value
+ {
+ // T is not a container and not a string
+ template <typename T_>
+ static void call(T_ const& val, Attribute& attr, mpl::false_, mpl::false_)
+ {
+ traits::push_back(attr, val);
+ }
+
+ // T is a container (but not a string)
+ template <typename T_>
+ static void call(T_ const& val, Attribute& attr, mpl::true_, mpl::false_)
+ {
+ typedef typename traits::container_iterator<T_ const>::type
+ iterator_type;
+ iterator_type end = traits::end(val);
+ for (iterator_type i = traits::begin(val); i != end; traits::next(i))
+ push_back(attr, traits::deref(i));
+ }
+
+ // T is a string
+ template <typename Iterator>
+ static void append_to_string(Attribute& attr, Iterator begin, Iterator end)
+ {
+ for (Iterator i = begin; i != end; ++i)
+ push_back(attr, *i);
+ }
+
+ template <typename T_, typename Pred>
+ static void call(T_ const& val, Attribute& attr, Pred, mpl::true_)
+ {
+ typedef typename char_type_of<T_>::type char_type;
+ append_to_string(attr, traits::get_begin<char_type>(val)
+ , traits::get_end<char_type>(val));
+ }
+
+ static void call(T const& val, Attribute& attr)
+ {
+ typedef typename traits::is_container<T>::type is_container;
+ typedef typename traits::is_string<T>::type is_string;
+
+ call(val, attr, is_container(), is_string());
+ }
+ };
+
+ template <typename Attribute, typename T>
+ struct assign_to_container_from_value<reference_wrapper<Attribute>, T>
+ {
+ static void
+ call(T const& val, reference_wrapper<Attribute> attr)
+ {
+ assign_to(val.get(), attr);
+ }
+ };
+
+ template <typename Attribute>
+ struct assign_to_container_from_value<optional<Attribute>, unused_type>
+ {
+ static void
+ call(unused_type, optional<Attribute> const&)
+ {
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ // overload for non-container attributes
+ template <typename T, typename Attribute, typename P1, typename P2>
+ inline void
+ assign_to(T const& val, Attribute& attr, P1, P2)
+ {
+ assign_to_attribute_from_value<Attribute, T>::call(val, attr);
+ }
+
+ // overload for containers (but not for variants holding containers)
+ template <typename T, typename Attribute>
+ inline void
+ assign_to(T const& val, Attribute& attr, mpl::true_, mpl::true_)
+ {
+ assign_to_container_from_value<Attribute, T>::call(val, attr);
+ }
+ }
+
     template <typename T, typename Attribute>
     inline void
     assign_to(T const& val, Attribute& attr)
     {
- assign_to_attribute_from_value<Attribute, T>::call(val, attr);
+ typedef typename traits::is_container<Attribute>::type is_container;
+ typedef typename traits::not_is_variant<Attribute>::type not_is_variant;
+
+ detail::assign_to(val, attr, is_container(), not_is_variant());
     }
 
     template <typename T>

Modified: trunk/boost/spirit/home/support/attributes_fwd.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes_fwd.hpp (original)
+++ trunk/boost/spirit/home/support/attributes_fwd.hpp 2010-12-23 21:12:10 EST (Thu, 23 Dec 2010)
@@ -101,6 +101,9 @@
     template <typename Attribute, typename T, typename Enable = void>
     struct assign_to_attribute_from_value;
 
+ template <typename Attribute, typename T, typename Enable = void>
+ struct assign_to_container_from_value;
+
     template <typename T, typename Attribute>
     void assign_to(T const& val, Attribute& attr);
 

Modified: trunk/libs/spirit/test/qi/sequence.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/sequence.cpp (original)
+++ trunk/libs/spirit/test/qi/sequence.cpp 2010-12-23 21:12:10 EST (Thu, 23 Dec 2010)
@@ -164,6 +164,28 @@
     { // alternative forms of attributes. Allow sequences to take in
       // stl containers.
 
+ std::vector<char> v;
+ BOOST_TEST(test_attr("abc", char_ >> *char_, v));
+ BOOST_TEST(v.size() == 3);
+ BOOST_TEST(v[0] == 'a');
+ BOOST_TEST(v[1] == 'b');
+ BOOST_TEST(v[2] == 'c');
+ }
+
+ { // alternative forms of attributes. Allow sequences to take in
+ // stl containers.
+
+ std::vector<char> v;
+ BOOST_TEST(test_attr("abc", char_ >> -(+char_), v));
+ BOOST_TEST(v.size() == 3);
+ BOOST_TEST(v[0] == 'a');
+ BOOST_TEST(v[1] == 'b');
+ BOOST_TEST(v[2] == 'c');
+ }
+
+ { // alternative forms of attributes. Allow sequences to take in
+ // stl containers.
+
         std::string s;
         BOOST_TEST(test_attr("foobar", string("foo") >> string("bar"), s));
         BOOST_TEST(s == "foobar");


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