Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r72198 - in branches/release: . boost boost/spirit boost/spirit/home boost/spirit/home/classic/actor boost/spirit/home/classic/debug boost/spirit/home/karma boost/spirit/home/karma/auxiliary boost/spirit/home/karma/nonterminal boost/spirit/home/karma/stream boost/spirit/home/lex/lexer boost/spirit/home/lex/lexer/lexertl boost/spirit/home/qi/auxiliary boost/spirit/home/qi/detail boost/spirit/home/support boost/spirit/home/support/utree boost/spirit/home/support/utree/detail boost/spirit/include libs libs/spirit libs/spirit/doc libs/spirit/doc/support libs/spirit/phoenix libs/spirit/phoenix/test/bind libs/spirit/test libs/spirit/test/lex libs/spirit/test/qi libs/spirit/test/support
From: hartmut.kaiser_at_[hidden]
Date: 2011-05-26 18:26:12


Author: hkaiser
Date: 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
New Revision: 72198
URL: http://svn.boost.org/trac/boost/changeset/72198

Log:
Spirit: merging from trunk
Added:
   branches/release/boost/spirit/home/lex/lexer/lexertl/position_token.hpp
      - copied unchanged from r72115, /trunk/boost/spirit/home/lex/lexer/lexertl/position_token.hpp
   branches/release/boost/spirit/include/lex_lexertl_position_token.hpp
      - copied unchanged from r72115, /trunk/boost/spirit/include/lex_lexertl_position_token.hpp
   branches/release/boost/spirit/include/lex_lexertl_token.hpp
      - copied unchanged from r72115, /trunk/boost/spirit/include/lex_lexertl_token.hpp
   branches/release/libs/spirit/test/lex/token_iterpair.cpp
      - copied unchanged from r72115, /trunk/libs/spirit/test/lex/token_iterpair.cpp
   branches/release/libs/spirit/test/lex/token_moretypes.cpp
      - copied unchanged from r72115, /trunk/libs/spirit/test/lex/token_moretypes.cpp
   branches/release/libs/spirit/test/lex/token_omit.cpp
      - copied unchanged from r72115, /trunk/libs/spirit/test/lex/token_omit.cpp
   branches/release/libs/spirit/test/lex/token_onetype.cpp
      - copied unchanged from r72115, /trunk/libs/spirit/test/lex/token_onetype.cpp
Properties modified:
   branches/release/ (props changed)
   branches/release/boost/ (props changed)
   branches/release/boost/spirit/ (props changed)
   branches/release/boost/spirit/home/ (props changed)
   branches/release/boost/spirit/home/karma/ (props changed)
   branches/release/boost/spirit/home/support/attributes.hpp (contents, props changed)
   branches/release/libs/ (props changed)
   branches/release/libs/spirit/ (props changed)
   branches/release/libs/spirit/doc/ (props changed)
   branches/release/libs/spirit/phoenix/ (props changed)
   branches/release/libs/spirit/test/ (props changed)
Text files modified:
   branches/release/boost/spirit/home/classic/actor/ref_value_actor.hpp | 3
   branches/release/boost/spirit/home/classic/debug/minimal.hpp | 2
   branches/release/boost/spirit/home/karma/auxiliary/lazy.hpp | 43 +++++++++
   branches/release/boost/spirit/home/karma/nonterminal/rule.hpp | 1
   branches/release/boost/spirit/home/karma/stream/stream.hpp | 4
   branches/release/boost/spirit/home/lex/lexer/lexer.hpp | 7 +
   branches/release/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp | 142 ++++++++++++++++++++++++++++++++++
   branches/release/boost/spirit/home/lex/lexer/lexertl/lexer.hpp | 8 +
   branches/release/boost/spirit/home/lex/lexer/lexertl/token.hpp | 48 ++++++-----
   branches/release/boost/spirit/home/qi/auxiliary/lazy.hpp | 57 +++++++++++--
   branches/release/boost/spirit/home/qi/detail/assign_to.hpp | 4
   branches/release/boost/spirit/home/support/attributes.hpp | 47 +++++++++--
   branches/release/boost/spirit/home/support/utree/detail/utree_detail1.hpp | 4
   branches/release/boost/spirit/home/support/utree/detail/utree_detail2.hpp | 163 +++++++++++++++++++++++----------------
   branches/release/boost/spirit/home/support/utree/operators.hpp | 15 ++
   branches/release/boost/spirit/home/support/utree/utree.hpp | 94 ++++++++--------------
   branches/release/boost/spirit/include/phoenix_algorithm.hpp | 2
   branches/release/boost/spirit/include/qi_as_string.hpp | 2
   branches/release/libs/spirit/doc/support/utree.qbk | 18 +--
   branches/release/libs/spirit/doc/what_s_new.qbk | 9 ++
   branches/release/libs/spirit/phoenix/test/bind/bind_member_variable_tests.cpp | 16 +-
   branches/release/libs/spirit/test/Jamfile | 14 ++-
   branches/release/libs/spirit/test/lex/lexertl1.cpp | 44 ++++++++++
   branches/release/libs/spirit/test/qi/pass_container2.cpp | 2
   branches/release/libs/spirit/test/qi/pass_container3.cpp | 25 +++++
   branches/release/libs/spirit/test/support/utree.cpp | 49 +++++++----
   26 files changed, 595 insertions(+), 228 deletions(-)

Modified: branches/release/boost/spirit/home/classic/actor/ref_value_actor.hpp
==============================================================================
--- branches/release/boost/spirit/home/classic/actor/ref_value_actor.hpp (original)
+++ branches/release/boost/spirit/home/classic/actor/ref_value_actor.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -1,5 +1,6 @@
 /*=============================================================================
     Copyright (c) 2003 Jonathan de Halleux (dehalleux_at_[hidden])
+ Copyright (c) 2011 Bryce Lelbach
     http://spirit.sourceforge.net/
 
   Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -8,6 +9,8 @@
 #ifndef BOOST_SPIRIT_ACTOR_REF_VALUE_ACTOR_HPP
 #define BOOST_SPIRIT_ACTOR_REF_VALUE_ACTOR_HPP
 
+#include <boost/detail/workaround.hpp>
+
 #include <boost/spirit/home/classic/namespace.hpp>
 
 namespace boost { namespace spirit {

Modified: branches/release/boost/spirit/home/classic/debug/minimal.hpp
==============================================================================
--- branches/release/boost/spirit/home/classic/debug/minimal.hpp (original)
+++ branches/release/boost/spirit/home/classic/debug/minimal.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -35,7 +35,7 @@
 #endif
 
 #if !defined(BOOST_SPIRIT_DEBUG_FLAGS)
-#define BOOST_SPIRIT_DEBUG_FLAGS SPIRIT_DEBUG_FLAGS_MAX
+#define BOOST_SPIRIT_DEBUG_FLAGS BOOST_SPIRIT_DEBUG_FLAGS_MAX
 #endif
 
 #if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME)

Modified: branches/release/boost/spirit/home/karma/auxiliary/lazy.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/auxiliary/lazy.hpp (original)
+++ branches/release/boost/spirit/home/karma/auxiliary/lazy.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -44,6 +44,40 @@
     using spirit::lazy;
     typedef modify<karma::domain> karma_modify;
 
+ namespace detail
+ {
+ template <typename Generator, typename OutputIterator, typename Context
+ , typename Delimiter, typename Attribute>
+ bool lazy_generate_impl(Generator const& g, OutputIterator& sink
+ , Context& context, Delimiter const& delim
+ , Attribute const& attr, mpl::false_)
+ {
+ return g.generate(sink, context, delim, attr);
+ }
+
+ template <typename Generator, typename OutputIterator, typename Context
+ , typename Delimiter, typename Attribute>
+ bool lazy_generate_impl(Generator const& g, OutputIterator& sink
+ , Context& context, Delimiter const& delim
+ , Attribute const& attr, mpl::true_)
+ {
+ // If DeducedAuto is false (semantic actions is present), the
+ // component's attribute is unused.
+ return g.generate(sink, context, delim, unused);
+ }
+
+ template <typename Generator, typename OutputIterator, typename Context
+ , typename Delimiter, typename Attribute>
+ bool lazy_generate_impl_main(Generator const& g, OutputIterator& sink
+ , Context& context, Delimiter const& delim, Attribute const& attr)
+ {
+ // If DeducedAuto is true (no semantic action), we pass the parser's
+ // attribute on to the component.
+ typedef typename traits::has_semantic_action<Generator>::type auto_rule;
+ return lazy_generate_impl(g, sink, context, delim, attr, auto_rule());
+ }
+ }
+
     template <typename Function, typename Modifiers>
     struct lazy_generator : generator<lazy_generator<Function, Modifiers> >
     {
@@ -86,9 +120,10 @@
         bool generate(OutputIterator& sink, Context& context,
             Delimiter const& d, Attribute const& attr) const
         {
- return compile<karma::domain>(func(unused, context)
+ return detail::lazy_generate_impl_main(
+ compile<karma::domain>(func(unused, context)
               , karma_modify()(tag::lazy_eval(), modifiers))
- .generate(sink, context, d, attr);
+ , sink, context, d, attr);
         }
 
         template <typename Context>
@@ -162,11 +197,11 @@
         bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
           , Attribute const& attr) const
         {
- return compile<karma::domain>(
+ return detail::lazy_generate_impl_main(compile<karma::domain>(
                 proto::make_expr<proto::tag::subscript>(
                     function(unused, ctx), subject)
                   , karma_modify()(tag::lazy_eval(), modifiers))
- .generate(sink, ctx, d, attr);
+ , sink, ctx, d, attr);
         }
 
         template <typename Context>

Modified: branches/release/boost/spirit/home/karma/nonterminal/rule.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/nonterminal/rule.hpp (original)
+++ branches/release/boost/spirit/home/karma/nonterminal/rule.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -30,6 +30,7 @@
 #include <boost/spirit/home/support/argument.hpp>
 #include <boost/spirit/home/support/context.hpp>
 #include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/karma/delimit_out.hpp>
 #include <boost/spirit/home/karma/detail/attributes.hpp>
 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
 #include <boost/spirit/home/support/nonterminal/locals.hpp>

Modified: branches/release/boost/spirit/home/karma/stream/stream.hpp
==============================================================================
--- branches/release/boost/spirit/home/karma/stream/stream.hpp (original)
+++ branches/release/boost/spirit/home/karma/stream/stream.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -229,7 +229,7 @@
             typename OutputIterator, typename Context, typename Delimiter
           , typename Attribute>
         bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attribute const&)
+ , Attribute const&) const
         {
             typedef karma::detail::iterator_sink<
                 OutputIterator, Char, CharEncoding, Tag
@@ -251,7 +251,7 @@
         bool generate(
             karma::detail::output_iterator<
                 karma::ostream_iterator<T1, Char, Traits>, Properties
- >& sink, Context&, Delimiter const& d, Attribute const&)
+ >& sink, Context&, Delimiter const& d, Attribute const&) const
         {
             typedef karma::detail::output_iterator<
                 karma::ostream_iterator<T1, Char, Traits>, Properties

Modified: branches/release/boost/spirit/home/lex/lexer/lexer.hpp
==============================================================================
--- branches/release/boost/spirit/home/lex/lexer/lexer.hpp (original)
+++ branches/release/boost/spirit/home/lex/lexer/lexer.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -265,6 +265,13 @@
                 return *this;
             }
 
+ // explicitly tell the lexer that the given state will be defined
+ // (useful in conjunction with "*")
+ std::size_t add_state(char_type const* state = 0)
+ {
+ return def.add_state(state ? state : def.initial_state().c_str());
+ }
+
             adder add;
             pattern_adder add_pattern;
 

Modified: branches/release/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp
==============================================================================
--- branches/release/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp (original)
+++ branches/release/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -10,6 +10,7 @@
 #pragma once
 #endif
 
+#include <boost/spirit/home/qi/detail/assign_to.hpp>
 #include <boost/spirit/home/support/detail/lexer/generator.hpp>
 #include <boost/spirit/home/support/detail/lexer/rules.hpp>
 #include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
@@ -17,6 +18,7 @@
 #include <boost/spirit/home/lex/lexer/lexertl/semantic_action_data.hpp>
 #include <boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp>
 #include <boost/mpl/bool.hpp>
+#include <boost/optional.hpp>
 
 namespace boost { namespace spirit { namespace lex { namespace lexertl
 {
@@ -401,6 +403,146 @@
             // silence MSVC warning C4512: assignment operator could not be generated
             data& operator= (data const&);
         };
+
+ ///////////////////////////////////////////////////////////////////////
+ // does support lexer semantic actions, may support state, is used for
+ // position_token exposing exactly one type
+ template <typename Iterator, typename HasState, typename TokenValue>
+ class data<Iterator, mpl::true_, HasState, boost::optional<TokenValue> >
+ : public data<Iterator, mpl::false_, HasState, TokenValue>
+ {
+ public:
+ typedef semantic_actions<Iterator, HasState, data>
+ semantic_actions_type;
+
+ protected:
+ typedef data<Iterator, mpl::false_, HasState, TokenValue> base_type;
+ typedef typename base_type::char_type char_type;
+ typedef typename semantic_actions_type::functor_wrapper_type
+ functor_wrapper_type;
+
+ public:
+ typedef Iterator base_iterator_type;
+ typedef boost::optional<TokenValue> token_value_type;
+ typedef boost::optional<TokenValue> const& get_value_type;
+ typedef typename base_type::state_type state_type;
+ typedef typename base_type::state_name_type state_name_type;
+
+ typedef detail::wrap_action<functor_wrapper_type
+ , Iterator, data, std::size_t> wrap_action_type;
+
+ template <typename IterData>
+ data (IterData const& data_, Iterator& first, Iterator const& last)
+ : base_type(data_, first, last)
+ , actions_(data_.actions_), hold_()
+ , has_value_(false), has_hold_(false)
+ {
+ spirit::traits::assign_to(first, last, value_);
+ has_value_ = true;
+ }
+
+ // invoke attached semantic actions, if defined
+ BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
+ , std::size_t& id, std::size_t unique_id, Iterator& end)
+ {
+ return actions_.invoke_actions(state, id, unique_id, end, *this);
+ }
+
+ // The function less() is used by the implementation of the support
+ // function lex::less(). Its functionality is equivalent to flex'
+ // function yyless(): it returns an iterator positioned to the
+ // nth input character beyond the current start iterator (i.e. by
+ // assigning the return value to the placeholder '_end' it is
+ // possible to return all but the first n characters of the current
+ // token back to the input stream).
+ Iterator const& less(Iterator& it, int n)
+ {
+ it = this->get_first();
+ std::advance(it, n);
+ return it;
+ }
+
+ // The function more() is used by the implementation of the support
+ // function lex::more(). Its functionality is equivalent to flex'
+ // function yymore(): it tells the lexer that the next time it
+ // matches a rule, the corresponding token should be appended onto
+ // the current token value rather than replacing it.
+ void more()
+ {
+ hold_ = this->get_first();
+ has_hold_ = true;
+ }
+
+ // The function lookahead() is used by the implementation of the
+ // support function lex::lookahead. It can be used to implement
+ // lookahead for lexer engines not supporting constructs like flex'
+ // a/b (match a, but only when followed by b)
+ bool lookahead(std::size_t id, std::size_t state = std::size_t(~0))
+ {
+ Iterator end = end_;
+ std::size_t unique_id = boost::lexer::npos;
+ bool bol = this->bol_;
+
+ if (std::size_t(~0) == state)
+ state = this->state_;
+
+ typedef basic_iterator_tokeniser<Iterator> tokenizer;
+ return id == tokenizer::next(this->state_machine_, state,
+ bol, end, this->get_eoi(), unique_id);
+ }
+
+ // The adjust_start() and revert_adjust_start() are helper
+ // functions needed to implement the functionality required for
+ // lex::more(). It is called from the functor body below.
+ bool adjust_start()
+ {
+ if (!has_hold_)
+ return false;
+
+ std::swap(this->get_first(), hold_);
+ has_hold_ = false;
+ return true;
+ }
+ void revert_adjust_start()
+ {
+ // this will be called only if adjust_start above returned true
+ std::swap(this->get_first(), hold_);
+ has_hold_ = true;
+ }
+
+ token_value_type const& get_value() const
+ {
+ if (!has_value_) {
+ spirit::traits::assign_to(this->get_first(), end_, value_);
+ has_value_ = true;
+ }
+ return value_;
+ }
+ template <typename Value>
+ void set_value(Value const& val)
+ {
+ value_ = val;
+ has_value_ = true;
+ }
+ void set_end(Iterator const& it)
+ {
+ end_ = it;
+ }
+ bool has_value() const { return has_value_; }
+ void reset_value() { has_value_ = false; }
+
+ protected:
+ semantic_actions_type const& actions_;
+ Iterator hold_; // iterator needed to support lex::more()
+ Iterator end_; // iterator pointing to end of matched token
+ mutable token_value_type value_; // token value to use
+ mutable bool has_value_; // 'true' if value_ is valid
+ bool has_hold_; // 'true' if hold_ is valid
+
+ private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ data& operator= (data const&);
+ };
     }
 }}}}
 

Modified: branches/release/boost/spirit/home/lex/lexer/lexertl/lexer.hpp
==============================================================================
--- branches/release/boost/spirit/home/lex/lexer/lexertl/lexer.hpp (original)
+++ branches/release/boost/spirit/home/lex/lexer/lexertl/lexer.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -302,8 +302,12 @@
                 typedef typename
                     basic_rules_type::string_size_t_map::value_type
                 state_type;
- BOOST_FOREACH(state_type const& s, rules_.statemap())
- actions_.add_action(unique_id, s.second, wrapper_type::call(act));
+
+ std::size_t states = rules_.statemap().size();
+ BOOST_FOREACH(state_type const& s, rules_.statemap()) {
+ for (std::size_t j = 0; j < states; ++j)
+ actions_.add_action(unique_id + j, s.second, wrapper_type::call(act));
+ }
             }
             else {
                 actions_.add_action(unique_id, state, wrapper_type::call(act));

Modified: branches/release/boost/spirit/home/lex/lexer/lexertl/token.hpp
==============================================================================
--- branches/release/boost/spirit/home/lex/lexer/lexertl/token.hpp (original)
+++ branches/release/boost/spirit/home/lex/lexer/lexertl/token.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -24,12 +24,15 @@
 #include <boost/fusion/include/value_at.hpp>
 #include <boost/detail/iterator.hpp>
 #include <boost/variant.hpp>
+#include <boost/mpl/bool.hpp>
 #include <boost/mpl/vector.hpp>
-#include <boost/mpl/insert.hpp>
+#include <boost/mpl/is_sequence.hpp>
 #include <boost/mpl/begin.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/identity.hpp>
+#include <boost/mpl/insert.hpp>
+#include <boost/mpl/vector.hpp>
 #include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/type_traits/is_same.hpp>
 #include <boost/range/iterator_range.hpp>
 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
 #include <boost/static_assert.hpp>
@@ -137,16 +140,17 @@
         token(id_type id, std::size_t, token_value_type)
           : id_(id) {}
 
+ token_value_type& value() { return unused; }
+ token_value_type const& value() const { return unused; }
+
 #if defined(BOOST_SPIRIT_DEBUG)
         token(id_type id, std::size_t, Iterator const& first
               , Iterator const& last)
           : matched_(first, last)
- , id_(id)
- {}
+ , id_(id) {}
 #else
         token(id_type id, std::size_t, Iterator const&, Iterator const&)
- : id_(id)
- {}
+ : id_(id) {}
 #endif
 
         // this default conversion operator is needed to allow the direct
@@ -526,13 +530,13 @@
         }
     };
 
- 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> >
- {};
+// 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
@@ -551,13 +555,13 @@
         }
     };
 
- 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> >
- {};
+// 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
@@ -603,7 +607,7 @@
                 attribute_type;
 
             iterpair_type const& ip = get<iterpair_type>(t.value());
- attr = attribute_type(t.id(), get<iterpair_type>(t.value()));
+ attr = attribute_type(t.id(), ip);
         }
     };
 

Modified: branches/release/boost/spirit/home/qi/auxiliary/lazy.hpp
==============================================================================
--- branches/release/boost/spirit/home/qi/auxiliary/lazy.hpp (original)
+++ branches/release/boost/spirit/home/qi/auxiliary/lazy.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -43,6 +43,44 @@
     using spirit::lazy;
     typedef modify<qi::domain> qi_modify;
 
+ namespace detail
+ {
+ template <typename Parser, typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool lazy_parse_impl(Parser const& p
+ , Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr, mpl::false_)
+ {
+ return p.parse(first, last, context, skipper, attr);
+ }
+
+ template <typename Parser, typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool lazy_parse_impl(Parser const& p
+ , Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr, mpl::true_)
+ {
+ // If DeducedAuto is false (semantic actions is present), the
+ // component's attribute is unused.
+ return p.parse(first, last, context, skipper, unused);
+ }
+
+ template <typename Parser, typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool lazy_parse_impl_main(Parser const& p
+ , Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr)
+ {
+ // If DeducedAuto is true (no semantic action), we pass the parser's
+ // attribute on to the component.
+ typedef typename traits::has_semantic_action<Parser>::type auto_rule;
+ return lazy_parse_impl(p, first, last, context, skipper, attr, auto_rule());
+ }
+ }
+
     template <typename Function, typename Modifiers>
     struct lazy_parser : parser<lazy_parser<Function, Modifiers> >
     {
@@ -82,9 +120,10 @@
           , Context& context, Skipper const& skipper
           , Attribute& attr) const
         {
- return compile<qi::domain>(function(unused, context)
+ return detail::lazy_parse_impl_main(
+ compile<qi::domain>(function(unused, context)
                 , qi_modify()(tag::lazy_eval(), modifiers))
- .parse(first, last, context, skipper, attr);
+ , first, last, context, skipper, attr);
         }
 
         template <typename Context>
@@ -103,7 +142,7 @@
 
 
     template <typename Function, typename Subject, typename Modifiers>
- struct lazy_directive
+ struct lazy_directive
         : unary_parser<lazy_directive<Function, Subject, Modifiers> >
     {
         typedef Subject subject_type;
@@ -155,12 +194,12 @@
           , Context& context, Skipper const& skipper
           , Attribute& attr) const
         {
- return compile<qi::domain>(
+ return detail::lazy_parse_impl_main(compile<qi::domain>(
                 proto::make_expr<proto::tag::subscript>(
                     function(unused, context)
- , subject
- ), qi_modify()(tag::lazy_eval(), modifiers))
- .parse(first, last, context, skipper, attr);
+ , subject)
+ , qi_modify()(tag::lazy_eval(), modifiers))
+ , first, last, context, skipper, attr);
         }
 
         template <typename Context>
@@ -230,7 +269,7 @@
       : handles_container<
           typename qi::lazy_parser<Actor, Modifiers>::template
               attribute<Context, Iterator>::parser_type
- , Attribute, Context, Iterator>
+ , Attribute, Context, Iterator>
     {};
 
     template <typename Subject, typename Actor, typename Modifiers
@@ -241,7 +280,7 @@
       : handles_container<
           typename qi::lazy_directive<Actor, Subject, Modifiers>::template
               attribute<Context, Iterator>::parser_type
- , Attribute, Context, Iterator>
+ , Attribute, Context, Iterator>
     {};
 }}}
 

Modified: branches/release/boost/spirit/home/qi/detail/assign_to.hpp
==============================================================================
--- branches/release/boost/spirit/home/qi/detail/assign_to.hpp (original)
+++ branches/release/boost/spirit/home/qi/detail/assign_to.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -68,7 +68,9 @@
         call(Iterator const& first, Iterator const& last
           , boost::optional<Attribute>& attr)
         {
- attr = Attribute(first, last);
+ Attribute val;
+ assign_to(first, last, val);
+ attr = val;
         }
     };
 

Modified: branches/release/boost/spirit/home/support/attributes.hpp
==============================================================================
--- branches/release/boost/spirit/home/support/attributes.hpp (original)
+++ branches/release/boost/spirit/home/support/attributes.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -112,6 +112,34 @@
     // Find out if T can be a weak substitute for Expected attribute
     namespace detail
     {
+ // A type, which is convertible to the attribute is at the same time
+ // usable as its weak substitute.
+ template <typename T, typename Expected, typename Enable = void>
+ struct is_weak_substitute_impl : is_convertible<T, Expected> {};
+
+// // An exposed attribute is a weak substitute for a supplied container
+// // attribute if it is a weak substitute for its value_type. This is
+// // true as all character parsers exposing compatible with a container
+// // attribute having the corresponding character type as its value_type.
+// template <typename T, typename Expected>
+// struct is_weak_substitute_for_value_type
+// : is_weak_substitute<T, typename container_value<Expected>::type>
+// {};
+//
+// template <typename T, typename Expected>
+// struct is_weak_substitute_impl<T, Expected,
+// typename enable_if<
+// mpl::and_<
+// mpl::not_<is_string<T> >
+// , is_string<Expected>
+// , is_weak_substitute_for_value_type<T, Expected> >
+// >::type>
+// : mpl::true_
+// {};
+
+ // An exposed container attribute is a weak substitute for a supplied
+ // container attribute if and only if their value_types are weak
+ // substitutes.
         template <typename T, typename Expected>
         struct value_type_is_weak_substitute
           : is_weak_substitute<
@@ -119,33 +147,32 @@
               , typename container_value<Expected>::type>
         {};
 
- template <typename T, typename Expected, typename Enable = void>
- struct is_weak_substitute_impl : is_convertible<T, Expected> {};
-
         template <typename T, typename Expected>
         struct is_weak_substitute_impl<T, Expected,
             typename enable_if<
                 mpl::and_<
- is_container<T>,
- is_container<Expected>,
- value_type_is_weak_substitute<T, Expected> >
+ is_container<T>
+ , is_container<Expected>
+ , value_type_is_weak_substitute<T, Expected> >
>::type>
           : mpl::true_ {};
 
+ // Two fusion sequences are weak substitutes if and only if their
+ // elements are pairwise weak substitutes.
         template <typename T, typename Expected>
         struct is_weak_substitute_impl<T, Expected,
             typename enable_if<
                 mpl::and_<
- fusion::traits::is_sequence<T>,
- fusion::traits::is_sequence<Expected>,
- mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> > >
+ fusion::traits::is_sequence<T>
+ , fusion::traits::is_sequence<Expected>
+ , mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> > >
>::type>
           : mpl::true_ {};
 
         // If this is not defined, the main template definition above will return
         // true if T is convertible to the first type in a fusion::vector. We
         // globally declare any non-Fusion sequence T as not compatible with any
- // Fusion sequence Expected.
+ // Fusion sequence 'Expected'.
         template <typename T, typename Expected>
         struct is_weak_substitute_impl<T, Expected,
             typename enable_if<

Modified: branches/release/boost/spirit/home/support/utree/detail/utree_detail1.hpp
==============================================================================
--- branches/release/boost/spirit/home/support/utree/detail/utree_detail1.hpp (original)
+++ branches/release/boost/spirit/home/support/utree/detail/utree_detail1.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -1,6 +1,7 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
     Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2011 Bryce Lelbach
 
     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)
@@ -16,7 +17,6 @@
     struct visit_impl;
 
     struct index_impl;
- struct assign_impl;
 
     ///////////////////////////////////////////////////////////////////////////
     // Our POD double linked list. Straightforward implementation.
@@ -105,7 +105,7 @@
             small_string_size = buff_size-sizeof(char);
 
         static std::size_t const
- max_string_len = small_string_size - 1;
+ max_string_len = small_string_size - 3;
 
         struct heap_store
         {

Modified: branches/release/boost/spirit/home/support/utree/detail/utree_detail2.hpp
==============================================================================
--- branches/release/boost/spirit/home/support/utree/detail/utree_detail2.hpp (original)
+++ branches/release/boost/spirit/home/support/utree/detail/utree_detail2.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -1,6 +1,7 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
     Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2011 Bryce Lelbach
 
     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)
@@ -43,15 +44,11 @@
 
     inline short fast_string::tag() const
     {
- // warning the tag is not allowed for fast_string!!! it's only
- // placed here to avoid excess padding.
         return (int(buff[small_string_size-2]) << 8) + (unsigned char)buff[small_string_size-1];
     }
 
     inline void fast_string::tag(short tag)
     {
- // warning the tag is not allowed for fast_string!!! it's only
- // placed here to avoid excess padding.
         buff[small_string_size-2] = tag >> 8;
         buff[small_string_size-1] = tag & 0xff;
     }
@@ -66,7 +63,7 @@
         if (is_heap_allocated())
             return heap.size;
         else
- return max_string_len - buff[small_string_size - 1];
+ return max_string_len - buff[max_string_len];
     }
 
     inline char const* fast_string::str() const
@@ -82,12 +79,12 @@
     {
         unsigned const size = l-f;
         char* str;
- if (size < small_string_size)
+ if (size < max_string_len)
         {
             // if it fits, store it in-situ; small_string_size minus the length
             // of the string is placed in buff[small_string_size - 1]
             str = buff;
- buff[small_string_size - 1] = static_cast<char>(max_string_len - size);
+ buff[max_string_len] = static_cast<char>(max_string_len - size);
             info() &= ~0x1;
         }
         else
@@ -646,7 +643,13 @@
     }
 
     template <typename F>
- utree stored_function<F>::operator()(scope const& env) const
+ utree stored_function<F>::operator()(utree const& env) const
+ {
+ return f(env);
+ }
+
+ template <typename F>
+ utree stored_function<F>::operator()(utree& env)
     {
         return f(env);
     }
@@ -670,7 +673,13 @@
     }
 
     template <typename F>
- utree referenced_function<F>::operator()(scope const& env) const
+ utree referenced_function<F>::operator()(utree const& env) const
+ {
+ return f(env);
+ }
+
+ template <typename F>
+ utree referenced_function<F>::operator()(utree& env)
     {
         return f(env);
     }
@@ -774,22 +783,20 @@
         set_type(type::any_type);
     }
 
- template <typename F>
- inline utree::utree(stored_function<F> const& pf_)
+ inline utree::utree(function_base const& pf_)
     {
         s.initialize();
- pf = new stored_function<F>(pf_);
+ pf = pf_.clone();
         set_type(type::function_type);
     }
     
- template <typename F>
- inline utree::utree(referenced_function<F> const& pf_)
+ inline utree::utree(function_base* pf_)
     {
         s.initialize();
- pf = new referenced_function<F>(pf_);
+ pf = pf_;
         set_type(type::function_type);
     }
-
+
     template <typename Iter>
     inline utree::utree(boost::iterator_range<Iter> r)
     {
@@ -932,25 +939,23 @@
         set_type(type::any_type);
         return *this;
     }
-
- template <typename F>
- utree& utree::operator=(stored_function<F> const& pf_)
+
+ utree& utree::operator=(function_base const& pf_)
     {
         free();
- pf = new stored_function<F>(pf_);
+ pf = pf_.clone();
         set_type(type::function_type);
         return *this;
     }
-
- template <typename F>
- utree& utree::operator=(referenced_function<F> const& pf_)
+
+ utree& utree::operator=(function_base* pf_)
     {
         free();
- pf = new referenced_function<F>(pf_);
+ pf = pf_;
         set_type(type::function_type);
         return *this;
     }
-
+
     template <typename Iter>
     inline utree& utree::operator=(boost::iterator_range<Iter> r)
     {
@@ -1265,10 +1270,22 @@
         if (t == type::list_type)
             return l.size;
 
+ if (t == type::string_type)
+ return s.size();
+
+ if (t == type::symbol_type)
+ return s.size();
+
+ if (t == type::binary_type)
+ return s.size();
+
+ if (t == type::string_range_type)
+ return sr.last - sr.first;
+
         if (t != type::nil_type)
             BOOST_THROW_EXCEPTION(
                 bad_type_exception
- ("size() called on non-list utree type",
+ ("size() called on non-list and non-string utree type",
                      get_type()));
 
         return 0;
@@ -1285,16 +1302,20 @@
             return p->front();
         if (get_type() == type::range_type)
         {
- BOOST_ASSERT(r.first != 0);
+ if (!r.first)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("front() called on empty utree range"));
             return r.first->val;
         }
 
         // otherwise...
- if (get_type() != type::list_type || l.first == 0)
+ if (get_type() != type::list_type)
             BOOST_THROW_EXCEPTION(
                 bad_type_exception
- ("front() called on non-list utree type",
- get_type()));
+ ("front() called on non-list utree type", get_type()));
+ else if (!l.first)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("front() called on empty utree list"));
 
         return l.first->val;
     }
@@ -1305,16 +1326,20 @@
             return p->back();
         if (get_type() == type::range_type)
         {
- BOOST_ASSERT(r.last != 0);
+ if (!r.last)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("back() called on empty utree range"));
             return r.last->val;
         }
 
         // otherwise...
- if (get_type() != type::list_type || l.last == 0)
+ if (get_type() != type::list_type)
             BOOST_THROW_EXCEPTION(
                 bad_type_exception
- ("back() called on non-list utree type",
- get_type()));
+ ("back() called on non-list utree type", get_type()));
+ else if (!l.last)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("back() called on empty utree list"));
 
         return l.last->val;
     }
@@ -1325,16 +1350,20 @@
             return ((utree const*)p)->front();
         if (get_type() == type::range_type)
         {
- BOOST_ASSERT(r.first != 0);
+ if (!r.first)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("front() called on empty utree range"));
             return r.first->val;
         }
 
         // otherwise...
- if (get_type() != type::list_type || l.first == 0)
+ if (get_type() != type::list_type)
             BOOST_THROW_EXCEPTION(
                 bad_type_exception
- ("front() called on non-list utree type",
- get_type()));
+ ("front() called on non-list utree type", get_type()));
+ else if (!l.first)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("front() called on empty utree list"));
 
         return l.first->val;
     }
@@ -1345,16 +1374,20 @@
             return ((utree const*)p)->back();
         if (get_type() == type::range_type)
         {
- BOOST_ASSERT(r.last != 0);
+ if (!r.last)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("back() called on empty utree range"));
             return r.last->val;
         }
 
         // otherwise...
- if (get_type() != type::list_type || l.last == 0)
+ if (get_type() != type::list_type)
             BOOST_THROW_EXCEPTION(
                 bad_type_exception
- ("back() called on non-list utree type",
- get_type()));
+ ("back() called on non-list utree type", get_type()));
+ else if (!l.last)
+ BOOST_THROW_EXCEPTION(
+ empty_exception("back() called on empty utree list"));
 
         return l.last->val;
     }
@@ -1462,6 +1495,7 @@
             case type::symbol_type:
             case type::binary_type:
                 s.copy(other.s);
+ s.tag(other.s.tag());
                 break;
             case type::list_type:
                 l.copy(other.l);
@@ -1549,39 +1583,15 @@
 
     inline short utree::tag() const
     {
- switch (get_type())
- {
- case type::string_type:
- case type::string_range_type:
- case type::binary_type:
- case type::symbol_type:
- BOOST_THROW_EXCEPTION(
- bad_type_exception(
- "tag() called on string utree type", get_type()));
- default:
- break;
- }
         return s.tag();
     }
 
     inline void utree::tag(short tag)
     {
- switch (get_type())
- {
- case type::string_type:
- case type::string_range_type:
- case type::binary_type:
- case type::symbol_type:
- BOOST_THROW_EXCEPTION(
- bad_type_exception(
- "tag() called on string utree type", get_type()));
- default:
- break;
- }
         s.tag(tag);
     }
 
- inline utree utree::eval(scope const& env) const
+ inline utree utree::eval(utree const& env) const
     {
         if (get_type() != type::function_type)
             BOOST_THROW_EXCEPTION(
@@ -1589,6 +1599,25 @@
                     "eval() called on non-function utree type", get_type()));
         return (*pf)(env);
     }
+
+ inline utree utree::eval(utree& env) const
+ {
+ if (get_type() != type::function_type)
+ BOOST_THROW_EXCEPTION(
+ bad_type_exception(
+ "eval() called on non-function utree type", get_type()));
+ return (*pf)(env);
+ }
+
+ inline utree utree::operator() (utree const& env) const
+ {
+ return eval(env);
+ }
+
+ inline utree utree::operator() (utree& env) const
+ {
+ return eval(env);
+ }
 }}
 
 #if defined(BOOST_MSVC)

Modified: branches/release/boost/spirit/home/support/utree/operators.hpp
==============================================================================
--- branches/release/boost/spirit/home/support/utree/operators.hpp (original)
+++ branches/release/boost/spirit/home/support/utree/operators.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -1,6 +1,7 @@
 /*=============================================================================
     Copyright (c) 2001-2011 Joel de Guzman
     Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2011 Bryce Lelbach
 
     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)
@@ -15,7 +16,9 @@
 #endif
 
 #include <exception>
-#include <ios>
+#if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
+ #include <ios>
+#endif
 #include <boost/spirit/home/support/utree/utree.hpp>
 #include <boost/preprocessor/cat.hpp>
 #include <boost/throw_exception.hpp>
@@ -32,12 +35,12 @@
     bool operator<=(utree const& a, utree const& b);
     bool operator>=(utree const& a, utree const& b);
 
- // Input and output
+#if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
+ // output
     std::ostream& operator<<(std::ostream& out, utree const& x);
- std::istream& operator>>(std::istream& in, utree& x);
-
     std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x);
     std::ostream& operator<<(std::ostream& out, utree::nil_type const& x);
+#endif
 
     // Logical operators
     utree operator&&(utree const& a, utree const& b);
@@ -190,6 +193,7 @@
         }
     };
 
+#if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
     struct utree_print
     {
         typedef void result_type;
@@ -271,6 +275,7 @@
             return (*this)("<function>");
         }
     };
+#endif
 
     template <typename Base>
     struct logical_function
@@ -494,6 +499,7 @@
         return !(a < b);
     }
 
+#if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
     inline std::ostream& operator<<(std::ostream& out, utree const& x)
     {
         utree::visit(x, utree_print(out));
@@ -509,6 +515,7 @@
     {
         return out;
     }
+#endif
 
     BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(and_, a&&b)
     BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(or_, a||b)

Modified: branches/release/boost/spirit/home/support/utree/utree.hpp
==============================================================================
--- branches/release/boost/spirit/home/support/utree/utree.hpp (original)
+++ branches/release/boost/spirit/home/support/utree/utree.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -48,6 +48,11 @@
        precondition is violated as the `utree` instance holds some other type.
     */
     struct bad_type_exception /*: utree_exception*/;
+
+ /*`The `empty_exception` is thrown whenever a precondition of a list
+ or range utree method is violated due to the list or range being empty.
+ */
+ struct empty_exception /*: utree_exception*/;
     //]
 
     //[utree_types
@@ -67,7 +72,7 @@
             any_type, // A pointer or reference to any C++ type.
             function_type, // A utree holding a stored_function<F> object,
                                 // where F is an unary function object taking a
- // scope as it's parameter and returning a
+ // utree as it's parameter and returning a
                                 // utree.
 
             // numeric atoms
@@ -137,9 +142,21 @@
 
         virtual ~bad_type_exception() throw() {}
 
- virtual const char* what() const throw()
+ virtual char const* what() const throw()
         { return msg.c_str(); }
     };
+
+ struct empty_exception : utree_exception
+ {
+ char const* msg;
+
+ empty_exception(char const* error) : msg(error) {}
+
+ virtual ~empty_exception() throw() {}
+
+ virtual char const* what() const throw()
+ { return msg; }
+ };
 
     ///////////////////////////////////////////////////////////////////////////
     // A typed string with parametric Base storage. The storage can be any
@@ -222,13 +239,13 @@
     // Our function type
     ///////////////////////////////////////////////////////////////////////////
     class utree;
- class scope;
 
     //[utree_function_object_interface
     struct function_base
     {
         virtual ~function_base() {}
- virtual utree operator()(scope const& env) const = 0;
+ virtual utree operator()(utree const& env) const = 0;
+ virtual utree operator()(utree& env) = 0;
 
         // Calling f.clone() must return a newly allocated function_base
         // instance that is equal to f.
@@ -241,7 +258,8 @@
         F f;
         stored_function(F f = F());
         virtual ~stored_function();
- virtual utree operator()(scope const& env) const;
+ virtual utree operator()(utree const& env) const;
+ virtual utree operator()(utree& env);
         virtual function_base* clone() const;
     };
     
@@ -251,7 +269,8 @@
         F& f;
         referenced_function(F& f);
         virtual ~referenced_function();
- virtual utree operator()(scope const& env) const;
+ virtual utree operator()(utree const& env) const;
+ virtual utree operator()(utree& env);
         virtual function_base* clone() const;
     };
     //]
@@ -416,20 +435,13 @@
         utree(boost::iterator_range<Iterator>);
         template <class Iterator>
         reference operator=(boost::iterator_range<Iterator>);
-
- // This initializes a `function_type` node, which can store an
- // arbitrary function or function object.
- template <class F>
- utree(stored_function<F> const&);
- template <class F>
- reference operator=(stored_function<F> const&);
-
- // This initializes a `function_type` node, storing by reference
- // instead of copying the function object.
- template <class F>
- utree(referenced_function<F> const&);
- template <class F>
- reference operator=(referenced_function<F> const&);
+
+ // This initializes a `function_type` node from a polymorphic function
+ // object pointer (takes ownership) or reference.
+ utree(function_base const&);
+ reference operator=(function_base const&);
+ utree(function_base*);
+ reference operator=(function_base*);
 
         // This initializes either a `string_type`, a `symbol_type`, or a
         // `binary_type` node (depending on the template parameter `type_`),
@@ -554,8 +566,11 @@
         short tag() const;
         void tag(short);
 
- utree eval(scope const&) const;
+ utree eval(utree const&) const;
+ utree eval(utree&) const;
 
+ utree operator() (utree const&) const;
+ utree operator() (utree&) const;
     //<-
     protected:
         void ensure_list_type(char const* failed_in = "ensure_list_type()");
@@ -566,7 +581,6 @@
         template <class UTreeX, class UTreeY>
         friend struct detail::visit_impl;
         friend struct detail::index_impl;
- friend struct detail::assign_impl;
 
         type::info get_type() const;
         void set_type(type::info);
@@ -615,42 +629,6 @@
     utree::invalid_type const invalid = {};
     utree::nil_type const nil = {};
     utree::list_type const empty_list = utree::list_type();
-
- ///////////////////////////////////////////////////////////////////////////
- //[utree_scope
- class scope : public boost::iterator_range<utree*>
- {
- public:
- scope(utree* first = 0,
- utree* last = 0,
- scope const* parent = 0)
- //<-
- : boost::iterator_range<utree*>(first, last)
- , parent(parent)
- , depth(parent? parent->depth + 1 : 0) {}
- //->
-
- scope const* outer() const
- //<-
- {
- return parent;
- }
- //->
-
- std::size_t level() const
- //<-
- {
- return depth;
- }
- //->
-
- //<-
- private:
- scope const* parent;
- std::size_t depth;
- //->
- };
- //]
 }}
 
 #if defined(BOOST_MSVC)

Modified: branches/release/boost/spirit/include/phoenix_algorithm.hpp
==============================================================================
--- branches/release/boost/spirit/include/phoenix_algorithm.hpp (original)
+++ branches/release/boost/spirit/include/phoenix_algorithm.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -12,7 +12,7 @@
 #ifndef BOOST_SPIRIT_USE_PHOENIX_V3
 #include <boost/spirit/home/phoenix/algorithm.hpp>
 #else
-#include <boost/phoenix/algorithm.hpp>
+#include <boost/phoenix/stl/algorithm.hpp>
 #endif
 
 #endif

Modified: branches/release/boost/spirit/include/qi_as_string.hpp
==============================================================================
--- branches/release/boost/spirit/include/qi_as_string.hpp (original)
+++ branches/release/boost/spirit/include/qi_as_string.hpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -13,6 +13,6 @@
 #pragma once
 #endif
 
-#include <boost/spirit/home/qi/directive/as_string.hpp>
+#include <boost/spirit/home/qi/directive/as.hpp>
 
 #endif

Modified: branches/release/libs/spirit/doc/support/utree.qbk
==============================================================================
--- branches/release/libs/spirit/doc/support/utree.qbk (original)
+++ branches/release/libs/spirit/doc/support/utree.qbk 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -12,19 +12,17 @@
 
 [section:utree The utree data structure]
 
-The `utree` data structure is a generic, hierarchical, and dynamic data
-structure that can represent abstract syntax trees. It's well integrated with
-__qi__ and __karma__. It can be passed as an attribute while parsing almost any
-grammars. At the same time, it can be used as an attribute to generate output
-from.
+`utree` is a dynamically-typed hierarchical data structure that can represent
+abstract syntax trees. It's well integrated with __qi__ and __karma__. `utree`
+can be passed as an attribute to almost any grammar. `utree`'s type system is
+implemented through the use of a discriminated union and type punning.
+
+`utree` has a minimal memory footprint. The data structure size is 16 bytes on a
+32-bit platform, and 32 bytes on 64-bit a platform (`4*sizeof(void*)`). Being a
+container of itself, it can represent tree structures.
 
 [utree_types]
 
-[note utree has minimal memory footprint. The data structure size is
-16 bytes on a 32-bit platform, and 32 bytes on 64-bit a platform
-(`4*sizeof(void*)`). Being a container of itself, it can represent tree
-structures.]
-
 The UTF-8 string, UTF-8 symbol, and binary data types are internally stored
 either directly as the node data (small string optimization applied), or they
 are allocated from the heap, storing the pointer to the allocated data in the

Modified: branches/release/libs/spirit/doc/what_s_new.qbk
==============================================================================
--- branches/release/libs/spirit/doc/what_s_new.qbk (original)
+++ branches/release/libs/spirit/doc/what_s_new.qbk 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -98,6 +98,15 @@
   using `lex::char_` and `lex::string`. Both primitives now accept a second
   parameter which will be interpreted as the requested token id for any token
   generated from this definition.
+* Added a new token type `lex::lexertl::position_token<>`, which is essentially
+ plup-in compatible with the existing `lex::lexertl::token<>` class. However
+ it additionally stores the pair of iterators pointing to the underlying
+ matched input sequence as an iterator_range.
+
+[heading Bug Fixes in Lex]
+
+* Fixed a problem with associating token definitions with all states (using
+ `"*"` as the state name) when actions were attached to them.
 
 [heading Making Stuff Work]
 

Modified: branches/release/libs/spirit/phoenix/test/bind/bind_member_variable_tests.cpp
==============================================================================
--- branches/release/libs/spirit/phoenix/test/bind/bind_member_variable_tests.cpp (original)
+++ branches/release/libs/spirit/phoenix/test/bind/bind_member_variable_tests.cpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -86,18 +86,18 @@
 int
 main()
 {
- write_test<test::x>(identity());
- write_test<test::x>(add_pointer());
- write_test<test::xx>(identity());
- write_test<test::xx>(add_pointer());
+ write_test<test::x>(::identity());
+ write_test<test::x>(::add_pointer());
+ write_test<test::xx>(::identity());
+ write_test<test::xx>(::add_pointer());
 
- read_test<test::x>(identity());
+ read_test<test::x>(::identity());
     //read_test<test::x>(constify()); // this fails because of capture by value.
- read_test<test::x>(add_pointer());
+ read_test<test::x>(::add_pointer());
     read_test<test::x>(add_const_pointer());
- read_test<test::xx>(identity());
+ read_test<test::xx>(::identity());
     //read_test<test::xx>(constify());// this fails because of capture by value.
- read_test<test::xx>(add_pointer());
+ read_test<test::xx>(::add_pointer());
     read_test<test::xx>(add_const_pointer());
     return boost::report_errors();
 }

Modified: branches/release/libs/spirit/test/Jamfile
==============================================================================
--- branches/release/libs/spirit/test/Jamfile (original)
+++ branches/release/libs/spirit/test/Jamfile 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -254,20 +254,24 @@
     ###########################################################################
     test-suite spirit_v2/lex :
 
+ [ run lex/auto_switch_lexerstate.cpp : : : : lex_auto_switch_lexerstate ]
+ [ run lex/dedent_handling_phoenix.cpp : : : : lex_dedent_handling_phoenix ]
+ [ run lex/id_type_enum.cpp : : : : lex_id_type_enum ]
      [ run lex/lexertl1.cpp : : : : lex_lexertl1 ]
      [ run lex/lexertl2.cpp : : : : lex_lexertl2 ]
      [ run lex/lexertl3.cpp : : : : lex_lexertl3 ]
      [ run lex/lexertl4.cpp : : : : lex_lexertl4 ]
      [ run lex/lexertl5.cpp : : : : lex_lexertl5 ]
- [ run lex/state_switcher.cpp : : : : lex_state_switcher ]
      [ run lex/lexer_state_switcher.cpp : : : : lex_lexer_state_switcher ]
+ [ run lex/semantic_actions.cpp : : : : lex_semantic_actions ]
      [ run lex/set_token_value.cpp : : : : lex_set_token_value ]
- [ run lex/dedent_handling_phoenix.cpp : : : : lex_dedent_handling_phoenix ]
      [ run lex/set_token_value_phoenix.cpp : : : : lex_set_token_value_phoenix ]
- [ run lex/semantic_actions.cpp : : : : lex_semantic_actions ]
- [ run lex/auto_switch_lexerstate.cpp : : : : lex_auto_switch_lexerstate ]
- [ run lex/id_type_enum.cpp : : : : lex_id_type_enum ]
+ [ run lex/state_switcher.cpp : : : : lex_state_switcher ]
      [ run lex/string_token_id.cpp : : : : lex_string_token_id ]
+ [ run lex/token_iterpair.cpp : : : : lex_token_iterpair ]
+ [ run lex/token_moretypes.cpp : : : : lex_token_moretypes ]
+ [ run lex/token_omit.cpp : : : : lex_token_omit ]
+ [ run lex/token_onetype.cpp : : : : lex_token_onetype ]
 
     ;
 

Modified: branches/release/libs/spirit/test/lex/lexertl1.cpp
==============================================================================
--- branches/release/libs/spirit/test/lex/lexertl1.cpp (original)
+++ branches/release/libs/spirit/test/lex/lexertl1.cpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -5,6 +5,7 @@
 
 #include <boost/detail/lightweight_test.hpp>
 #include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_lexertl_position_token.hpp>
 #include "test.hpp"
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -25,6 +26,8 @@
     token_def cpp_comment ("\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)", CPPCOMMENT);
 
     typedef std::string::iterator base_iterator_type;
+
+ // test with default token type
     typedef lex::lexertl::token<base_iterator_type> token_type;
     typedef lex::lexertl::lexer<token_type> lexer_type;
     typedef lex::lexer<lexer_type> lexer_def;
@@ -65,5 +68,46 @@
         BOOST_TEST(test (lex, "/", '/'));
     }
 
+ // test with position_token
+ typedef lex::lexertl::position_token<base_iterator_type> position_token_type;
+ typedef lex::lexertl::lexer<position_token_type> position_lexer_type;
+ typedef lex::lexer<position_lexer_type> position_lexer_def;
+
+ {
+ // initialize lexer
+ position_lexer_def lex;
+ lex.self = c_comment;
+ lex.self += cpp_comment;
+
+ // test lexer for two different input strings
+ BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+ BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+ }
+
+ {
+ // initialize lexer
+ position_lexer_def lex;
+ lex.self = c_comment | cpp_comment;
+
+ // test lexer for two different input strings
+ BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+ BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+ }
+
+ {
+ // initialize lexer
+ position_lexer_def lex;
+ lex.self = token_def('+') | '-' | c_comment;
+ lex.self += lex::char_('*') | '/' | cpp_comment;
+
+ // test lexer for two different input strings
+ BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+ BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+ BOOST_TEST(test (lex, "+", '+'));
+ BOOST_TEST(test (lex, "-", '-'));
+ BOOST_TEST(test (lex, "*", '*'));
+ BOOST_TEST(test (lex, "/", '/'));
+ }
+
     return boost::report_errors();
 }

Modified: branches/release/libs/spirit/test/qi/pass_container2.cpp
==============================================================================
--- branches/release/libs/spirit/test/qi/pass_container2.cpp (original)
+++ branches/release/libs/spirit/test/qi/pass_container2.cpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -246,7 +246,7 @@
                              at_c<0>(v[1]) == 3 && at_c<1>(v[1]) == 4.0);
     }
 
-// doesn't work yet
+// doesn't currently work
 // {
 // std::vector<std::vector<char> > v2;
 // BOOST_TEST(test_attr("ab1cd123", *(alpha >> alpha | +digit), v2) &&

Modified: branches/release/libs/spirit/test/qi/pass_container3.cpp
==============================================================================
--- branches/release/libs/spirit/test/qi/pass_container3.cpp (original)
+++ branches/release/libs/spirit/test/qi/pass_container3.cpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -5,6 +5,9 @@
 
 // compilation test only
 
+#include <boost/config/warning_disable.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
 #include <string>
 #include <vector>
 
@@ -13,6 +16,10 @@
 
 #include <boost/variant.hpp>
 
+#include "test.hpp"
+
+using namespace spirit_test;
+
 //////////////////////////////////////////////////////////////////////////////
 struct ast; // Forward declaration
 
@@ -38,9 +45,21 @@
 {
     namespace qi = boost::spirit::qi;
 
- qi::rule<char const*, ast()> num_expr;
- num_expr = (*(qi::char_ >> num_expr))[ qi::_1 ];
+ {
+ qi::rule<char const*, ast()> num_expr;
+ num_expr = (*(qi::char_ >> num_expr))[ qi::_1 ];
+ }
+
+// doesn't currently work
+// {
+// qi::rule<char const*, std::string()> str = "abc";
+// qi::rule<char const*, std::string()> r =
+// '"' >> *('\\' >> qi::char_ | str) >> "'";
+//
+// std::string s;
+// BOOST_TEST(test_attr("\"abc\\a\"", r, s) && s == "abca");
+// }
 
- return 0;
+ return boost::report_errors();
 }
 

Modified: branches/release/libs/spirit/test/support/utree.cpp
==============================================================================
--- branches/release/libs/spirit/test/support/utree.cpp (original)
+++ branches/release/libs/spirit/test/support/utree.cpp 2011-05-26 18:26:09 EDT (Thu, 26 May 2011)
@@ -32,7 +32,7 @@
 
 struct one_two_three
 {
- boost::spirit::utree operator()(boost::spirit::scope) const
+ boost::spirit::utree operator()(boost::spirit::utree) const
     {
         return boost::spirit::utree(123);
     }
@@ -40,7 +40,7 @@
 
 struct this_
 {
- boost::spirit::utree operator()(boost::spirit::scope) const
+ boost::spirit::utree operator()(boost::spirit::utree) const
     {
         return boost::spirit::utree(static_cast<int>(boost::hash_value(this)));
     }
@@ -159,42 +159,42 @@
         utree val;
         val.push_back(123);
         val.push_back("Chuckie");
- BOOST_TEST_EQ(val.size(), 2);
+ BOOST_TEST_EQ(val.size(), 2U);
         utree val2;
         val2.push_back(123.456);
         val2.push_back("Mah Doggie");
         val.push_back(val2);
- BOOST_TEST_EQ(val.size(), 3);
+ BOOST_TEST_EQ(val.size(), 3U);
         BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
         BOOST_TEST(check(val.front(), "123"));
 
         utree val3(nil);
         val3.swap(val);
- BOOST_TEST_EQ(val3.size(), 3);
+ BOOST_TEST_EQ(val3.size(), 3U);
         BOOST_TEST(check(val, "<nil>"));
         val3.swap(val);
         BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
         val.push_back("another string");
- BOOST_TEST_EQ(val.size(), 4);
+ BOOST_TEST_EQ(val.size(), 4U);
         BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
         val.pop_front();
         BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
         utree::iterator i = val.begin();
         ++++i;
         val.insert(i, "Right in the middle");
- BOOST_TEST_EQ(val.size(), 4);
+ BOOST_TEST_EQ(val.size(), 4U);
         BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" \"another string\" )"));
         val.pop_back();
         BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" )"));
- BOOST_TEST_EQ(val.size(), 3);
+ BOOST_TEST_EQ(val.size(), 3U);
         utree::iterator it = val.end(); --it;
         val.erase(it);
         BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
- BOOST_TEST_EQ(val.size(), 2);
+ BOOST_TEST_EQ(val.size(), 2U);
 
         val.insert(val.begin(), val2.begin(), val2.end());
         BOOST_TEST(check(val, "( 123.456 \"Mah Doggie\" \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
- BOOST_TEST_EQ(val.size(), 4);
+ BOOST_TEST_EQ(val.size(), 4U);
     }
 
     {
@@ -380,30 +380,45 @@
 
     {
         // check the tag
- // TODO: test tags on all utree types (some are invalid and should
- // throw).
+ // TODO: test tags on all utree types
         utree x;
         x.tag(123);
         BOOST_TEST_EQ(x.tag(), 123);
+
+ x = "hello world! my name is bob the builder";
+ x.tag(123);
+ BOOST_TEST_EQ(x.tag(), 123);
+
+ x.tag(456);
+ BOOST_TEST_EQ(x.tag(), 456);
+ BOOST_TEST_EQ(x.size(), 39U);
+ BOOST_TEST(check(x, "\"hello world! my name is bob the builder\""));
+
+ x = "hello";
+ x.tag(456);
+ BOOST_TEST_EQ(x.tag(), 456);
+
+ x.tag(789);
+ BOOST_TEST_EQ(x.tag(), 789);
+ BOOST_TEST_EQ(x.size(), 5U);
+ BOOST_TEST(check(x, "\"hello\""));
     }
 
     {
         // test functions
         using boost::spirit::stored_function;
- using boost::spirit::scope;
 
         utree f = stored_function<one_two_three>();
- f.eval(scope());
+ f.eval(utree());
     }
     
     {
         // test referenced functions
         using boost::spirit::referenced_function;
- using boost::spirit::scope;
 
         one_two_three f;
         utree ff = referenced_function<one_two_three>(f);
- BOOST_TEST_EQ(ff.eval(scope()), f(scope()));
+ BOOST_TEST_EQ(ff.eval(utree()), f(utree()));
     }
 
     {
@@ -420,7 +435,7 @@
         utree alias(utree::range(i, val.end()), shallow);
 
         BOOST_TEST(check(alias, "( 2 3 4 )"));
- BOOST_TEST_EQ(alias.size(), 3);
+ BOOST_TEST_EQ(alias.size(), 3U);
         BOOST_TEST_EQ(alias.front(), 2);
         BOOST_TEST_EQ(alias.back(), 4);
         BOOST_TEST(!alias.empty());


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