summaryrefslogtreecommitdiff
path: root/boost/xpressive
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/xpressive
downloadboost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/xpressive')
-rw-r--r--boost/xpressive/basic_regex.hpp295
-rw-r--r--boost/xpressive/detail/core/access.hpp132
-rw-r--r--boost/xpressive/detail/core/action.hpp39
-rw-r--r--boost/xpressive/detail/core/adaptor.hpp81
-rw-r--r--boost/xpressive/detail/core/finder.hpp221
-rw-r--r--boost/xpressive/detail/core/flow_control.hpp74
-rw-r--r--boost/xpressive/detail/core/icase.hpp42
-rw-r--r--boost/xpressive/detail/core/linker.hpp325
-rw-r--r--boost/xpressive/detail/core/list.hpp243
-rw-r--r--boost/xpressive/detail/core/matcher/action_matcher.hpp501
-rw-r--r--boost/xpressive/detail/core/matcher/alternate_end_matcher.hpp51
-rw-r--r--boost/xpressive/detail/core/matcher/alternate_matcher.hpp132
-rw-r--r--boost/xpressive/detail/core/matcher/any_matcher.hpp51
-rw-r--r--boost/xpressive/detail/core/matcher/assert_bol_matcher.hpp71
-rw-r--r--boost/xpressive/detail/core/matcher/assert_bos_matcher.hpp39
-rw-r--r--boost/xpressive/detail/core/matcher/assert_eol_matcher.hpp71
-rw-r--r--boost/xpressive/detail/core/matcher/assert_eos_matcher.hpp39
-rw-r--r--boost/xpressive/detail/core/matcher/assert_line_base.hpp47
-rw-r--r--boost/xpressive/detail/core/matcher/assert_word_matcher.hpp125
-rw-r--r--boost/xpressive/detail/core/matcher/attr_begin_matcher.hpp50
-rw-r--r--boost/xpressive/detail/core/matcher/attr_end_matcher.hpp47
-rw-r--r--boost/xpressive/detail/core/matcher/attr_matcher.hpp111
-rw-r--r--boost/xpressive/detail/core/matcher/charset_matcher.hpp67
-rw-r--r--boost/xpressive/detail/core/matcher/end_matcher.hpp98
-rw-r--r--boost/xpressive/detail/core/matcher/epsilon_matcher.hpp39
-rw-r--r--boost/xpressive/detail/core/matcher/keeper_matcher.hpp96
-rw-r--r--boost/xpressive/detail/core/matcher/literal_matcher.hpp66
-rw-r--r--boost/xpressive/detail/core/matcher/logical_newline_matcher.hpp83
-rw-r--r--boost/xpressive/detail/core/matcher/lookahead_matcher.hpp151
-rw-r--r--boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp168
-rw-r--r--boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp56
-rw-r--r--boost/xpressive/detail/core/matcher/mark_end_matcher.hpp64
-rw-r--r--boost/xpressive/detail/core/matcher/mark_matcher.hpp78
-rw-r--r--boost/xpressive/detail/core/matcher/optional_matcher.hpp121
-rw-r--r--boost/xpressive/detail/core/matcher/posix_charset_matcher.hpp73
-rw-r--r--boost/xpressive/detail/core/matcher/predicate_matcher.hpp174
-rw-r--r--boost/xpressive/detail/core/matcher/range_matcher.hpp87
-rw-r--r--boost/xpressive/detail/core/matcher/regex_byref_matcher.hpp77
-rw-r--r--boost/xpressive/detail/core/matcher/regex_matcher.hpp63
-rw-r--r--boost/xpressive/detail/core/matcher/repeat_begin_matcher.hpp69
-rw-r--r--boost/xpressive/detail/core/matcher/repeat_end_matcher.hpp121
-rw-r--r--boost/xpressive/detail/core/matcher/set_matcher.hpp100
-rw-r--r--boost/xpressive/detail/core/matcher/simple_repeat_matcher.hpp234
-rw-r--r--boost/xpressive/detail/core/matcher/string_matcher.hpp90
-rw-r--r--boost/xpressive/detail/core/matcher/true_matcher.hpp38
-rw-r--r--boost/xpressive/detail/core/matchers.hpp50
-rw-r--r--boost/xpressive/detail/core/optimize.hpp116
-rw-r--r--boost/xpressive/detail/core/peeker.hpp284
-rw-r--r--boost/xpressive/detail/core/quant_style.hpp129
-rw-r--r--boost/xpressive/detail/core/regex_domain.hpp24
-rw-r--r--boost/xpressive/detail/core/regex_impl.hpp212
-rw-r--r--boost/xpressive/detail/core/results_cache.hpp134
-rw-r--r--boost/xpressive/detail/core/state.hpp401
-rw-r--r--boost/xpressive/detail/core/sub_match_impl.hpp47
-rw-r--r--boost/xpressive/detail/core/sub_match_vector.hpp171
-rw-r--r--boost/xpressive/detail/detail_fwd.hpp486
-rw-r--r--boost/xpressive/detail/dynamic/dynamic.hpp337
-rw-r--r--boost/xpressive/detail/dynamic/matchable.hpp177
-rw-r--r--boost/xpressive/detail/dynamic/parse_charset.hpp365
-rw-r--r--boost/xpressive/detail/dynamic/parser.hpp360
-rw-r--r--boost/xpressive/detail/dynamic/parser_enum.hpp81
-rw-r--r--boost/xpressive/detail/dynamic/parser_traits.hpp474
-rw-r--r--boost/xpressive/detail/dynamic/sequence.hpp175
-rw-r--r--boost/xpressive/detail/static/compile.hpp104
-rw-r--r--boost/xpressive/detail/static/grammar.hpp365
-rw-r--r--boost/xpressive/detail/static/is_pure.hpp216
-rw-r--r--boost/xpressive/detail/static/modifier.hpp66
-rw-r--r--boost/xpressive/detail/static/placeholders.hpp120
-rw-r--r--boost/xpressive/detail/static/static.hpp259
-rw-r--r--boost/xpressive/detail/static/transforms/as_action.hpp322
-rw-r--r--boost/xpressive/detail/static/transforms/as_alternate.hpp131
-rw-r--r--boost/xpressive/detail/static/transforms/as_independent.hpp215
-rw-r--r--boost/xpressive/detail/static/transforms/as_inverse.hpp94
-rw-r--r--boost/xpressive/detail/static/transforms/as_marker.hpp58
-rw-r--r--boost/xpressive/detail/static/transforms/as_matcher.hpp48
-rw-r--r--boost/xpressive/detail/static/transforms/as_modifier.hpp85
-rw-r--r--boost/xpressive/detail/static/transforms/as_quantifier.hpp378
-rw-r--r--boost/xpressive/detail/static/transforms/as_sequence.hpp52
-rw-r--r--boost/xpressive/detail/static/transforms/as_set.hpp224
-rw-r--r--boost/xpressive/detail/static/transmogrify.hpp240
-rw-r--r--boost/xpressive/detail/static/type_traits.hpp60
-rw-r--r--boost/xpressive/detail/static/visitor.hpp143
-rw-r--r--boost/xpressive/detail/static/width_of.hpp287
-rw-r--r--boost/xpressive/detail/utility/algorithm.hpp174
-rw-r--r--boost/xpressive/detail/utility/any.hpp108
-rw-r--r--boost/xpressive/detail/utility/boyer_moore.hpp198
-rw-r--r--boost/xpressive/detail/utility/chset/basic_chset.hpp172
-rw-r--r--boost/xpressive/detail/utility/chset/basic_chset.ipp409
-rw-r--r--boost/xpressive/detail/utility/chset/chset.hpp165
-rw-r--r--boost/xpressive/detail/utility/chset/range_run.hpp102
-rw-r--r--boost/xpressive/detail/utility/chset/range_run.ipp235
-rw-r--r--boost/xpressive/detail/utility/cons.hpp309
-rw-r--r--boost/xpressive/detail/utility/counted_base.hpp84
-rw-r--r--boost/xpressive/detail/utility/dont_care.hpp25
-rw-r--r--boost/xpressive/detail/utility/hash_peek_bitset.hpp178
-rw-r--r--boost/xpressive/detail/utility/ignore_unused.hpp24
-rw-r--r--boost/xpressive/detail/utility/literals.hpp85
-rw-r--r--boost/xpressive/detail/utility/never_true.hpp25
-rw-r--r--boost/xpressive/detail/utility/save_restore.hpp55
-rw-r--r--boost/xpressive/detail/utility/sequence_stack.hpp259
-rw-r--r--boost/xpressive/detail/utility/symbols.hpp278
-rw-r--r--boost/xpressive/detail/utility/tracking_ptr.hpp494
-rw-r--r--boost/xpressive/detail/utility/traits_utils.hpp145
-rw-r--r--boost/xpressive/detail/utility/width.hpp94
-rw-r--r--boost/xpressive/match_results.hpp1395
-rw-r--r--boost/xpressive/regex_actions.hpp973
-rw-r--r--boost/xpressive/regex_algorithms.hpp994
-rw-r--r--boost/xpressive/regex_compiler.hpp744
-rw-r--r--boost/xpressive/regex_constants.hpp294
-rw-r--r--boost/xpressive/regex_error.hpp114
-rw-r--r--boost/xpressive/regex_iterator.hpp260
-rw-r--r--boost/xpressive/regex_primitives.hpp927
-rw-r--r--boost/xpressive/regex_token_iterator.hpp370
-rw-r--r--boost/xpressive/regex_traits.hpp107
-rw-r--r--boost/xpressive/sub_match.hpp392
-rw-r--r--boost/xpressive/traits/c_regex_traits.hpp413
-rw-r--r--boost/xpressive/traits/cpp_regex_traits.hpp694
-rw-r--r--boost/xpressive/traits/detail/c_ctype.hpp841
-rw-r--r--boost/xpressive/traits/null_regex_traits.hpp231
-rw-r--r--boost/xpressive/xpressive.hpp21
-rw-r--r--boost/xpressive/xpressive_dynamic.hpp25
-rw-r--r--boost/xpressive/xpressive_fwd.hpp243
-rw-r--r--boost/xpressive/xpressive_static.hpp32
-rw-r--r--boost/xpressive/xpressive_typeof.hpp150
124 files changed, 25328 insertions, 0 deletions
diff --git a/boost/xpressive/basic_regex.hpp b/boost/xpressive/basic_regex.hpp
new file mode 100644
index 0000000000..eedcd9a547
--- /dev/null
+++ b/boost/xpressive/basic_regex.hpp
@@ -0,0 +1,295 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file basic_regex.hpp
+/// Contains the definition of the basic_regex\<\> class template and its
+/// associated helper functions.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/xpressive_fwd.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/core/regex_domain.hpp>
+
+// Doxygen can't handle proto :-(
+#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+# include <boost/xpressive/detail/static/grammar.hpp>
+# include <boost/proto/extends.hpp>
+#endif
+
+#if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD
+# include <excpt.h> // for _exception_code()
+# include <malloc.h> // for _resetstkoflw()
+#endif
+
+namespace boost { namespace xpressive
+{
+
+namespace detail
+{
+ inline void throw_on_stack_error(bool stack_error)
+ {
+ BOOST_XPR_ENSURE_(!stack_error, regex_constants::error_stack, "Regex stack space exhausted");
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// basic_regex
+//
+/// \brief Class template basic_regex\<\> is a class for holding a compiled regular expression.
+template<typename BidiIter>
+struct basic_regex
+ : proto::extends<
+ proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0>
+ , basic_regex<BidiIter>
+ , detail::regex_domain
+ >
+{
+private:
+ typedef proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0> pimpl_type;
+ typedef proto::extends<pimpl_type, basic_regex<BidiIter>, detail::regex_domain> base_type;
+
+public:
+ typedef BidiIter iterator_type;
+ typedef typename iterator_value<BidiIter>::type char_type;
+ // For compatibility with std::basic_regex
+ typedef typename iterator_value<BidiIter>::type value_type;
+ typedef typename detail::string_type<char_type>::type string_type;
+ typedef regex_constants::syntax_option_type flag_type;
+
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ECMAScript = regex_constants::ECMAScript);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, icase = regex_constants::icase_);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, nosubs = regex_constants::nosubs);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, optimize = regex_constants::optimize);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, collate = regex_constants::collate);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, single_line = regex_constants::single_line);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_null = regex_constants::not_dot_null);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_newline = regex_constants::not_dot_newline);
+ BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ignore_white_space = regex_constants::ignore_white_space);
+
+ /// \post regex_id() == 0
+ /// \post mark_count() == 0
+ basic_regex()
+ : base_type()
+ {
+ }
+
+ /// \param that The basic_regex object to copy.
+ /// \post regex_id() == that.regex_id()
+ /// \post mark_count() == that.mark_count()
+ basic_regex(basic_regex<BidiIter> const &that)
+ : base_type(that)
+ {
+ }
+
+ /// \param that The basic_regex object to copy.
+ /// \post regex_id() == that.regex_id()
+ /// \post mark_count() == that.mark_count()
+ /// \return *this
+ basic_regex<BidiIter> &operator =(basic_regex<BidiIter> const &that)
+ {
+ proto::value(*this) = proto::value(that);
+ return *this;
+ }
+
+ /// Construct from a static regular expression.
+ ///
+ /// \param expr The static regular expression
+ /// \pre Expr is the type of a static regular expression.
+ /// \post regex_id() != 0
+ /// \post mark_count() \>= 0
+ template<typename Expr>
+ basic_regex(Expr const &expr)
+ : base_type()
+ {
+ BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type);
+ this->compile_(expr, is_valid_regex<Expr, char_type>());
+ }
+
+ /// Construct from a static regular expression.
+ ///
+ /// \param expr The static regular expression.
+ /// \pre Expr is the type of a static regular expression.
+ /// \post regex_id() != 0
+ /// \post mark_count() \>= 0
+ /// \throw std::bad_alloc on out of memory
+ /// \return *this
+ template<typename Expr>
+ basic_regex<BidiIter> &operator =(Expr const &expr)
+ {
+ BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type);
+ this->compile_(expr, is_valid_regex<Expr, char_type>());
+ return *this;
+ }
+
+ /// Returns the count of capturing sub-expressions in this regular expression
+ ///
+ std::size_t mark_count() const
+ {
+ return proto::value(*this) ? proto::value(*this)->mark_count_ : 0;
+ }
+
+ /// Returns a token which uniquely identifies this regular expression.
+ ///
+ regex_id_type regex_id() const
+ {
+ return proto::value(*this) ? proto::value(*this)->xpr_.get() : 0;
+ }
+
+ /// Swaps the contents of this basic_regex object with another.
+ ///
+ /// \param that The other basic_regex object.
+ /// \attention This is a shallow swap that does not do reference tracking.
+ /// If you embed a basic_regex object by reference in another
+ /// regular expression and then swap its contents with another
+ /// basic_regex object, the change will not be visible to the
+ /// enclosing regular expression. It is done this way to ensure
+ /// that swap() cannot throw.
+ /// \throw nothrow
+ void swap(basic_regex<BidiIter> &that) // throw()
+ {
+ proto::value(*this).swap(proto::value(that));
+ }
+
+ /// Factory method for building a regex object from a range of characters.
+ /// Equivalent to regex_compiler\< BidiIter \>().compile(begin, end, flags);
+ ///
+ /// \param begin The beginning of a range of characters representing the
+ /// regular expression to compile.
+ /// \param end The end of a range of characters representing the
+ /// regular expression to compile.
+ /// \param flags Optional bitmask that determines how the pat string is
+ /// interpreted. (See syntax_option_type.)
+ /// \return A basic_regex object corresponding to the regular expression
+ /// represented by the character range.
+ /// \pre [begin,end) is a valid range.
+ /// \pre The range of characters specified by [begin,end) contains a
+ /// valid string-based representation of a regular expression.
+ /// \throw regex_error when the range of characters has invalid regular
+ /// expression syntax.
+ template<typename InputIter>
+ static basic_regex<BidiIter> compile(InputIter begin, InputIter end, flag_type flags = regex_constants::ECMAScript)
+ {
+ return regex_compiler<BidiIter>().compile(begin, end, flags);
+ }
+
+ /// \overload
+ ///
+ template<typename InputRange>
+ static basic_regex<BidiIter> compile(InputRange const &pat, flag_type flags = regex_constants::ECMAScript)
+ {
+ return regex_compiler<BidiIter>().compile(pat, flags);
+ }
+
+ /// \overload
+ ///
+ static basic_regex<BidiIter> compile(char_type const *begin, flag_type flags = regex_constants::ECMAScript)
+ {
+ return regex_compiler<BidiIter>().compile(begin, flags);
+ }
+
+ /// \overload
+ ///
+ static basic_regex<BidiIter> compile(char_type const *begin, std::size_t len, flag_type flags)
+ {
+ return regex_compiler<BidiIter>().compile(begin, len, flags);
+ }
+
+private:
+ friend struct detail::core_access<BidiIter>;
+
+ // Avoid a common programming mistake. Construction from a string is
+ // ambiguous. It could mean:
+ // sregex rx = sregex::compile(str); // compile the string into a regex
+ // or
+ // sregex rx = as_xpr(str); // treat the string as a literal
+ // Since there is no easy way to disambiguate, it is disallowed. You must
+ // say what you mean.
+
+ /// INTERNAL ONLY
+ basic_regex(char_type const *);
+ /// INTERNAL ONLY
+ basic_regex(string_type const &);
+
+ /// INTERNAL ONLY
+ bool match_(detail::match_state<BidiIter> &state) const
+ {
+ #if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD
+ bool success = false, stack_error = false;
+ __try
+ {
+ success = proto::value(*this)->xpr_->match(state);
+ }
+ __except(_exception_code() == 0xC00000FDUL)
+ {
+ stack_error = true;
+ _resetstkoflw();
+ }
+ detail::throw_on_stack_error(stack_error);
+ return success;
+ #else
+ return proto::value(*this)->xpr_->match(state);
+ #endif
+ }
+
+ // Compiles valid static regexes into a state machine.
+ /// INTERNAL ONLY
+ template<typename Expr>
+ void compile_(Expr const &expr, mpl::true_)
+ {
+ detail::static_compile(expr, proto::value(*this).get());
+ }
+
+ // No-op for invalid static regexes.
+ /// INTERNAL ONLY
+ template<typename Expr>
+ void compile_(Expr const &, mpl::false_)
+ {
+ }
+};
+
+#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::ECMAScript;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::icase;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::nosubs;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::optimize;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::collate;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::single_line;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_null;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_newline;
+template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::ignore_white_space;
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// swap
+/// \brief Swaps the contents of two basic_regex objects.
+/// \param left The first basic_regex object.
+/// \param right The second basic_regex object.
+/// \attention This is a shallow swap that does not do reference tracking.
+/// If you embed a basic_regex object by reference in another
+/// regular expression and then swap its contents with another
+/// basic_regex object, the change will not be visible to the
+/// enclosing regular expression. It is done this way to ensure
+/// that swap() cannot throw.
+/// \throw nothrow
+template<typename BidiIter>
+inline void swap(basic_regex<BidiIter> &left, basic_regex<BidiIter> &right) // throw()
+{
+ left.swap(right);
+}
+
+}} // namespace boost::xpressive
+
+#endif // BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005
diff --git a/boost/xpressive/detail/core/access.hpp b/boost/xpressive/detail/core/access.hpp
new file mode 100644
index 0000000000..d984a432fa
--- /dev/null
+++ b/boost/xpressive/detail/core/access.hpp
@@ -0,0 +1,132 @@
+///////////////////////////////////////////////////////////////////////////////
+// access.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_ACCESS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_ACCESS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <boost/proto/traits.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/dynamic/matchable.hpp>
+#include <boost/xpressive/match_results.hpp> // for type_info_less
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// core_access
+//
+template<typename BidiIter>
+struct core_access
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ static std::size_t get_hidden_mark_count(basic_regex<BidiIter> const &rex)
+ {
+ return proto::value(rex)->hidden_mark_count_;
+ }
+
+ static bool match(basic_regex<BidiIter> const &rex, match_state<BidiIter> &state)
+ {
+ return rex.match_(state);
+ }
+
+ static shared_ptr<detail::regex_impl<BidiIter> > const &
+ get_regex_impl(basic_regex<BidiIter> const &rex)
+ {
+ return proto::value(rex).get();
+ }
+
+ static void init_sub_match_vector
+ (
+ sub_match_vector<BidiIter> &subs_vect
+ , sub_match_impl<BidiIter> *subs_ptr
+ , std::size_t size
+ )
+ {
+ subs_vect.init_(subs_ptr, size);
+ }
+
+ static void init_sub_match_vector
+ (
+ sub_match_vector<BidiIter> &subs_vect
+ , sub_match_impl<BidiIter> *subs_ptr
+ , std::size_t size
+ , sub_match_vector<BidiIter> const &that
+ )
+ {
+ subs_vect.init_(subs_ptr, size, that);
+ }
+
+ static void init_match_results
+ (
+ match_results<BidiIter> &what
+ , regex_id_type regex_id
+ , intrusive_ptr<traits<char_type> const> const &tr
+ , sub_match_impl<BidiIter> *sub_matches
+ , std::size_t size
+ , std::vector<named_mark<char_type> > const &named_marks
+ )
+ {
+ what.init_(regex_id, tr, sub_matches, size, named_marks);
+ }
+
+ static sub_match_vector<BidiIter> &get_sub_match_vector(match_results<BidiIter> &what)
+ {
+ return what.sub_matches_;
+ }
+
+ static sub_match_impl<BidiIter> *get_sub_matches(sub_match_vector<BidiIter> &subs)
+ {
+ return subs.sub_matches_;
+ }
+
+ static results_extras<BidiIter> &get_extras(match_results<BidiIter> &what)
+ {
+ return what.get_extras_();
+ }
+
+ static nested_results<BidiIter> &get_nested_results(match_results<BidiIter> &what)
+ {
+ return what.nested_results_;
+ }
+
+ static action_args_type &get_action_args(match_results<BidiIter> &what)
+ {
+ return what.args_;
+ }
+
+ static void set_prefix_suffix(match_results<BidiIter> &what, BidiIter begin, BidiIter end)
+ {
+ what.set_prefix_suffix_(begin, end);
+ }
+
+ static void reset(match_results<BidiIter> &what)
+ {
+ what.reset_();
+ }
+
+ static void set_base(match_results<BidiIter> &what, BidiIter base)
+ {
+ what.set_base_(base);
+ }
+
+ static BidiIter get_base(match_results<BidiIter> &what)
+ {
+ return *what.base_;
+ }
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/action.hpp b/boost/xpressive/detail/core/action.hpp
new file mode 100644
index 0000000000..bb54ee5f74
--- /dev/null
+++ b/boost/xpressive/detail/core/action.hpp
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////////
+// action.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_ACTION_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_ACTION_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/match_results.hpp> // for type_info_less
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // actionable
+ //
+ struct actionable
+ {
+ virtual ~actionable() {}
+ virtual void execute(action_args_type *) const {}
+
+ actionable()
+ : next(0)
+ {}
+
+ actionable const *next;
+ };
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/adaptor.hpp b/boost/xpressive/detail/core/adaptor.hpp
new file mode 100644
index 0000000000..6afecf2f92
--- /dev/null
+++ b/boost/xpressive/detail/core/adaptor.hpp
@@ -0,0 +1,81 @@
+///////////////////////////////////////////////////////////////////////////////
+// adaptor.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_ADAPTOR_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_ADAPTOR_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/ref.hpp>
+#include <boost/implicit_cast.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/dynamic/matchable.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// xpression_adaptor
+//
+// wrap a static xpression in a matchable interface so it can be stored
+// in and invoked from a basic_regex object.
+template<typename Xpr, typename Base>
+struct xpression_adaptor
+ : Base // either matchable or matchable_ex
+{
+ typedef typename Base::iterator_type iterator_type;
+ typedef typename iterator_value<iterator_type>::type char_type;
+
+ Xpr xpr_;
+
+ xpression_adaptor(Xpr const &xpr)
+ #if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4)) \
+ && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+ // Ugh, gcc has an optimizer bug which elides this c'tor call
+ // resulting in pure virtual function calls.
+ __attribute__((noinline))
+ #endif
+ : xpr_(xpr)
+ {
+ }
+
+ virtual bool match(match_state<iterator_type> &state) const
+ {
+ typedef typename boost::unwrap_reference<Xpr const>::type xpr_type;
+ return implicit_cast<xpr_type &>(this->xpr_).match(state);
+ }
+
+ void link(xpression_linker<char_type> &linker) const
+ {
+ this->xpr_.link(linker);
+ }
+
+ void peek(xpression_peeker<char_type> &peeker) const
+ {
+ this->xpr_.peek(peeker);
+ }
+
+private:
+ xpression_adaptor &operator =(xpression_adaptor const &);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// make_adaptor
+//
+template<typename Base, typename Xpr>
+inline intrusive_ptr<Base const> make_adaptor(Xpr const &xpr)
+{
+ return intrusive_ptr<Base const>(new xpression_adaptor<Xpr, Base>(xpr));
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/finder.hpp b/boost/xpressive/detail/core/finder.hpp
new file mode 100644
index 0000000000..56c6422719
--- /dev/null
+++ b/boost/xpressive/detail/core/finder.hpp
@@ -0,0 +1,221 @@
+/// Contains the definition of the basic_regex\<\> class template and its associated helper functions.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_FINDER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_FINDER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4189) // local variable is initialized but not referenced
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/utility/boyer_moore.hpp>
+#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// boyer_moore_finder
+//
+template<typename BidiIter, typename Traits>
+struct boyer_moore_finder
+ : finder<BidiIter>
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ boyer_moore_finder(char_type const *begin, char_type const *end, Traits const &tr, bool icase)
+ : bm_(begin, end, tr, icase)
+ {
+ }
+
+ bool ok_for_partial_matches() const
+ {
+ return false;
+ }
+
+ bool operator ()(match_state<BidiIter> &state) const
+ {
+ Traits const &tr = traits_cast<Traits>(state);
+ state.cur_ = this->bm_.find(state.cur_, state.end_, tr);
+ return state.cur_ != state.end_;
+ }
+
+private:
+ boyer_moore_finder(boyer_moore_finder const &);
+ boyer_moore_finder &operator =(boyer_moore_finder const &);
+
+ boyer_moore<BidiIter, Traits> bm_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// hash_peek_finder
+//
+template<typename BidiIter, typename Traits>
+struct hash_peek_finder
+ : finder<BidiIter>
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ hash_peek_finder(hash_peek_bitset<char_type> const &bset)
+ : bset_(bset)
+ {
+ }
+
+ bool operator ()(match_state<BidiIter> &state) const
+ {
+ Traits const &tr = traits_cast<Traits>(state);
+ state.cur_ = (this->bset_.icase()
+ ? this->find_(state.cur_, state.end_, tr, mpl::true_())
+ : this->find_(state.cur_, state.end_, tr, mpl::false_()));
+ return state.cur_ != state.end_;
+ }
+
+private:
+ hash_peek_finder(hash_peek_finder const &);
+ hash_peek_finder &operator =(hash_peek_finder const &);
+
+ template<typename ICase>
+ BidiIter find_(BidiIter begin, BidiIter end, Traits const &tr, ICase) const
+ {
+ for(; begin != end && !this->bset_.test(*begin, tr, ICase()); ++begin)
+ ;
+ return begin;
+ }
+
+ hash_peek_bitset<char_type> bset_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// line_start_finder
+//
+template<typename BidiIter, typename Traits, std::size_t Size = sizeof(typename iterator_value<BidiIter>::type)>
+struct line_start_finder
+ : finder<BidiIter>
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef typename iterator_difference<BidiIter>::type diff_type;
+ typedef typename Traits::char_class_type char_class_type;
+
+ line_start_finder(Traits const &tr)
+ : newline_(lookup_classname(tr, "newline"))
+ {
+ }
+
+ bool operator ()(match_state<BidiIter> &state) const
+ {
+ if(state.bos() && state.flags_.match_bol_)
+ {
+ return true;
+ }
+
+ Traits const &tr = traits_cast<Traits>(state);
+ BidiIter cur = state.cur_;
+ BidiIter const end = state.end_;
+ std::advance(cur, static_cast<diff_type>(-!state.bos()));
+
+ for(; cur != end; ++cur)
+ {
+ if(tr.isctype(*cur, this->newline_))
+ {
+ state.cur_ = ++cur;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+private:
+ line_start_finder(line_start_finder const &);
+ line_start_finder &operator =(line_start_finder const &);
+
+ char_class_type newline_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// line_start_finder
+//
+template<typename BidiIter, typename Traits>
+struct line_start_finder<BidiIter, Traits, 1u>
+ : finder<BidiIter>
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef typename iterator_difference<BidiIter>::type diff_type;
+ typedef typename Traits::char_class_type char_class_type;
+
+ line_start_finder(Traits const &tr)
+ {
+ char_class_type newline = lookup_classname(tr, "newline");
+ for(int j = 0; j < 256; ++j)
+ {
+ this->bits_[j] = tr.isctype(static_cast<char_type>(static_cast<unsigned char>(j)), newline);
+ }
+ }
+
+ bool operator ()(match_state<BidiIter> &state) const
+ {
+ if(state.bos() && state.flags_.match_bol_)
+ {
+ return true;
+ }
+
+ BidiIter cur = state.cur_;
+ BidiIter const end = state.end_;
+ std::advance(cur, static_cast<diff_type>(-!state.bos()));
+
+ for(; cur != end; ++cur)
+ {
+ if(this->bits_[static_cast<unsigned char>(*cur)])
+ {
+ state.cur_ = ++cur;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+private:
+ line_start_finder(line_start_finder const &);
+ line_start_finder &operator =(line_start_finder const &);
+
+ bool bits_[256];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// leading_simple_repeat_finder
+//
+template<typename BidiIter>
+struct leading_simple_repeat_finder
+ : finder<BidiIter>
+{
+ leading_simple_repeat_finder()
+ : finder<BidiIter>()
+ {}
+
+ bool operator ()(match_state<BidiIter> &state) const
+ {
+ state.cur_ = state.next_search_;
+ return true;
+ }
+
+private:
+ leading_simple_repeat_finder(leading_simple_repeat_finder const &);
+ leading_simple_repeat_finder &operator =(leading_simple_repeat_finder const &);
+};
+
+}}}
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/core/flow_control.hpp b/boost/xpressive/detail/core/flow_control.hpp
new file mode 100644
index 0000000000..2ca5156525
--- /dev/null
+++ b/boost/xpressive/detail/core/flow_control.hpp
@@ -0,0 +1,74 @@
+///////////////////////////////////////////////////////////////////////////////
+// flow_control.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_FLOW_CONTROL_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_FLOW_CONTROL_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// push_context_match
+//
+template<typename BidiIter>
+inline bool push_context_match
+(
+ regex_impl<BidiIter> const &impl
+ , match_state<BidiIter> &state
+ , matchable<BidiIter> const &next
+)
+{
+ // avoid infinite recursion
+ // BUGBUG this only catches direct infinite recursion, like sregex::compile("(?R)"), but
+ // not indirect infinite recursion where two rules invoke each other recursively.
+ if(state.is_active_regex(impl) && state.cur_ == state.sub_match(0).begin_)
+ {
+ return next.match(state);
+ }
+
+ // save state
+ match_context<BidiIter> context = state.push_context(impl, next, context);
+ detail::ignore_unused(context);
+
+ // match the nested regex and uninitialize the match context
+ // (reclaims the sub_match objects if necessary)
+ return state.pop_context(impl, impl.xpr_->match(state));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// pop_context_match
+//
+template<typename BidiIter>
+inline bool pop_context_match(match_state<BidiIter> &state)
+{
+ // save state
+ // BUGBUG nested regex could have changed state.traits_
+ match_context<BidiIter> &context(*state.context_.prev_context_);
+ state.swap_context(context);
+
+ // Finished matching the nested regex; now match the rest of the enclosing regex
+ bool success = context.next_ptr_->match(state);
+
+ // restore state
+ state.swap_context(context);
+ return success;
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
+
diff --git a/boost/xpressive/detail/core/icase.hpp b/boost/xpressive/detail/core/icase.hpp
new file mode 100644
index 0000000000..2b2bdc8541
--- /dev/null
+++ b/boost/xpressive/detail/core/icase.hpp
@@ -0,0 +1,42 @@
+///////////////////////////////////////////////////////////////////////////////
+// icase.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_ICASE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_ICASE_HPP_EAN_10_04_2005
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/detail/static/modifier.hpp>
+#include <boost/xpressive/detail/core/linker.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+namespace boost { namespace xpressive { namespace regex_constants
+{
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Makes a sub-expression case-insensitive.
+///
+/// Use icase() to make a sub-expression case-insensitive. For instance,
+/// "foo" >> icase(set['b'] >> "ar") will match "foo" exactly followed by
+/// "bar" irrespective of case.
+detail::modifier_op<detail::icase_modifier> const icase = {{}, regex_constants::icase_};
+
+} // namespace regex_constants
+
+using regex_constants::icase;
+
+namespace detail
+{
+ inline void ignore_unused_icase()
+ {
+ detail::ignore_unused(icase);
+ }
+}
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/detail/core/linker.hpp b/boost/xpressive/detail/core/linker.hpp
new file mode 100644
index 0000000000..e87e26d125
--- /dev/null
+++ b/boost/xpressive/detail/core/linker.hpp
@@ -0,0 +1,325 @@
+///////////////////////////////////////////////////////////////////////////////
+// linker.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_LINKER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_LINKER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_STD_LOCALE
+# include <locale>
+#endif
+#include <stack>
+#include <limits>
+#include <typeinfo>
+#include <boost/shared_ptr.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/version.hpp>
+
+#if BOOST_VERSION >= 103500
+# include <boost/fusion/include/for_each.hpp>
+#else
+# include <boost/spirit/fusion/algorithm/for_each.hpp>
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/dynamic/matchable.hpp>
+#include <boost/xpressive/detail/core/matchers.hpp>
+#include <boost/xpressive/detail/core/peeker.hpp>
+#include <boost/xpressive/detail/utility/never_true.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// icase_modifier
+//
+// wrapped by the modifier<> template and inserted into the xpression
+// template with the icase() helper function. icase_modifier morphs
+// a case-sensitive visitor into a case-insensitive visitor, which
+// causes all matchers visited to become case-insensitive.
+//
+struct icase_modifier
+{
+ template<typename Visitor>
+ struct apply {};
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct apply<xpression_visitor<BidiIter, ICase, Traits> >
+ {
+ typedef xpression_visitor<BidiIter, mpl::true_, Traits> type;
+ };
+
+ template<typename Visitor>
+ static typename apply<Visitor>::type
+ call(Visitor &visitor)
+ {
+ return typename apply<Visitor>::type(visitor.traits(), visitor.self());
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_traits_type : wrap a locale in the appropriate regex_traits
+//
+template<typename Locale, typename BidiIter>
+struct regex_traits_type
+{
+#ifndef BOOST_NO_STD_LOCALE
+
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ // if Locale is std::locale, wrap it in a cpp_regex_traits<Char>
+ typedef typename mpl::if_c
+ <
+ is_same<Locale, std::locale>::value
+ , cpp_regex_traits<char_type>
+ , Locale
+ >::type type;
+
+#else
+
+ typedef Locale type;
+
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// locale_modifier
+//
+// wrapped by the modifier<> template and inserted into the xpression
+// template with the imbue() helper function. Causes a sub-xpression to
+// use the specified Locale
+//
+template<typename Locale>
+struct locale_modifier
+{
+ typedef Locale locale_type;
+
+ locale_modifier(Locale const &loc)
+ : loc_(loc)
+ {
+ }
+
+ template<typename Visitor>
+ struct apply {};
+
+ template<typename BidiIter, typename ICase, typename OtherTraits>
+ struct apply<xpression_visitor<BidiIter, ICase, OtherTraits> >
+ {
+ typedef typename regex_traits_type<Locale, BidiIter>::type traits_type;
+ typedef xpression_visitor<BidiIter, ICase, traits_type> type;
+ };
+
+ template<typename Visitor>
+ typename apply<Visitor>::type
+ call(Visitor &visitor) const
+ {
+ return typename apply<Visitor>::type(this->loc_, visitor.self());
+ }
+
+ Locale getloc() const
+ {
+ return this->loc_;
+ }
+
+private:
+ Locale loc_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// xpression_linker
+//
+template<typename Char>
+struct xpression_linker
+{
+ template<typename Traits>
+ explicit xpression_linker(Traits const &tr)
+ : back_stack_()
+ , traits_(&tr)
+ , traits_type_(&typeid(Traits))
+ , has_backrefs_(false)
+ {
+ }
+
+ template<typename Matcher>
+ void accept(Matcher const &, void const *)
+ {
+ // no-op
+ }
+
+ template<typename Traits, typename ICase>
+ void accept(mark_matcher<Traits, ICase> const &, void const *)
+ {
+ this->has_backrefs_ = true;
+ }
+
+ template<typename Action>
+ void accept(action_matcher<Action> const &, void const *)
+ {
+ this->has_backrefs_ = true;
+ }
+
+ template<typename Predicate>
+ void accept(predicate_matcher<Predicate> const &, void const *)
+ {
+ this->has_backrefs_ = true;
+ }
+
+ void accept(repeat_begin_matcher const &, void const *next)
+ {
+ this->back_stack_.push(next);
+ }
+
+ template<typename Greedy>
+ void accept(repeat_end_matcher<Greedy> const &matcher, void const *)
+ {
+ matcher.back_ = this->back_stack_.top();
+ this->back_stack_.pop();
+ }
+
+ template<typename Alternates, typename Traits>
+ void accept(alternate_matcher<Alternates, Traits> const &matcher, void const *next)
+ {
+ xpression_peeker<Char> peeker(matcher.bset_, this->get_traits<Traits>());
+ this->alt_link(matcher.alternates_, next, &peeker);
+ }
+
+ void accept(alternate_end_matcher const &matcher, void const *)
+ {
+ matcher.back_ = this->back_stack_.top();
+ this->back_stack_.pop();
+ }
+
+ template<typename Xpr, typename Greedy>
+ void accept(optional_matcher<Xpr, Greedy> const &matcher, void const *next)
+ {
+ this->back_stack_.push(next);
+ matcher.xpr_.link(*this);
+ }
+
+ template<typename Xpr, typename Greedy>
+ void accept(optional_mark_matcher<Xpr, Greedy> const &matcher, void const *next)
+ {
+ this->back_stack_.push(next);
+ matcher.xpr_.link(*this);
+ }
+
+ template<typename Xpr>
+ void accept(keeper_matcher<Xpr> const &matcher, void const *)
+ {
+ matcher.xpr_.link(*this);
+ }
+
+ template<typename Xpr>
+ void accept(lookahead_matcher<Xpr> const &matcher, void const *)
+ {
+ matcher.xpr_.link(*this);
+ }
+
+ template<typename Xpr>
+ void accept(lookbehind_matcher<Xpr> const &matcher, void const *)
+ {
+ matcher.xpr_.link(*this);
+ }
+
+ template<typename Xpr, typename Greedy>
+ void accept(simple_repeat_matcher<Xpr, Greedy> const &matcher, void const *)
+ {
+ matcher.xpr_.link(*this);
+ }
+
+ // accessors
+ bool has_backrefs() const
+ {
+ return this->has_backrefs_;
+ }
+
+ // for use by alt_link_pred below
+ template<typename Xpr>
+ void alt_branch_link(Xpr const &xpr, void const *next, xpression_peeker<Char> *peeker)
+ {
+ this->back_stack_.push(next);
+ xpr.link(*this);
+ xpr.peek(*peeker);
+ }
+
+private:
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // alt_link_pred
+ //
+ struct alt_link_pred
+ {
+ xpression_linker<Char> *linker_;
+ xpression_peeker<Char> *peeker_;
+ void const *next_;
+
+ alt_link_pred
+ (
+ xpression_linker<Char> *linker
+ , xpression_peeker<Char> *peeker
+ , void const *next
+ )
+ : linker_(linker)
+ , peeker_(peeker)
+ , next_(next)
+ {
+ }
+
+ template<typename Xpr>
+ void operator ()(Xpr const &xpr) const
+ {
+ this->linker_->alt_branch_link(xpr, this->next_, this->peeker_);
+ }
+ };
+
+ template<typename BidiIter>
+ void alt_link
+ (
+ alternates_vector<BidiIter> const &alternates
+ , void const *next
+ , xpression_peeker<Char> *peeker
+ )
+ {
+ std::for_each(alternates.begin(), alternates.end(), alt_link_pred(this, peeker, next));
+ }
+
+ template<typename Alternates>
+ void alt_link
+ (
+ fusion::sequence_base<Alternates> const &alternates
+ , void const *next
+ , xpression_peeker<Char> *peeker
+ )
+ {
+#if BOOST_VERSION >= 103500
+ fusion::for_each(alternates.derived(), alt_link_pred(this, peeker, next));
+#else
+ fusion::for_each(alternates.cast(), alt_link_pred(this, peeker, next));
+#endif
+ }
+
+ template<typename Traits>
+ Traits const &get_traits() const
+ {
+ BOOST_ASSERT(*this->traits_type_ == typeid(Traits));
+ return *static_cast<Traits const *>(this->traits_);
+ }
+
+ std::stack<void const *> back_stack_;
+ void const *traits_;
+ std::type_info const *traits_type_;
+ bool has_backrefs_;
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/list.hpp b/boost/xpressive/detail/core/list.hpp
new file mode 100644
index 0000000000..f2135408ec
--- /dev/null
+++ b/boost/xpressive/detail/core/list.hpp
@@ -0,0 +1,243 @@
+///////////////////////////////////////////////////////////////////////////////
+// list.hpp
+// A simple implementation of std::list that allows incomplete
+// types, does no dynamic allocation in the default constructor,
+// and has a guarnteed O(1) splice.
+//
+// Copyright 2009 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_LIST_HPP_EAN_10_26_2009
+#define BOOST_XPRESSIVE_DETAIL_CORE_LIST_HPP_EAN_10_26_2009
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <cstddef>
+#include <iterator>
+#include <algorithm>
+#include <boost/assert.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // list
+ //
+ template<typename T>
+ struct list
+ {
+ private:
+ struct node_base
+ {
+ node_base *_prev;
+ node_base *_next;
+ };
+
+ struct node : node_base
+ {
+ explicit node(T const &value)
+ : _value(value)
+ {}
+
+ T _value;
+ };
+
+ node_base _sentry;
+
+ template<typename Ref = T &>
+ struct list_iterator
+ : boost::iterator_facade<list_iterator<Ref>, T, std::bidirectional_iterator_tag, Ref>
+ {
+ list_iterator(list_iterator<> const &it) : _node(it._node) {}
+ explicit list_iterator(node_base *n = 0) : _node(n) {}
+ private:
+ friend struct list<T>;
+ friend class boost::iterator_core_access;
+ Ref dereference() const { return static_cast<node *>(_node)->_value; }
+ void increment() { _node = _node->_next; }
+ void decrement() { _node = _node->_prev; }
+ bool equal(list_iterator const &it) const { return _node == it._node; }
+ node_base *_node;
+ };
+
+ public:
+ typedef T *pointer;
+ typedef T const *const_pointer;
+ typedef T &reference;
+ typedef T const &const_reference;
+ typedef list_iterator<> iterator;
+ typedef list_iterator<T const &> const_iterator;
+ typedef std::size_t size_type;
+
+ list()
+ {
+ _sentry._next = _sentry._prev = &_sentry;
+ }
+
+ list(list const &that)
+ {
+ _sentry._next = _sentry._prev = &_sentry;
+ const_iterator it = that.begin(), e = that.end();
+ for( ; it != e; ++it)
+ push_back(*it);
+ }
+
+ list &operator =(list const &that)
+ {
+ list(that).swap(*this);
+ return *this;
+ }
+
+ ~list()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ while(!empty())
+ pop_front();
+ }
+
+ void swap(list &that) // throw()
+ {
+ list temp;
+ temp.splice(temp.begin(), that); // move that to temp
+ that.splice(that.begin(), *this); // move this to that
+ splice(begin(), temp); // move temp to this
+ }
+
+ void push_front(T const &t)
+ {
+ node *new_node = new node(t);
+
+ new_node->_next = _sentry._next;
+ new_node->_prev = &_sentry;
+
+ _sentry._next->_prev = new_node;
+ _sentry._next = new_node;
+ }
+
+ void push_back(T const &t)
+ {
+ node *new_node = new node(t);
+
+ new_node->_next = &_sentry;
+ new_node->_prev = _sentry._prev;
+
+ _sentry._prev->_next = new_node;
+ _sentry._prev = new_node;
+ }
+
+ void pop_front()
+ {
+ BOOST_ASSERT(!empty());
+ node *old_node = static_cast<node *>(_sentry._next);
+ _sentry._next = old_node->_next;
+ _sentry._next->_prev = &_sentry;
+ delete old_node;
+ }
+
+ void pop_back()
+ {
+ BOOST_ASSERT(!empty());
+ node *old_node = static_cast<node *>(_sentry._prev);
+ _sentry._prev = old_node->_prev;
+ _sentry._prev->_next = &_sentry;
+ delete old_node;
+ }
+
+ bool empty() const
+ {
+ return _sentry._next == &_sentry;
+ }
+
+ void splice(iterator it, list &x)
+ {
+ if(x.empty())
+ return;
+
+ x._sentry._prev->_next = it._node;
+ x._sentry._next->_prev = it._node->_prev;
+
+ it._node->_prev->_next = x._sentry._next;
+ it._node->_prev = x._sentry._prev;
+
+ x._sentry._prev = x._sentry._next = &x._sentry;
+ }
+
+ void splice(iterator it, list &, iterator xit)
+ {
+ xit._node->_prev->_next = xit._node->_next;
+ xit._node->_next->_prev = xit._node->_prev;
+
+ xit._node->_next = it._node;
+ xit._node->_prev = it._node->_prev;
+
+ it._node->_prev = it._node->_prev->_next = xit._node;
+ }
+
+ reference front()
+ {
+ BOOST_ASSERT(!empty());
+ return static_cast<node *>(_sentry._next)->_value;
+ }
+
+ const_reference front() const
+ {
+ BOOST_ASSERT(!empty());
+ return static_cast<node *>(_sentry._next)->_value;
+ }
+
+ reference back()
+ {
+ BOOST_ASSERT(!empty());
+ return static_cast<node *>(_sentry._prev)->_value;
+ }
+
+ const_reference back() const
+ {
+ BOOST_ASSERT(!empty());
+ return static_cast<node *>(_sentry._prev)->_value;
+ }
+
+ iterator begin()
+ {
+ return iterator(_sentry._next);
+ }
+
+ const_iterator begin() const
+ {
+ return const_iterator(_sentry._next);
+ }
+
+ iterator end()
+ {
+ return iterator(&_sentry);
+ }
+
+ const_iterator end() const
+ {
+ return const_iterator(const_cast<node_base *>(&_sentry));
+ }
+
+ size_type size() const
+ {
+ return static_cast<size_type>(std::distance(begin(), end()));
+ }
+ };
+
+ template<typename T>
+ void swap(list<T> &lhs, list<T> &rhs)
+ {
+ lhs.swap(rhs);
+ }
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/action_matcher.hpp b/boost/xpressive/detail/core/matcher/action_matcher.hpp
new file mode 100644
index 0000000000..37180112f5
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/action_matcher.hpp
@@ -0,0 +1,501 @@
+///////////////////////////////////////////////////////////////////////////////
+// action_matcher.hpp
+//
+// Copyright 2008 Eric Niebler.
+// Copyright 2008 David Jenkins.
+//
+// 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/version.hpp>
+#include <boost/ref.hpp>
+#include <boost/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/action.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/xpressive/match_results.hpp> // for type_info_less
+#include <boost/xpressive/detail/static/transforms/as_action.hpp> // for 'read_attr'
+#if BOOST_VERSION >= 103500
+# include <boost/proto/fusion.hpp>
+# include <boost/fusion/include/transform_view.hpp>
+# include <boost/fusion/include/invoke.hpp>
+# include <boost/fusion/include/push_front.hpp>
+# include <boost/fusion/include/pop_front.hpp>
+#endif
+
+#if BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4510) // default constructor could not be generated
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
+#endif
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ #if BOOST_VERSION >= 103500
+ struct DataMember
+ : proto::mem_ptr<proto::_, proto::terminal<proto::_> >
+ {};
+
+ template<typename Expr, long N>
+ struct child_
+ : remove_reference<
+ typename proto::result_of::child_c<Expr &, N>::type
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // mem_ptr_eval
+ // Rewrites expressions of the form x->*foo(a) into foo(x, a) and then
+ // evaluates them.
+ template<typename Expr, typename Context, bool IsDataMember = proto::matches<Expr, DataMember>::value>
+ struct mem_ptr_eval
+ {
+ typedef typename child_<Expr, 0>::type left_type;
+ typedef typename child_<Expr, 1>::type right_type;
+
+ typedef
+ typename proto::result_of::value<
+ typename proto::result_of::child_c<right_type, 0>::type
+ >::type
+ function_type;
+
+ typedef
+ fusion::transform_view<
+ typename fusion::result_of::push_front<
+ typename fusion::result_of::pop_front<right_type>::type const
+ , reference_wrapper<left_type>
+ >::type const
+ , proto::eval_fun<Context>
+ >
+ evaluated_args;
+
+ typedef
+ typename fusion::result_of::invoke<function_type, evaluated_args>::type
+ result_type;
+
+ result_type operator()(Expr &expr, Context &ctx) const
+ {
+ return fusion::invoke<function_type>(
+ proto::value(proto::child_c<0>(proto::right(expr)))
+ , evaluated_args(
+ fusion::push_front(fusion::pop_front(proto::right(expr)), boost::ref(proto::left(expr)))
+ , proto::eval_fun<Context>(ctx)
+ )
+ );
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // mem_ptr_eval
+ // Rewrites expressions of the form x->*foo into foo(x) and then
+ // evaluates them.
+ template<typename Expr, typename Context>
+ struct mem_ptr_eval<Expr, Context, true>
+ {
+ typedef typename child_<Expr, 0>::type left_type;
+ typedef typename child_<Expr, 1>::type right_type;
+
+ typedef
+ typename proto::result_of::value<right_type>::type
+ function_type;
+
+ typedef typename boost::result_of<
+ function_type(typename proto::result_of::eval<left_type, Context>::type)
+ >::type result_type;
+
+ result_type operator()(Expr &expr, Context &ctx) const
+ {
+ return proto::value(proto::right(expr))(
+ proto::eval(proto::left(expr), ctx)
+ );
+ }
+ };
+ #endif
+
+ struct attr_with_default_tag
+ {};
+
+ template<typename T>
+ struct opt;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // action_context
+ //
+ struct action_context
+ {
+ explicit action_context(action_args_type *action_args)
+ : action_args_(action_args)
+ {}
+
+ action_args_type const &args() const
+ {
+ return *this->action_args_;
+ }
+
+ // eval_terminal
+ template<typename Expr, typename Arg>
+ struct eval_terminal
+ : proto::default_eval<Expr, action_context const>
+ {};
+
+ template<typename Expr, typename Arg>
+ struct eval_terminal<Expr, reference_wrapper<Arg> >
+ {
+ typedef Arg &result_type;
+ result_type operator()(Expr &expr, action_context const &) const
+ {
+ return proto::value(expr).get();
+ }
+ };
+
+ template<typename Expr, typename Arg>
+ struct eval_terminal<Expr, opt<Arg> >
+ {
+ typedef Arg const &result_type;
+ result_type operator()(Expr &expr, action_context const &) const
+ {
+ return proto::value(expr);
+ }
+ };
+
+ template<typename Expr, typename Type, typename Int>
+ struct eval_terminal<Expr, action_arg<Type, Int> >
+ {
+ typedef typename action_arg<Type, Int>::reference result_type;
+ result_type operator()(Expr &expr, action_context const &ctx) const
+ {
+ action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
+ if(where_ == ctx.args().end())
+ {
+ BOOST_THROW_EXCEPTION(
+ regex_error(
+ regex_constants::error_badarg
+ , "An argument to an action was unspecified"
+ )
+ );
+ }
+ return proto::value(expr).cast(where_->second);
+ }
+ };
+
+ // eval
+ template<typename Expr, typename Tag = typename Expr::proto_tag>
+ struct eval
+ : proto::default_eval<Expr, action_context const>
+ {};
+
+ template<typename Expr>
+ struct eval<Expr, proto::tag::terminal>
+ : eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
+ {};
+
+ // Evaluate attributes like a1|42
+ template<typename Expr>
+ struct eval<Expr, attr_with_default_tag>
+ {
+ typedef
+ typename proto::result_of::value<
+ typename proto::result_of::left<
+ typename proto::result_of::child<
+ Expr
+ >::type
+ >::type
+ >::type
+ temp_type;
+
+ typedef typename temp_type::type result_type;
+
+ result_type operator ()(Expr const &expr, action_context const &ctx) const
+ {
+ return proto::value(proto::left(proto::child(expr))).t_
+ ? *proto::value(proto::left(proto::child(expr))).t_
+ : proto::eval(proto::right(proto::child(expr)), ctx);
+ }
+ };
+
+ #if BOOST_VERSION >= 103500
+ template<typename Expr>
+ struct eval<Expr, proto::tag::mem_ptr>
+ : mem_ptr_eval<Expr, action_context const>
+ {};
+ #endif
+
+ private:
+ action_args_type *action_args_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // action
+ //
+ template<typename Actor>
+ struct action
+ : actionable
+ {
+ action(Actor const &actor)
+ : actionable()
+ , actor_(actor)
+ {
+ }
+
+ virtual void execute(action_args_type *action_args) const
+ {
+ action_context const ctx(action_args);
+ proto::eval(this->actor_, ctx);
+ }
+
+ private:
+ Actor actor_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // subreg_transform
+ //
+ struct subreg_transform : proto::transform<subreg_transform>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::state state_type;
+
+ typedef
+ typename proto::terminal<sub_match<typename state_type::iterator> >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ return result_type::make(state.sub_matches_[ data ]);
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // mark_transform
+ //
+ struct mark_transform : proto::transform<mark_transform>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::state state_type;
+ typedef
+ typename proto::terminal<sub_match<typename state_type::iterator> >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param
+ ) const
+ {
+ return result_type::make(state.sub_matches_[ proto::value(expr).mark_number_ ]);
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // opt
+ //
+ template<typename T>
+ struct opt
+ {
+ typedef T type;
+ typedef T const &reference;
+
+ opt(T const *t)
+ : t_(t)
+ {}
+
+ operator reference() const
+ {
+ BOOST_XPR_ENSURE_(0 != this->t_, regex_constants::error_badattr, "Use of uninitialized regex attribute");
+ return *this->t_;
+ }
+
+ T const *t_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // attr_transform
+ //
+ struct attr_transform : proto::transform<attr_transform>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::expr expr_type;
+
+ typedef
+ typename expr_type::proto_child0::matcher_type::value_type::second_type
+ attr_type;
+
+ typedef
+ typename proto::terminal<opt<attr_type> >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param
+ , typename impl::state_param state
+ , typename impl::data_param
+ ) const
+ {
+ int slot = typename expr_type::proto_child0::nbr_type();
+ attr_type const *attr = static_cast<attr_type const *>(state.attr_context_.attr_slots_[slot-1]);
+ return result_type::make(opt<attr_type>(attr));
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // attr_with_default_transform
+ //
+ template<typename Grammar, typename Callable = proto::callable>
+ struct attr_with_default_transform : proto::transform<attr_with_default_transform<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename proto::unary_expr<
+ attr_with_default_tag
+ , typename Grammar::template impl<Expr, State, Data>::result_type
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ result_type that = {
+ typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
+ };
+ return that;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // by_ref_transform
+ //
+ struct by_ref_transform : proto::transform<by_ref_transform>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename proto::result_of::value<typename impl::expr_param>::type
+ reference;
+
+ typedef
+ typename proto::terminal<reference>::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param
+ ) const
+ {
+ return result_type::make(proto::value(expr));
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // BindActionArgs
+ //
+ struct BindActionArgs
+ : proto::or_<
+ proto::when<proto::terminal<any_matcher>, subreg_transform>
+ , proto::when<proto::terminal<mark_placeholder>, mark_transform>
+ , proto::when<proto::terminal<read_attr<proto::_, proto::_> >, attr_transform>
+ , proto::when<proto::terminal<proto::_>, by_ref_transform>
+ , proto::when<
+ proto::bitwise_or<proto::terminal<read_attr<proto::_, proto::_> >, BindActionArgs>
+ , attr_with_default_transform<proto::bitwise_or<attr_transform, BindActionArgs> >
+ >
+ , proto::otherwise<proto::nary_expr<proto::_, proto::vararg<BindActionArgs> > >
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // action_matcher
+ //
+ template<typename Actor>
+ struct action_matcher
+ : quant_style<quant_none, 0, false>
+ {
+ int sub_;
+ Actor actor_;
+
+ action_matcher(Actor const &actor, int sub)
+ : sub_(sub)
+ , actor_(actor)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ // Bind the arguments
+ typedef
+ typename boost::result_of<BindActionArgs(
+ Actor const &
+ , match_state<BidiIter> &
+ , int const &
+ )>::type
+ action_type;
+
+ action<action_type> actor(BindActionArgs()(this->actor_, state, this->sub_));
+
+ // Put the action in the action list
+ actionable const **action_list_tail = state.action_list_tail_;
+ *state.action_list_tail_ = &actor;
+ state.action_list_tail_ = &actor.next;
+
+ // Match the rest of the pattern
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ BOOST_ASSERT(0 == actor.next);
+ // remove action from list
+ *action_list_tail = 0;
+ state.action_list_tail_ = action_list_tail;
+ return false;
+ }
+ };
+
+}}}
+
+#if BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/alternate_end_matcher.hpp b/boost/xpressive/detail/core/matcher/alternate_end_matcher.hpp
new file mode 100644
index 0000000000..e0ae2ad283
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/alternate_end_matcher.hpp
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+// alternate_end_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_END_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_END_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // alternate_end_matcher
+ //
+ struct alternate_end_matcher
+ : quant_style_assertion
+ {
+ mutable void const *back_;
+
+ alternate_end_matcher()
+ : back_(0)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ return next.pop_match(state, this->back_);
+ }
+ };
+
+}}}
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/alternate_matcher.hpp b/boost/xpressive/detail/core/matcher/alternate_matcher.hpp
new file mode 100644
index 0000000000..10e57ad6d1
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/alternate_matcher.hpp
@@ -0,0 +1,132 @@
+///////////////////////////////////////////////////////////////////////////////
+// alternate_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/version.hpp>
+#if BOOST_VERSION <= 103200
+// WORKAROUND for Fusion bug in Boost 1.32
+namespace boost { namespace fusion
+{
+ namespace detail { struct iterator_root; }
+ using detail::iterator_root;
+}}
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/dynamic/matchable.hpp>
+#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+#include <boost/xpressive/detail/utility/any.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // alt_match_pred
+ //
+ template<typename BidiIter, typename Next>
+ struct alt_match_pred
+ {
+ alt_match_pred(match_state<BidiIter> &state)
+ : state_(&state)
+ {
+ }
+
+ template<typename Xpr>
+ bool operator ()(Xpr const &xpr) const
+ {
+ return xpr.BOOST_NESTED_TEMPLATE push_match<Next>(*this->state_);
+ }
+
+ private:
+ match_state<BidiIter> *state_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // alt_match
+ //
+ template<typename BidiIter, typename Next>
+ inline bool alt_match
+ (
+ alternates_vector<BidiIter> const &alts, match_state<BidiIter> &state, Next const &
+ )
+ {
+ return detail::any(alts.begin(), alts.end(), alt_match_pred<BidiIter, Next>(state));
+ }
+
+ template<typename Head, typename Tail, typename BidiIter, typename Next>
+ inline bool alt_match
+ (
+ alternates_list<Head, Tail> const &alts, match_state<BidiIter> &state, Next const &
+ )
+ {
+ return fusion::any(alts, alt_match_pred<BidiIter, Next>(state));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // alternate_matcher
+ template<typename Alternates, typename Traits>
+ struct alternate_matcher
+ : quant_style<
+ Alternates::width != unknown_width::value && Alternates::pure ? quant_fixed_width : quant_variable_width
+ , Alternates::width
+ , Alternates::pure
+ >
+ {
+ typedef Alternates alternates_type;
+ typedef typename Traits::char_type char_type;
+
+ Alternates alternates_;
+ mutable hash_peek_bitset<char_type> bset_;
+
+ explicit alternate_matcher(Alternates const &alternates = Alternates())
+ : alternates_(alternates)
+ , bset_()
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(!state.eos() && !this->can_match_(*state.cur_, traits_cast<Traits>(state)))
+ {
+ return false;
+ }
+
+ return detail::alt_match(this->alternates_, state, next);
+ }
+
+ detail::width get_width() const
+ {
+ // Only called when constructing static regexes, and this is a
+ // set of same-width alternates where the widths are known at compile
+ // time, as in: sregex rx = +(_ | 'a' | _n);
+ BOOST_MPL_ASSERT_RELATION(unknown_width::value, !=, Alternates::width);
+ return Alternates::width;
+ }
+
+ private:
+ alternate_matcher &operator =(alternate_matcher const &);
+
+ bool can_match_(char_type ch, Traits const &tr) const
+ {
+ return this->bset_.test(ch, tr);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/any_matcher.hpp b/boost/xpressive/detail/core/matcher/any_matcher.hpp
new file mode 100644
index 0000000000..5c5336639f
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/any_matcher.hpp
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+// any_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ANY_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ANY_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // any_matcher
+ //
+ struct any_matcher
+ {
+ BOOST_XPR_QUANT_STYLE(quant_fixed_width, 1, true)
+
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &state, Next const &next)
+ {
+ if(state.eos())
+ {
+ return false;
+ }
+
+ ++state.cur_;
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ --state.cur_;
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/assert_bol_matcher.hpp b/boost/xpressive/detail/core/matcher/assert_bol_matcher.hpp
new file mode 100644
index 0000000000..a7c0c8cdc5
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/assert_bol_matcher.hpp
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+// assert_bol_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOL_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOL_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/next_prior.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/core/matcher/assert_line_base.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // assert_bol_matcher
+ //
+ template<typename Traits>
+ struct assert_bol_matcher
+ : assert_line_base<Traits>
+ {
+ typedef typename Traits::char_type char_type;
+
+ assert_bol_matcher(Traits const &tr)
+ : assert_line_base<Traits>(tr)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.bos())
+ {
+ if(!state.flags_.match_bol_)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ char_type ch = *boost::prior(state.cur_);
+
+ // If the previous character is not a newline, we're not at the start of a line
+ if(!traits_cast<Traits>(state).isctype(ch, this->newline_))
+ {
+ return false;
+ }
+ // There is no line-break between \r and \n
+ else if(ch == this->cr_ && !state.eos() && *state.cur_ == this->nl_)
+ {
+ return false;
+ }
+ }
+
+ return next.match(state);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/assert_bos_matcher.hpp b/boost/xpressive/detail/core/matcher/assert_bos_matcher.hpp
new file mode 100644
index 0000000000..00b63b0280
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/assert_bos_matcher.hpp
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////////
+// assert_bos_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOS_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOS_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // assert_bos_matcher
+ // match the beginning of the sequence (\A)
+ struct assert_bos_matcher
+ {
+ BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
+
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &state, Next const &next)
+ {
+ return state.bos() && next.match(state);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/assert_eol_matcher.hpp b/boost/xpressive/detail/core/matcher/assert_eol_matcher.hpp
new file mode 100644
index 0000000000..abceb952e0
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/assert_eol_matcher.hpp
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+// assert_eol_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOL_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOL_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/next_prior.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/core/matcher/assert_line_base.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // assert_eol_matcher
+ //
+ template<typename Traits>
+ struct assert_eol_matcher
+ : assert_line_base<Traits>
+ {
+ typedef typename Traits::char_type char_type;
+
+ assert_eol_matcher(Traits const &tr)
+ : assert_line_base<Traits>(tr)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.eos())
+ {
+ if(!state.flags_.match_eol_)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ char_type ch = *state.cur_;
+
+ // If the current character is not a newline, we're not at the end of a line
+ if(!traits_cast<Traits>(state).isctype(ch, this->newline_))
+ {
+ return false;
+ }
+ // There is no line-break between \r and \n
+ else if(ch == this->nl_ && (!state.bos() || state.flags_.match_prev_avail_) && *boost::prior(state.cur_) == this->cr_)
+ {
+ return false;
+ }
+ }
+
+ return next.match(state);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/assert_eos_matcher.hpp b/boost/xpressive/detail/core/matcher/assert_eos_matcher.hpp
new file mode 100644
index 0000000000..a0acbdd369
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/assert_eos_matcher.hpp
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////////
+// assert_eos_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOS_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOS_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // assert_eos_matcher
+ // match the end of the sequence (\Z)
+ struct assert_eos_matcher
+ {
+ BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
+
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &state, Next const &next)
+ {
+ return state.eos() && next.match(state);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/assert_line_base.hpp b/boost/xpressive/detail/core/matcher/assert_line_base.hpp
new file mode 100644
index 0000000000..e10d90971a
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/assert_line_base.hpp
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+// assert_line_base.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_DETAIL_ASSERT_LINE_BASE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_DETAIL_ASSERT_LINE_BASE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // assert_line_base
+ //
+ template<typename Traits>
+ struct assert_line_base
+ : quant_style_assertion
+ {
+ typedef typename Traits::char_type char_type;
+ typedef typename Traits::char_class_type char_class_type;
+
+ protected:
+ assert_line_base(Traits const &tr)
+ : newline_(lookup_classname(tr, "newline"))
+ , nl_(tr.widen('\n'))
+ , cr_(tr.widen('\r'))
+ {
+ }
+
+ char_class_type newline_;
+ char_type nl_, cr_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/assert_word_matcher.hpp b/boost/xpressive/detail/core/matcher/assert_word_matcher.hpp
new file mode 100644
index 0000000000..444d88a5df
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/assert_word_matcher.hpp
@@ -0,0 +1,125 @@
+///////////////////////////////////////////////////////////////////////////////
+// assert_word_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_WORD_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_WORD_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // word_boundary
+ //
+ template<typename IsBoundary>
+ struct word_boundary
+ {
+ template<typename BidiIter>
+ static bool eval(bool prevword, bool thisword, match_state<BidiIter> &state)
+ {
+ if((state.flags_.match_not_bow_ && state.bos()) || (state.flags_.match_not_eow_ && state.eos()))
+ {
+ return !IsBoundary::value;
+ }
+
+ return IsBoundary::value == (prevword != thisword);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // word_begin
+ //
+ struct word_begin
+ {
+ template<typename BidiIter>
+ static bool eval(bool prevword, bool thisword, match_state<BidiIter> &state)
+ {
+ if(state.flags_.match_not_bow_ && state.bos())
+ {
+ return false;
+ }
+
+ return !prevword && thisword;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // word_end
+ //
+ struct word_end
+ {
+ template<typename BidiIter>
+ static bool eval(bool prevword, bool thisword, match_state<BidiIter> &state)
+ {
+ if(state.flags_.match_not_eow_ && state.eos())
+ {
+ return false;
+ }
+
+ return prevword && !thisword;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // assert_word_matcher
+ //
+ template<typename Cond, typename Traits>
+ struct assert_word_matcher
+ : quant_style_assertion
+ {
+ typedef typename Traits::char_type char_type;
+ typedef typename Traits::char_class_type char_class_type;
+
+ assert_word_matcher(Traits const &tr)
+ : word_(lookup_classname(tr, "w"))
+ {
+ BOOST_ASSERT(0 != this->word_);
+ }
+
+ assert_word_matcher(char_class_type word)
+ : word_(word)
+ {}
+
+ bool is_word(Traits const &tr, char_type ch) const
+ {
+ detail::ignore_unused(tr);
+ return tr.isctype(tr.translate(ch), this->word_);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ BidiIter cur = state.cur_;
+ bool const thisword = !state.eos() && this->is_word(traits_cast<Traits>(state), *cur);
+ bool const prevword = (!state.bos() || state.flags_.match_prev_avail_)
+ && this->is_word(traits_cast<Traits>(state), *--cur);
+
+ return Cond::eval(prevword, thisword, state) && next.match(state);
+ }
+
+ char_class_type word() const
+ {
+ return this->word_;
+ }
+
+ private:
+ char_class_type word_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/attr_begin_matcher.hpp b/boost/xpressive/detail/core/matcher/attr_begin_matcher.hpp
new file mode 100644
index 0000000000..86d48a4d39
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/attr_begin_matcher.hpp
@@ -0,0 +1,50 @@
+///////////////////////////////////////////////////////////////////////////////
+// attr_begin_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_BEGIN_MATCHER_HPP_EAN_06_09_2007
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_BEGIN_MATCHER_HPP_EAN_06_09_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // attr_begin_matcher
+ //
+ template<typename Nbr>
+ struct attr_begin_matcher
+ : quant_style<quant_none, 0, false>
+ {
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &state, Next const &next)
+ {
+ void const *attr_slots[Nbr::value] = {};
+ attr_context old_attr_context = state.attr_context_;
+ state.attr_context_.attr_slots_ = attr_slots;
+ state.attr_context_.prev_attr_context_ = &old_attr_context;
+
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ state.attr_context_ = old_attr_context;
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/attr_end_matcher.hpp b/boost/xpressive/detail/core/matcher/attr_end_matcher.hpp
new file mode 100644
index 0000000000..1ad23c28b9
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/attr_end_matcher.hpp
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+// attr_end_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_END_MATCHER_HPP_EAN_06_09_2007
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_END_MATCHER_HPP_EAN_06_09_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // attr_end_matcher
+ //
+ struct attr_end_matcher
+ : quant_style<quant_none, 0, false>
+ {
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &state, Next const &next)
+ {
+ attr_context old_attr_context = state.attr_context_;
+ state.attr_context_ = *old_attr_context.prev_attr_context_;
+
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ state.attr_context_ = old_attr_context;
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/attr_matcher.hpp b/boost/xpressive/detail/core/matcher/attr_matcher.hpp
new file mode 100644
index 0000000000..7d8e67281a
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/attr_matcher.hpp
@@ -0,0 +1,111 @@
+///////////////////////////////////////////////////////////////////////////////
+// attr_matcher.hpp
+//
+// Copyright 2008 Eric Niebler.
+// Copyright 2008 David Jenkins.
+//
+// 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_MATCHER_HPP_EAN_06_09_2007
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_MATCHER_HPP_EAN_06_09_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/symbols.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // char_translate
+ //
+ template<typename Traits, bool ICase>
+ struct char_translate
+ {
+ typedef typename Traits::char_type char_type;
+ Traits const &traits_;
+
+ explicit char_translate(Traits const &tr)
+ : traits_(tr)
+ {}
+
+ char_type operator ()(char_type ch1) const
+ {
+ return this->traits_.translate(ch1);
+ }
+ private:
+ char_translate &operator =(char_translate const &);
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // char_translate
+ //
+ template<typename Traits>
+ struct char_translate<Traits, true>
+ {
+ typedef typename Traits::char_type char_type;
+ Traits const &traits_;
+
+ explicit char_translate(Traits const &tr)
+ : traits_(tr)
+ {}
+
+ char_type operator ()(char_type ch1) const
+ {
+ return this->traits_.translate_nocase(ch1);
+ }
+ private:
+ char_translate &operator =(char_translate const &);
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // attr_matcher
+ // Note: the Matcher is a std::map
+ template<typename Matcher, typename Traits, typename ICase>
+ struct attr_matcher
+ : quant_style<quant_none, 0, false>
+ {
+ typedef typename Matcher::value_type::second_type const* result_type;
+
+ attr_matcher(int slot, Matcher const &matcher, Traits const& tr)
+ : slot_(slot-1)
+ {
+ char_translate<Traits, ICase::value> trans(tr);
+ this->sym_.load(matcher, trans);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ BidiIter tmp = state.cur_;
+ char_translate<Traits, ICase::value> trans(traits_cast<Traits>(state));
+ result_type const &result = this->sym_(state.cur_, state.end_, trans);
+ if(result)
+ {
+ void const *old_slot = state.attr_context_.attr_slots_[this->slot_];
+ state.attr_context_.attr_slots_[this->slot_] = &*result;
+ if(next.match(state))
+ {
+ return true;
+ }
+ state.attr_context_.attr_slots_[this->slot_] = old_slot;
+ }
+ state.cur_ = tmp;
+ return false;
+ }
+
+ int slot_;
+ boost::xpressive::detail::symbols<Matcher> sym_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/charset_matcher.hpp b/boost/xpressive/detail/core/matcher/charset_matcher.hpp
new file mode 100644
index 0000000000..66d1d298f2
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/charset_matcher.hpp
@@ -0,0 +1,67 @@
+///////////////////////////////////////////////////////////////////////////////
+// charset_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_CHARSET_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_CHARSET_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // charset_matcher
+ //
+ template<typename Traits, typename ICase, typename CharSet>
+ struct charset_matcher
+ : quant_style_fixed_width<1>
+ {
+ typedef typename Traits::char_type char_type;
+ typedef Traits traits_type;
+ typedef ICase icase_type;
+
+ charset_matcher(CharSet const &charset = CharSet())
+ : charset_(charset)
+ {
+ }
+
+ void inverse()
+ {
+ this->charset_.inverse();
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.eos() || !this->charset_.test(*state.cur_, traits_cast<Traits>(state), icase_type()))
+ {
+ return false;
+ }
+
+ ++state.cur_;
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ --state.cur_;
+ return false;
+ }
+
+ CharSet charset_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/end_matcher.hpp b/boost/xpressive/detail/core/matcher/end_matcher.hpp
new file mode 100644
index 0000000000..2b10db4a18
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/end_matcher.hpp
@@ -0,0 +1,98 @@
+///////////////////////////////////////////////////////////////////////////////
+// end_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_END_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_END_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/core/sub_match_impl.hpp>
+#include <boost/xpressive/detail/core/flow_control.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // end_matcher
+ //
+ struct end_matcher
+ : quant_style_assertion
+ {
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &state, Next const &)
+ {
+ BidiIter const tmp = state.cur_;
+ sub_match_impl<BidiIter> &s0 = state.sub_match(0);
+ BOOST_ASSERT(!s0.matched);
+
+ // SPECIAL: if there is a match context on the context stack, then
+ // this pattern has been nested within another. pop that context and
+ // continue executing.
+ if(0 != state.context_.prev_context_)
+ {
+ if(!pop_context_match(state))
+ {
+ return false;
+ }
+
+ // record the end of sub-match zero
+ s0.first = s0.begin_;
+ s0.second = tmp;
+ s0.matched = true;
+
+ return true;
+ }
+ else if((state.flags_.match_all_ && !state.eos()) ||
+ (state.flags_.match_not_null_ && state.cur_ == s0.begin_))
+ {
+ return false;
+ }
+
+ // record the end of sub-match zero
+ s0.first = s0.begin_;
+ s0.second = tmp;
+ s0.matched = true;
+
+ // Now execute any actions that have been queued
+ for(actionable const *actor = state.action_list_.next; 0 != actor; actor = actor->next)
+ {
+ actor->execute(state.action_args_);
+ }
+
+ return true;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // independent_end_matcher
+ //
+ struct independent_end_matcher
+ : quant_style_assertion
+ {
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &) const
+ {
+ // Now execute any actions that have been queued
+ for(actionable const *actor = state.action_list_.next; 0 != actor; actor = actor->next)
+ {
+ actor->execute(state.action_args_);
+ }
+
+ return true;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/epsilon_matcher.hpp b/boost/xpressive/detail/core/matcher/epsilon_matcher.hpp
new file mode 100644
index 0000000000..3452b3462d
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/epsilon_matcher.hpp
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////////
+// epsilon_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_EPSILON_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_EPSILON_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // epsilon_matcher
+ //
+ struct epsilon_matcher
+ {
+ BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
+
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &state, Next const &next)
+ {
+ return next.match(state);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/keeper_matcher.hpp b/boost/xpressive/detail/core/matcher/keeper_matcher.hpp
new file mode 100644
index 0000000000..d4b31e47e1
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/keeper_matcher.hpp
@@ -0,0 +1,96 @@
+///////////////////////////////////////////////////////////////////////////////
+// keeper_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // keeper_matcher
+ // Xpr can be either a static_xpression, or a shared_matchable
+ template<typename Xpr>
+ struct keeper_matcher
+ : quant_style<quant_variable_width, unknown_width::value, Xpr::pure>
+ {
+ keeper_matcher(Xpr const &xpr, bool pure = Xpr::pure)
+ : xpr_(xpr)
+ , pure_(pure)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ return Xpr::pure || this->pure_
+ ? this->match_(state, next, mpl::true_())
+ : this->match_(state, next, mpl::false_());
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
+ {
+ BidiIter const tmp = state.cur_;
+
+ // matching xpr is guaranteed to not produce side-effects, don't bother saving state
+ if(!this->xpr_.match(state))
+ {
+ return false;
+ }
+ else if(next.match(state))
+ {
+ return true;
+ }
+
+ state.cur_ = tmp;
+ return false;
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
+ {
+ BidiIter const tmp = state.cur_;
+
+ // matching xpr could produce side-effects, save state
+ memento<BidiIter> mem = save_sub_matches(state);
+
+ if(!this->xpr_.match(state))
+ {
+ restore_action_queue(mem, state);
+ reclaim_sub_matches(mem, state, false);
+ return false;
+ }
+ restore_action_queue(mem, state);
+ if(next.match(state))
+ {
+ reclaim_sub_matches(mem, state, true);
+ return true;
+ }
+
+ restore_sub_matches(mem, state);
+ state.cur_ = tmp;
+ return false;
+ }
+
+ Xpr xpr_;
+ bool pure_; // false if matching xpr_ could modify the sub-matches
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/literal_matcher.hpp b/boost/xpressive/detail/core/matcher/literal_matcher.hpp
new file mode 100644
index 0000000000..ee862363a0
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/literal_matcher.hpp
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////////
+// literal_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LITERAL_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LITERAL_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/traits_utils.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // literal_matcher
+ //
+ template<typename Traits, typename ICase, typename Not>
+ struct literal_matcher
+ : quant_style_fixed_width<1>
+ {
+ typedef typename Traits::char_type char_type;
+ typedef Not not_type;
+ typedef ICase icase_type;
+ char_type ch_;
+
+ explicit literal_matcher(char_type ch)
+ : ch_(ch)
+ {}
+
+ literal_matcher(char_type ch, Traits const &tr)
+ : ch_(detail::translate(ch, tr, icase_type()))
+ {}
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.eos() || Not::value ==
+ (detail::translate(*state.cur_, traits_cast<Traits>(state), icase_type()) == this->ch_))
+ {
+ return false;
+ }
+
+ ++state.cur_;
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ --state.cur_;
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/logical_newline_matcher.hpp b/boost/xpressive/detail/core/matcher/logical_newline_matcher.hpp
new file mode 100644
index 0000000000..be490f603c
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/logical_newline_matcher.hpp
@@ -0,0 +1,83 @@
+///////////////////////////////////////////////////////////////////////////////
+// logical_newline_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOGICAL_NEWLINE_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOGICAL_NEWLINE_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ //////////////////////////////////////////////////////////////////////////
+ // logical_newline_matcher
+ //
+ template<typename Traits>
+ struct logical_newline_matcher
+ : quant_style_variable_width
+ {
+ typedef typename Traits::char_type char_type;
+ typedef typename Traits::char_class_type char_class_type;
+
+ logical_newline_matcher(Traits const &tr)
+ : newline_(lookup_classname(tr, "newline"))
+ , nl_(tr.widen('\n'))
+ , cr_(tr.widen('\r'))
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.eos())
+ {
+ return false;
+ }
+
+ char_type ch = *state.cur_;
+ if(traits_cast<Traits>(state).isctype(ch, this->newline_))
+ {
+ ++state.cur_;
+ if(this->cr_ == ch && !state.eos() && this->nl_ == *state.cur_)
+ {
+ ++state.cur_;
+ if(next.match(state))
+ {
+ return true;
+ }
+ --state.cur_;
+ }
+ else if(next.match(state))
+ {
+ return true;
+ }
+
+ --state.cur_;
+ }
+ return false;
+ }
+
+ char_class_type newline() const
+ {
+ return this->newline_;
+ }
+
+ private:
+ char_class_type newline_;
+ char_type nl_, cr_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/lookahead_matcher.hpp b/boost/xpressive/detail/core/matcher/lookahead_matcher.hpp
new file mode 100644
index 0000000000..06f25e45e2
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/lookahead_matcher.hpp
@@ -0,0 +1,151 @@
+///////////////////////////////////////////////////////////////////////////////
+// lookahead_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKAHEAD_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKAHEAD_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/save_restore.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // lookahead_matcher
+ // Xpr can be either a static_xpression, or a shared_matchable
+ //
+ template<typename Xpr>
+ struct lookahead_matcher
+ : quant_style<quant_none, 0, Xpr::pure>
+ {
+ lookahead_matcher(Xpr const &xpr, bool no, bool pure = Xpr::pure)
+ : xpr_(xpr)
+ , not_(no)
+ , pure_(pure)
+ {
+ }
+
+ void inverse()
+ {
+ this->not_ = !this->not_;
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ return Xpr::pure || this->pure_
+ ? this->match_(state, next, mpl::true_())
+ : this->match_(state, next, mpl::false_());
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
+ {
+ BidiIter const tmp = state.cur_;
+
+ if(this->not_)
+ {
+ // negative look-ahead assertions do not trigger partial matches.
+ save_restore<bool> partial_match(state.found_partial_match_);
+ detail::ignore_unused(partial_match);
+
+ if(this->xpr_.match(state))
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+ else if(next.match(state))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if(!this->xpr_.match(state))
+ {
+ return false;
+ }
+ state.cur_ = tmp;
+ if(next.match(state))
+ {
+ return true;
+ }
+ }
+
+ BOOST_ASSERT(state.cur_ == tmp);
+ return false;
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
+ {
+ BidiIter const tmp = state.cur_;
+
+ // matching xpr could produce side-effects, save state
+ memento<BidiIter> mem = save_sub_matches(state);
+
+ if(this->not_)
+ {
+ // negative look-ahead assertions do not trigger partial matches.
+ save_restore<bool> partial_match(state.found_partial_match_);
+ detail::ignore_unused(partial_match);
+
+ if(this->xpr_.match(state))
+ {
+ restore_action_queue(mem, state);
+ restore_sub_matches(mem, state);
+ state.cur_ = tmp;
+ return false;
+ }
+ restore_action_queue(mem, state);
+ if(next.match(state))
+ {
+ reclaim_sub_matches(mem, state, true);
+ return true;
+ }
+ reclaim_sub_matches(mem, state, false);
+ }
+ else
+ {
+ if(!this->xpr_.match(state))
+ {
+ restore_action_queue(mem, state);
+ reclaim_sub_matches(mem, state, false);
+ return false;
+ }
+ state.cur_ = tmp;
+ restore_action_queue(mem, state);
+ if(next.match(state))
+ {
+ reclaim_sub_matches(mem, state, true);
+ return true;
+ }
+ restore_sub_matches(mem, state);
+ }
+
+ BOOST_ASSERT(state.cur_ == tmp);
+ return false;
+ }
+
+ Xpr xpr_;
+ bool not_;
+ bool pure_; // false if matching xpr_ could modify the sub-matches
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp b/boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp
new file mode 100644
index 0000000000..e75f5ed78f
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp
@@ -0,0 +1,168 @@
+///////////////////////////////////////////////////////////////////////////////
+// lookbehind_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/xpressive/regex_error.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+#include <boost/xpressive/detail/utility/save_restore.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // lookbehind_matcher
+ // Xpr can be either a static_xpression or a shared_matchable
+ template<typename Xpr>
+ struct lookbehind_matcher
+ : quant_style<quant_none, 0, Xpr::pure>
+ {
+ lookbehind_matcher(Xpr const &xpr, std::size_t wid, bool no, bool pure = Xpr::pure)
+ : xpr_(xpr)
+ , not_(no)
+ , pure_(pure)
+ , width_(wid)
+ {
+ BOOST_XPR_ENSURE_(!is_unknown(this->width_), regex_constants::error_badlookbehind,
+ "Variable-width look-behind assertions are not supported");
+ }
+
+ void inverse()
+ {
+ this->not_ = !this->not_;
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ return Xpr::pure || this->pure_
+ ? this->match_(state, next, mpl::true_())
+ : this->match_(state, next, mpl::false_());
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
+ {
+ typedef typename iterator_difference<BidiIter>::type difference_type;
+ BidiIter const tmp = state.cur_;
+ if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
+ {
+ state.cur_ = tmp;
+ return this->not_ ? next.match(state) : false;
+ }
+
+ if(this->not_)
+ {
+ if(this->xpr_.match(state))
+ {
+ BOOST_ASSERT(state.cur_ == tmp);
+ return false;
+ }
+ state.cur_ = tmp;
+ if(next.match(state))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if(!this->xpr_.match(state))
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+ BOOST_ASSERT(state.cur_ == tmp);
+ if(next.match(state))
+ {
+ return true;
+ }
+ }
+
+ BOOST_ASSERT(state.cur_ == tmp);
+ return false;
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
+ {
+ typedef typename iterator_difference<BidiIter>::type difference_type;
+ BidiIter const tmp = state.cur_;
+ if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
+ {
+ state.cur_ = tmp;
+ return this->not_ ? next.match(state) : false;
+ }
+
+ // matching xpr could produce side-effects, save state
+ memento<BidiIter> mem = save_sub_matches(state);
+
+ if(this->not_)
+ {
+ // negative look-ahead assertions do not trigger partial matches.
+ save_restore<bool> partial_match(state.found_partial_match_);
+ detail::ignore_unused(partial_match);
+
+ if(this->xpr_.match(state))
+ {
+ restore_action_queue(mem, state);
+ restore_sub_matches(mem, state);
+ BOOST_ASSERT(state.cur_ == tmp);
+ return false;
+ }
+ state.cur_ = tmp;
+ restore_action_queue(mem, state);
+ if(next.match(state))
+ {
+ reclaim_sub_matches(mem, state, true);
+ return true;
+ }
+ reclaim_sub_matches(mem, state, false);
+ }
+ else
+ {
+ if(!this->xpr_.match(state))
+ {
+ state.cur_ = tmp;
+ restore_action_queue(mem, state);
+ reclaim_sub_matches(mem, state, false);
+ return false;
+ }
+ BOOST_ASSERT(state.cur_ == tmp);
+ restore_action_queue(mem, state);
+ if(next.match(state))
+ {
+ reclaim_sub_matches(mem, state, true);
+ return true;
+ }
+ restore_sub_matches(mem, state);
+ }
+
+ BOOST_ASSERT(state.cur_ == tmp);
+ return false;
+ }
+
+ Xpr xpr_;
+ bool not_;
+ bool pure_; // false if matching xpr_ could modify the sub-matches
+ std::size_t width_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp b/boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp
new file mode 100644
index 0000000000..b73608a38f
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+// mark_begin_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_BEGIN_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_BEGIN_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // mark_begin_matcher
+ //
+ struct mark_begin_matcher
+ : quant_style<quant_fixed_width, 0, false>
+ {
+ int mark_number_; // signed because it could be negative
+
+ mark_begin_matcher(int mark_number)
+ : mark_number_(mark_number)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
+
+ BidiIter old_begin = br.begin_;
+ br.begin_ = state.cur_;
+
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ br.begin_ = old_begin;
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/mark_end_matcher.hpp b/boost/xpressive/detail/core/matcher/mark_end_matcher.hpp
new file mode 100644
index 0000000000..1316c1dfad
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/mark_end_matcher.hpp
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+// mark_end_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_END_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_END_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // mark_end_matcher
+ //
+ struct mark_end_matcher
+ : quant_style<quant_none, 0, false>
+ {
+ int mark_number_;
+
+ mark_end_matcher(int mark_number)
+ : mark_number_(mark_number)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
+
+ BidiIter old_first = br.first;
+ BidiIter old_second = br.second;
+ bool old_matched = br.matched;
+
+ br.first = br.begin_;
+ br.second = state.cur_;
+ br.matched = true;
+
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ br.first = old_first;
+ br.second = old_second;
+ br.matched = old_matched;
+
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/mark_matcher.hpp b/boost/xpressive/detail/core/matcher/mark_matcher.hpp
new file mode 100644
index 0000000000..a4696e1938
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/mark_matcher.hpp
@@ -0,0 +1,78 @@
+///////////////////////////////////////////////////////////////////////////////
+// mark_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/traits_utils.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ // TODO: the mark matcher is acually a fixed-width matcher, but the width is
+ // not known until pattern match time.
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // mark_matcher
+ //
+ template<typename Traits, typename ICase>
+ struct mark_matcher
+ : quant_style_variable_width
+ {
+ typedef ICase icase_type;
+ int mark_number_;
+
+ mark_matcher(int mark_number, Traits const &)
+ : mark_number_(mark_number)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ BOOST_ASSERT(this->mark_number_ < static_cast<int>(state.mark_count_));
+ sub_match_impl<BidiIter> const &br = state.sub_match(this->mark_number_);
+
+ if(!br.matched)
+ {
+ return false;
+ }
+
+ BidiIter const tmp = state.cur_;
+ for(BidiIter begin = br.first, end = br.second; begin != end; ++begin, ++state.cur_)
+ {
+ if(state.eos()
+ || detail::translate(*state.cur_, traits_cast<Traits>(state), icase_type())
+ != detail::translate(*begin, traits_cast<Traits>(state), icase_type()))
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+ }
+
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ state.cur_ = tmp;
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/optional_matcher.hpp b/boost/xpressive/detail/core/matcher/optional_matcher.hpp
new file mode 100644
index 0000000000..ab4ac59840
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/optional_matcher.hpp
@@ -0,0 +1,121 @@
+///////////////////////////////////////////////////////////////////////////////
+// optional_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_OPTIONAL_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_OPTIONAL_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // optional_matcher
+ template<typename Xpr, typename Greedy>
+ struct optional_matcher
+ : quant_style<quant_variable_width, unknown_width::value, Xpr::pure>
+ {
+ Xpr xpr_;
+
+ explicit optional_matcher(Xpr const &xpr)
+ : xpr_(xpr)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ return this->match_(state, next, Greedy());
+ }
+
+ private:
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const // Greedy
+ {
+ return this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state)
+ || next.match(state);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const // Non-greedy
+ {
+ return next.match(state)
+ || this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state);
+ }
+
+ optional_matcher &operator =(optional_matcher const &);
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // optional_mark_matcher
+ template<typename BidiIter, typename Next>
+ inline bool match_next(match_state<BidiIter> &state, Next const &next, int mark_number)
+ {
+ sub_match_impl<BidiIter> &br = state.sub_match(mark_number);
+
+ bool old_matched = br.matched;
+ br.matched = false;
+
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ br.matched = old_matched;
+ return false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // optional_mark_matcher
+ template<typename Xpr, typename Greedy>
+ struct optional_mark_matcher
+ : quant_style<quant_variable_width, unknown_width::value, Xpr::pure>
+ {
+ Xpr xpr_;
+ int mark_number_;
+
+ explicit optional_mark_matcher(Xpr const &xpr, int mark_number)
+ : xpr_(xpr)
+ , mark_number_(mark_number)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ return this->match_(state, next, Greedy());
+ }
+
+ private:
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const // Greedy
+ {
+ return this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state)
+ || match_next(state, next, this->mark_number_);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const // Non-greedy
+ {
+ return match_next(state, next, this->mark_number_)
+ || this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state);
+ }
+
+ optional_mark_matcher &operator =(optional_mark_matcher const &);
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/posix_charset_matcher.hpp b/boost/xpressive/detail/core/matcher/posix_charset_matcher.hpp
new file mode 100644
index 0000000000..19e87bf42f
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/posix_charset_matcher.hpp
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+// posix_charset_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_POSIX_CHARSET_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_POSIX_CHARSET_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/traits_utils.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // posix_charset_matcher
+ //
+ template<typename Traits>
+ struct posix_charset_matcher
+ : quant_style_fixed_width<1>
+ {
+ typedef Traits traits_type;
+ typedef typename Traits::char_class_type char_class_type;
+
+ posix_charset_matcher(char_class_type m, bool no)
+ : not_(no)
+ , mask_(m)
+ {
+ BOOST_ASSERT(0 != this->mask_);
+ }
+
+ void inverse()
+ {
+ this->not_ = !this->not_;
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.eos() || this->not_ == traits_cast<Traits>(state).isctype(
+ *state.cur_, this->mask_))
+ {
+ return false;
+ }
+
+ ++state.cur_;
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ --state.cur_;
+ return false;
+ }
+
+ bool not_;
+ char_class_type mask_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/predicate_matcher.hpp b/boost/xpressive/detail/core/matcher/predicate_matcher.hpp
new file mode 100644
index 0000000000..eced1c7643
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/predicate_matcher.hpp
@@ -0,0 +1,174 @@
+///////////////////////////////////////////////////////////////////////////////
+// predicate_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/matcher/action_matcher.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/proto/core.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // predicate_context
+ //
+ template<typename BidiIter>
+ struct predicate_context
+ {
+ explicit predicate_context(int sub, sub_match_impl<BidiIter> const *sub_matches, action_args_type *action_args)
+ : sub_(sub)
+ , sub_matches_(sub_matches)
+ , action_args_(action_args)
+ {}
+
+ action_args_type const &args() const
+ {
+ return *this->action_args_;
+ }
+
+ // eval_terminal
+ template<typename Expr, typename Arg>
+ struct eval_terminal
+ : proto::default_eval<Expr, predicate_context const>
+ {};
+
+ template<typename Expr, typename Arg>
+ struct eval_terminal<Expr, reference_wrapper<Arg> >
+ {
+ typedef Arg &result_type;
+ result_type operator()(Expr &expr, predicate_context const &) const
+ {
+ return proto::value(expr).get();
+ }
+ };
+
+ template<typename Expr>
+ struct eval_terminal<Expr, any_matcher>
+ {
+ typedef sub_match<BidiIter> const &result_type;
+ result_type operator()(Expr &, predicate_context const &ctx) const
+ {
+ return ctx.sub_matches_[ctx.sub_];
+ }
+ };
+
+ template<typename Expr>
+ struct eval_terminal<Expr, mark_placeholder>
+ {
+ typedef sub_match<BidiIter> const &result_type;
+ result_type operator()(Expr &expr, predicate_context const &ctx) const
+ {
+ return ctx.sub_matches_[proto::value(expr).mark_number_];
+ }
+ };
+
+ template<typename Expr, typename Type, typename Int>
+ struct eval_terminal<Expr, action_arg<Type, Int> >
+ {
+ typedef typename action_arg<Type, Int>::reference result_type;
+ result_type operator()(Expr &expr, predicate_context const &ctx) const
+ {
+ action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
+ if(where_ == ctx.args().end())
+ {
+ BOOST_THROW_EXCEPTION(
+ regex_error(
+ regex_constants::error_badarg
+ , "An argument to an action was unspecified"
+ )
+ );
+ }
+ return proto::value(expr).cast(where_->second);
+ }
+ };
+
+ // eval
+ template<typename Expr, typename Tag = typename Expr::proto_tag>
+ struct eval
+ : proto::default_eval<Expr, predicate_context const>
+ {};
+
+ template<typename Expr>
+ struct eval<Expr, proto::tag::terminal>
+ : eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
+ {};
+
+ #if BOOST_VERSION >= 103500
+ template<typename Expr>
+ struct eval<Expr, proto::tag::mem_ptr>
+ : mem_ptr_eval<Expr, predicate_context const>
+ {};
+ #endif
+
+ int sub_;
+ sub_match_impl<BidiIter> const *sub_matches_;
+ action_args_type *action_args_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // AssertionFunctor
+ //
+ struct AssertionFunctor
+ : proto::function<
+ proto::terminal<check_tag>
+ , proto::terminal<proto::_>
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // predicate_matcher
+ //
+ template<typename Predicate>
+ struct predicate_matcher
+ : quant_style_assertion
+ {
+ int sub_;
+ Predicate predicate_;
+
+ predicate_matcher(Predicate const &pred, int sub)
+ : sub_(sub)
+ , predicate_(pred)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ // Predicate is check(assertion), where assertion can be
+ // a lambda or a function object.
+ return this->match_(state, next, proto::matches<Predicate, AssertionFunctor>());
+ }
+
+ private:
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
+ {
+ sub_match<BidiIter> const &sub = state.sub_match(this->sub_);
+ return proto::value(proto::child_c<1>(this->predicate_))(sub) && next.match(state);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
+ {
+ predicate_context<BidiIter> ctx(this->sub_, state.sub_matches_, state.action_args_);
+ return proto::eval(proto::child_c<1>(this->predicate_), ctx) && next.match(state);
+ }
+ };
+
+}}}
+
+#endif // BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007
diff --git a/boost/xpressive/detail/core/matcher/range_matcher.hpp b/boost/xpressive/detail/core/matcher/range_matcher.hpp
new file mode 100644
index 0000000000..2f2c6974d8
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/range_matcher.hpp
@@ -0,0 +1,87 @@
+///////////////////////////////////////////////////////////////////////////////
+// range_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_RANGE_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_RANGE_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // range_matcher
+ //
+ template<typename Traits, typename ICase>
+ struct range_matcher
+ : quant_style_fixed_width<1>
+ {
+ typedef typename Traits::char_type char_type;
+ typedef ICase icase_type;
+ char_type ch_min_;
+ char_type ch_max_;
+ bool not_;
+
+ range_matcher(char_type ch_min, char_type ch_max, bool no, Traits const &)
+ : ch_min_(ch_min)
+ , ch_max_(ch_max)
+ , not_(no)
+ {
+ }
+
+ void inverse()
+ {
+ this->not_ = !this->not_;
+ }
+
+ bool in_range(Traits const &tr, char_type ch, mpl::false_) const // case-sensitive
+ {
+ return tr.in_range(this->ch_min_, this->ch_max_, ch);
+ }
+
+ bool in_range(Traits const &tr, char_type ch, mpl::true_) const // case-insensitive
+ {
+ return tr.in_range_nocase(this->ch_min_, this->ch_max_, ch);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.eos() || this->not_ ==
+ this->in_range(traits_cast<Traits>(state), *state.cur_, icase_type()))
+ {
+ return false;
+ }
+
+ ++state.cur_;
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ --state.cur_;
+ return false;
+ }
+ };
+
+}}}
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/regex_byref_matcher.hpp b/boost/xpressive/detail/core/matcher/regex_byref_matcher.hpp
new file mode 100644
index 0000000000..f92820424e
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/regex_byref_matcher.hpp
@@ -0,0 +1,77 @@
+///////////////////////////////////////////////////////////////////////////////
+// regex_byref_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_BYREF_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_BYREF_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/xpressive/regex_error.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/core/adaptor.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // regex_byref_matcher
+ //
+ template<typename BidiIter>
+ struct regex_byref_matcher
+ : quant_style<quant_variable_width, unknown_width::value, false>
+ {
+ // avoid cyclic references by holding a weak_ptr to the
+ // regex_impl struct
+ weak_ptr<regex_impl<BidiIter> > wimpl_;
+
+ // the basic_regex object holds a ref-count to this regex_impl, so
+ // we don't have to worry about it going away.
+ regex_impl<BidiIter> const *pimpl_;
+
+ regex_byref_matcher(shared_ptr<regex_impl<BidiIter> > const &impl)
+ : wimpl_(impl)
+ , pimpl_(impl.get())
+ {
+ BOOST_ASSERT(this->pimpl_);
+ }
+
+ template<typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ BOOST_ASSERT(this->pimpl_ == this->wimpl_.lock().get());
+ BOOST_XPR_ENSURE_(this->pimpl_->xpr_, regex_constants::error_badref, "bad regex reference");
+
+ return push_context_match(*this->pimpl_, state, this->wrap_(next, is_static_xpression<Next>()));
+ }
+
+ private:
+ template<typename Next>
+ static xpression_adaptor<reference_wrapper<Next const>, matchable<BidiIter> > wrap_(Next const &next, mpl::true_)
+ {
+ // wrap the static xpression in a matchable interface
+ return xpression_adaptor<reference_wrapper<Next const>, matchable<BidiIter> >(boost::cref(next));
+ }
+
+ template<typename Next>
+ static Next const &wrap_(Next const &next, mpl::false_)
+ {
+ return next;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/regex_matcher.hpp b/boost/xpressive/detail/core/matcher/regex_matcher.hpp
new file mode 100644
index 0000000000..e7eee7d3ea
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/regex_matcher.hpp
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////////////////////
+// regex_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/assert.hpp>
+#include <boost/xpressive/regex_error.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/core/adaptor.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // regex_matcher
+ //
+ template<typename BidiIter>
+ struct regex_matcher
+ : quant_style<quant_variable_width, unknown_width::value, false>
+ {
+ regex_impl<BidiIter> impl_;
+
+ regex_matcher(shared_ptr<regex_impl<BidiIter> > const &impl)
+ : impl_()
+ {
+ this->impl_.xpr_ = impl->xpr_;
+ this->impl_.traits_ = impl->traits_;
+ this->impl_.mark_count_ = impl->mark_count_;
+ this->impl_.hidden_mark_count_ = impl->hidden_mark_count_;
+
+ BOOST_XPR_ENSURE_(this->impl_.xpr_, regex_constants::error_badref, "bad regex reference");
+ }
+
+ template<typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ // regex_matcher is used for embeding a dynamic regex in a static regex. As such,
+ // Next will always point to a static regex.
+ BOOST_MPL_ASSERT((is_static_xpression<Next>));
+
+ // wrap the static xpression in a matchable interface
+ xpression_adaptor<reference_wrapper<Next const>, matchable<BidiIter> > adaptor(boost::cref(next));
+ return push_context_match(this->impl_, state, adaptor);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/repeat_begin_matcher.hpp b/boost/xpressive/detail/core/matcher/repeat_begin_matcher.hpp
new file mode 100644
index 0000000000..bcc59ee70f
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/repeat_begin_matcher.hpp
@@ -0,0 +1,69 @@
+///////////////////////////////////////////////////////////////////////////////
+// repeat_end_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_BEGIN_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_BEGIN_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ //
+ // Note: here is the variable-width xpression quantifier. It always
+ // matches at least once, so if the min is 0, it is the responsibility
+ // of the parser to make it alternate with an epsilon matcher.
+ //
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // repeat_begin_matcher
+ //
+ struct repeat_begin_matcher
+ : quant_style<quant_variable_width, unknown_width::value, false>
+ {
+ int mark_number_;
+
+ repeat_begin_matcher(int mark_number)
+ : mark_number_(mark_number)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
+
+ unsigned int old_repeat_count = br.repeat_count_;
+ bool old_zero_width = br.zero_width_;
+
+ br.repeat_count_ = 1;
+ br.zero_width_ = false;
+
+ // "push" next onto the stack, so it can be "popped" in
+ // repeat_end_matcher and used to loop back.
+ if(next.BOOST_NESTED_TEMPLATE push_match<Next>(state))
+ {
+ return true;
+ }
+
+ br.repeat_count_ = old_repeat_count;
+ br.zero_width_ = old_zero_width;
+
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/repeat_end_matcher.hpp b/boost/xpressive/detail/core/matcher/repeat_end_matcher.hpp
new file mode 100644
index 0000000000..c2dc4495b5
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/repeat_end_matcher.hpp
@@ -0,0 +1,121 @@
+///////////////////////////////////////////////////////////////////////////////
+// repeat_end_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_END_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_END_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // repeat_end_matcher
+ //
+ template<typename Greedy>
+ struct repeat_end_matcher
+ : quant_style<quant_none, 0, false>
+ {
+ typedef Greedy greedy_type;
+ int mark_number_;
+ unsigned int min_, max_;
+ mutable void const *back_;
+
+ repeat_end_matcher(int mark_nbr, unsigned int min, unsigned int max)
+ : mark_number_(mark_nbr)
+ , min_(min)
+ , max_(max)
+ , back_(0)
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ // prevent repeated zero-width sub-matches from causing infinite recursion
+ sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
+
+ if(br.zero_width_ && br.begin_ == state.cur_)
+ {
+ return next.skip_match(state);
+ }
+
+ bool old_zero_width = br.zero_width_;
+ br.zero_width_ = (br.begin_ == state.cur_);
+
+ if(this->match_(state, next, greedy_type()))
+ {
+ return true;
+ }
+
+ br.zero_width_ = old_zero_width;
+ return false;
+ }
+
+ // greedy, variable-width quantifier
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
+ {
+ sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
+
+ if(this->max_ > br.repeat_count_)
+ {
+ ++br.repeat_count_;
+ // loop back to the expression "pushed" in repeat_begin_matcher::match
+ if(next.top_match(state, this->back_))
+ {
+ return true;
+ }
+ else if(--br.repeat_count_ < this->min_)
+ {
+ return false;
+ }
+ }
+
+ // looping finished, continue matching the rest of the pattern
+ return next.skip_match(state);
+ }
+
+ // non-greedy, variable-width quantifier
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
+ {
+ sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
+
+ if(this->min_ <= br.repeat_count_)
+ {
+ if(next.skip_match(state))
+ {
+ return true;
+ }
+ }
+
+ if(this->max_ > br.repeat_count_)
+ {
+ ++br.repeat_count_;
+ if(next.top_match(state, this->back_))
+ {
+ return true;
+ }
+ --br.repeat_count_;
+ }
+
+ return false;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/set_matcher.hpp b/boost/xpressive/detail/core/matcher/set_matcher.hpp
new file mode 100644
index 0000000000..124a545fe7
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/set_matcher.hpp
@@ -0,0 +1,100 @@
+///////////////////////////////////////////////////////////////////////////////
+// set.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_SET_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_SET_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4127) // conditional expression constant
+# pragma warning(disable : 4100) // unreferenced formal parameter
+# pragma warning(disable : 4351) // vc8 new behavior: elements of array 'foo' will be default initialized
+#endif
+
+#include <algorithm>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/same_traits.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// set_matcher
+//
+template<typename Traits, typename Size>
+struct set_matcher
+ : quant_style_fixed_width<1>
+{
+ typedef typename Traits::char_type char_type;
+ char_type set_[ Size::value ];
+ bool not_;
+ bool icase_;
+
+ set_matcher()
+ : set_()
+ , not_(false)
+ , icase_(false)
+ {
+ }
+
+ void inverse()
+ {
+ this->not_ = !this->not_;
+ }
+
+ void nocase(Traits const &tr)
+ {
+ this->icase_ = true;
+
+ for(int i = 0; i < Size::value; ++i)
+ {
+ this->set_[i] = tr.translate_nocase(this->set_[i]);
+ }
+ }
+
+ bool in_set(Traits const &tr, char_type ch) const
+ {
+ char_type const *begin = &this->set_[0], *end = begin + Size::value;
+ ch = this->icase_ ? tr.translate_nocase(ch) : tr.translate(ch);
+ return end != std::find(begin, end, ch);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ if(state.eos() || this->not_ == this->in_set(traits_cast<Traits>(state), *state.cur_))
+ {
+ return false;
+ }
+
+ if(++state.cur_, next.match(state))
+ {
+ return true;
+ }
+
+ return --state.cur_, false;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// set_initializer
+struct set_initializer
+{
+};
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/simple_repeat_matcher.hpp b/boost/xpressive/detail/core/matcher/simple_repeat_matcher.hpp
new file mode 100644
index 0000000000..26610f2868
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/simple_repeat_matcher.hpp
@@ -0,0 +1,234 @@
+///////////////////////////////////////////////////////////////////////////////
+// simple_repeat_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_SIMPLE_REPEAT_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_SIMPLE_REPEAT_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/static/type_traits.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // simple_repeat_traits
+ //
+ struct greedy_slow_tag {};
+ struct greedy_fast_tag {};
+ struct non_greedy_tag {};
+
+ typedef static_xpression<any_matcher, true_xpression> any_sxpr;
+ typedef matcher_wrapper<any_matcher> any_dxpr;
+
+ template<typename Xpr, typename Greedy, typename Random>
+ struct simple_repeat_traits
+ {
+ typedef typename mpl::if_c<Greedy::value, greedy_slow_tag, non_greedy_tag>::type tag_type;
+ };
+
+ template<>
+ struct simple_repeat_traits<any_sxpr, mpl::true_, mpl::true_>
+ {
+ typedef greedy_fast_tag tag_type;
+ };
+
+ template<>
+ struct simple_repeat_traits<any_dxpr, mpl::true_, mpl::true_>
+ {
+ typedef greedy_fast_tag tag_type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // simple_repeat_matcher
+ //
+ template<typename Xpr, typename Greedy>
+ struct simple_repeat_matcher
+ : quant_style_variable_width
+ {
+ typedef Xpr xpr_type;
+ typedef Greedy greedy_type;
+
+ Xpr xpr_;
+ unsigned int min_, max_;
+ std::size_t width_;
+ mutable bool leading_;
+
+ simple_repeat_matcher(Xpr const &xpr, unsigned int min, unsigned int max, std::size_t width)
+ : xpr_(xpr)
+ , min_(min)
+ , max_(max)
+ , width_(width)
+ , leading_(false)
+ {
+ // it is the job of the parser to make sure this never happens
+ BOOST_ASSERT(min <= max);
+ BOOST_ASSERT(0 != max);
+ BOOST_ASSERT(0 != width && unknown_width() != width);
+ BOOST_ASSERT(Xpr::width == unknown_width() || Xpr::width == width);
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ typedef mpl::bool_<is_random<BidiIter>::value> is_rand;
+ typedef typename simple_repeat_traits<Xpr, greedy_type, is_rand>::tag_type tag_type;
+ return this->match_(state, next, tag_type());
+ }
+
+ // greedy, fixed-width quantifier
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, greedy_slow_tag) const
+ {
+ int const diff = -static_cast<int>(Xpr::width == unknown_width::value ? this->width_ : Xpr::width);
+ unsigned int matches = 0;
+ BidiIter const tmp = state.cur_;
+
+ // greedily match as much as we can
+ while(matches < this->max_ && this->xpr_.match(state))
+ {
+ ++matches;
+ }
+
+ // If this repeater is at the front of the pattern, note
+ // how much of the input we consumed so that a repeated search
+ // doesn't have to cover the same ground again.
+ if(this->leading_)
+ {
+ state.next_search_ = (matches && matches < this->max_)
+ ? state.cur_
+ : (tmp == state.end_) ? tmp : boost::next(tmp);
+ }
+
+ if(this->min_ > matches)
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+
+ // try matching the rest of the pattern, and back off if necessary
+ for(; ; --matches, std::advance(state.cur_, diff))
+ {
+ if(next.match(state))
+ {
+ return true;
+ }
+ else if(this->min_ == matches)
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+ }
+ }
+
+ // non-greedy fixed-width quantification
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, non_greedy_tag) const
+ {
+ BOOST_ASSERT(!this->leading_);
+ BidiIter const tmp = state.cur_;
+ unsigned int matches = 0;
+
+ for(; matches < this->min_; ++matches)
+ {
+ if(!this->xpr_.match(state))
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+ }
+
+ do
+ {
+ if(next.match(state))
+ {
+ return true;
+ }
+ }
+ while(matches++ < this->max_ && this->xpr_.match(state));
+
+ state.cur_ = tmp;
+ return false;
+ }
+
+ // when greedily matching any character, skip to the end instead of iterating there.
+ template<typename BidiIter, typename Next>
+ bool match_(match_state<BidiIter> &state, Next const &next, greedy_fast_tag) const
+ {
+ BidiIter const tmp = state.cur_;
+ std::size_t const diff_to_end = static_cast<std::size_t>(state.end_ - tmp);
+
+ // is there enough room?
+ if(this->min_ > diff_to_end)
+ {
+ if(this->leading_)
+ {
+ state.next_search_ = (tmp == state.end_) ? tmp : boost::next(tmp);
+ }
+ return false;
+ }
+
+ BidiIter const min_iter = tmp + this->min_;
+ state.cur_ += (std::min)((std::size_t)this->max_, diff_to_end);
+
+ if(this->leading_)
+ {
+ state.next_search_ = (diff_to_end && diff_to_end < this->max_)
+ ? state.cur_
+ : (tmp == state.end_) ? tmp : boost::next(tmp);
+ }
+
+ for(;; --state.cur_)
+ {
+ if(next.match(state))
+ {
+ return true;
+ }
+ else if(min_iter == state.cur_)
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+ }
+ }
+
+ detail::width get_width() const
+ {
+ if(this->min_ != this->max_)
+ {
+ return unknown_width::value;
+ }
+ return this->min_ * this->width_;
+ }
+
+ private:
+ simple_repeat_matcher &operator =(simple_repeat_matcher const &);
+ };
+
+ // BUGBUG can all non-greedy quantification be done with the fixed width quantifier?
+
+ // BUGBUG matchers are chained together using static_xpression so that matchers to
+ // the left can invoke matchers to the right. This is so that if the left matcher
+ // succeeds but the right matcher fails, the left matcher is given the opportunity
+ // to try something else. This is how backtracking works. However, if the left matcher
+ // can succeed only one way (as with any_matcher, for example), it does not need
+ // backtracking. In this case, leaving its stack frame active is a waste of stack
+ // space. Can something be done?
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/string_matcher.hpp b/boost/xpressive/detail/core/matcher/string_matcher.hpp
new file mode 100644
index 0000000000..02b538c249
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/string_matcher.hpp
@@ -0,0 +1,90 @@
+///////////////////////////////////////////////////////////////////////////////
+// string_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <string>
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+#include <boost/xpressive/detail/utility/traits_utils.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // string_matcher
+ //
+ template<typename Traits, typename ICase>
+ struct string_matcher
+ : quant_style_fixed_unknown_width
+ {
+ typedef typename Traits::char_type char_type;
+ typedef typename Traits::string_type string_type;
+ typedef ICase icase_type;
+ string_type str_;
+ char_type const *end_;
+
+ string_matcher(string_type const &str, Traits const &tr)
+ : str_(str)
+ , end_()
+ {
+ typename range_iterator<string_type>::type cur = boost::begin(this->str_);
+ typename range_iterator<string_type>::type end = boost::end(this->str_);
+ for(; cur != end; ++cur)
+ {
+ *cur = detail::translate(*cur, tr, icase_type());
+ }
+ this->end_ = detail::data_end(str_);
+ }
+
+ string_matcher(string_matcher<Traits, ICase> const &that)
+ : str_(that.str_)
+ , end_(detail::data_end(str_))
+ {
+ }
+
+ template<typename BidiIter, typename Next>
+ bool match(match_state<BidiIter> &state, Next const &next) const
+ {
+ BidiIter const tmp = state.cur_;
+ char_type const *begin = detail::data_begin(this->str_);
+ for(; begin != this->end_; ++begin, ++state.cur_)
+ {
+ if(state.eos() ||
+ (detail::translate(*state.cur_, traits_cast<Traits>(state), icase_type()) != *begin))
+ {
+ state.cur_ = tmp;
+ return false;
+ }
+ }
+
+ if(next.match(state))
+ {
+ return true;
+ }
+
+ state.cur_ = tmp;
+ return false;
+ }
+
+ detail::width get_width() const
+ {
+ return boost::size(this->str_);
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matcher/true_matcher.hpp b/boost/xpressive/detail/core/matcher/true_matcher.hpp
new file mode 100644
index 0000000000..df45e47d21
--- /dev/null
+++ b/boost/xpressive/detail/core/matcher/true_matcher.hpp
@@ -0,0 +1,38 @@
+///////////////////////////////////////////////////////////////////////////////
+// true_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_TRUE_MATCHER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_TRUE_MATCHER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // true_matcher
+ //
+ struct true_matcher
+ : quant_style_assertion
+ {
+ template<typename BidiIter, typename Next>
+ static bool match(match_state<BidiIter> &, Next const &)
+ {
+ return true;
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/matchers.hpp b/boost/xpressive/detail/core/matchers.hpp
new file mode 100644
index 0000000000..8363ce0c1d
--- /dev/null
+++ b/boost/xpressive/detail/core/matchers.hpp
@@ -0,0 +1,50 @@
+///////////////////////////////////////////////////////////////////////////////
+// matchers.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHERS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHERS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//#include <boost/xpressive/detail/core/matcher/action_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/alternate_end_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/alternate_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/any_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/assert_bol_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/assert_bos_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/assert_eol_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/assert_eos_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/assert_word_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/attr_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/charset_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/end_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/epsilon_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/keeper_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/literal_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/logical_newline_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/lookahead_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/mark_end_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/mark_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/optional_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/posix_charset_matcher.hpp>
+//#include <boost/xpressive/detail/core/matcher/predicate_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/range_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/regex_byref_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/regex_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/repeat_begin_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/repeat_end_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/set_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/simple_repeat_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/string_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/true_matcher.hpp>
+
+#endif
diff --git a/boost/xpressive/detail/core/optimize.hpp b/boost/xpressive/detail/core/optimize.hpp
new file mode 100644
index 0000000000..f9d9ebebdc
--- /dev/null
+++ b/boost/xpressive/detail/core/optimize.hpp
@@ -0,0 +1,116 @@
+///////////////////////////////////////////////////////////////////////////////
+// optimize.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_OPTIMIZE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_OPTIMIZE_HPP_EAN_10_04_2005
+
+#include <string>
+#include <utility>
+#include <boost/mpl/bool.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/xpressive/detail/core/finder.hpp>
+#include <boost/xpressive/detail/core/linker.hpp>
+#include <boost/xpressive/detail/core/peeker.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// optimize_regex
+//
+template<typename BidiIter, typename Traits>
+intrusive_ptr<finder<BidiIter> > optimize_regex
+(
+ xpression_peeker<typename iterator_value<BidiIter>::type> const &peeker
+ , Traits const &tr
+ , mpl::false_
+)
+{
+ if(peeker.line_start())
+ {
+ return intrusive_ptr<finder<BidiIter> >
+ (
+ new line_start_finder<BidiIter, Traits>(tr)
+ );
+ }
+ else if(peeker.leading_simple_repeat())
+ {
+ return intrusive_ptr<finder<BidiIter> >
+ (
+ new leading_simple_repeat_finder<BidiIter>()
+ );
+ }
+ else if(256 != peeker.bitset().count())
+ {
+ return intrusive_ptr<finder<BidiIter> >
+ (
+ new hash_peek_finder<BidiIter, Traits>(peeker.bitset())
+ );
+ }
+
+ return intrusive_ptr<finder<BidiIter> >();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// optimize_regex
+//
+template<typename BidiIter, typename Traits>
+intrusive_ptr<finder<BidiIter> > optimize_regex
+(
+ xpression_peeker<typename iterator_value<BidiIter>::type> const &peeker
+ , Traits const &tr
+ , mpl::true_
+)
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ // if we have a leading string literal, initialize a boyer-moore struct with it
+ peeker_string<char_type> const &str = peeker.get_string();
+ if(str.begin_ != str.end_)
+ {
+ BOOST_ASSERT(1 == peeker.bitset().count());
+ return intrusive_ptr<finder<BidiIter> >
+ (
+ new boyer_moore_finder<BidiIter, Traits>(str.begin_, str.end_, tr, str.icase_)
+ );
+ }
+
+ return optimize_regex<BidiIter>(peeker, tr, mpl::false_());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// common_compile
+//
+template<typename BidiIter, typename Traits>
+void common_compile
+(
+ intrusive_ptr<matchable_ex<BidiIter> const> const &regex
+ , regex_impl<BidiIter> &impl
+ , Traits const &tr
+)
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ // "link" the regex
+ xpression_linker<char_type> linker(tr);
+ regex->link(linker);
+
+ // "peek" into the compiled regex to see if there are optimization opportunities
+ hash_peek_bitset<char_type> bset;
+ xpression_peeker<char_type> peeker(bset, tr, linker.has_backrefs());
+ regex->peek(peeker);
+
+ // optimization: get the peek chars OR the boyer-moore search string
+ impl.finder_ = optimize_regex<BidiIter>(peeker, tr, is_random<BidiIter>());
+ impl.xpr_ = regex;
+}
+
+}}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/detail/core/peeker.hpp b/boost/xpressive/detail/core/peeker.hpp
new file mode 100644
index 0000000000..45183fc49c
--- /dev/null
+++ b/boost/xpressive/detail/core/peeker.hpp
@@ -0,0 +1,284 @@
+///////////////////////////////////////////////////////////////////////////////
+// peeker.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_PEEKER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_PEEKER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <string>
+#include <typeinfo>
+#include <boost/assert.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/size_t.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/matchers.hpp>
+#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
+#include <boost/xpressive/detail/utility/never_true.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// peeker_string
+//
+template<typename Char>
+struct peeker_string
+{
+ Char const *begin_;
+ Char const *end_;
+ bool icase_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// char_sink
+//
+template<typename Traits, bool ICase>
+struct char_sink
+{
+ typedef typename Traits::char_type char_type;
+
+ char_sink(hash_peek_bitset<char_type> &bset, Traits const &tr)
+ : bset_(bset)
+ , traits_(tr)
+ {}
+
+ void operator()(char_type ch) const
+ {
+ this->bset_.set_char(ch, ICase, this->traits_);
+ }
+
+ hash_peek_bitset<char_type> &bset_;
+ Traits const &traits_;
+private:
+ char_sink &operator =(char_sink const &);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// xpression_peeker
+//
+template<typename Char>
+struct xpression_peeker
+{
+ template<typename Traits>
+ xpression_peeker(hash_peek_bitset<Char> &bset, Traits const &tr, bool has_backrefs = false)
+ : bset_(bset)
+ , str_()
+ , line_start_(false)
+ , traits_(0)
+ , traits_type_(0)
+ , leading_simple_repeat_(0)
+ , has_backrefs_(has_backrefs)
+ {
+ this->set_traits(tr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // accessors
+ peeker_string<Char> const &get_string() const
+ {
+ return this->str_;
+ }
+
+ bool line_start() const
+ {
+ return this->line_start_;
+ }
+
+ bool leading_simple_repeat() const
+ {
+ return 0 < this->leading_simple_repeat_;
+ }
+
+ hash_peek_bitset<Char> const &bitset() const
+ {
+ return this->bset_;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // modifiers
+ void fail()
+ {
+ this->bset_.set_all();
+ }
+
+ template<typename Matcher>
+ mpl::false_ accept(Matcher const &)
+ {
+ this->fail();
+ return mpl::false_();
+ }
+
+ mpl::true_ accept(mark_begin_matcher const &)
+ {
+ if(this->has_backrefs_)
+ {
+ --this->leading_simple_repeat_;
+ }
+ return mpl::true_();
+ }
+
+ mpl::true_ accept(repeat_begin_matcher const &)
+ {
+ --this->leading_simple_repeat_;
+ return mpl::true_();
+ }
+
+ template<typename Traits>
+ mpl::true_ accept(assert_bol_matcher<Traits> const &)
+ {
+ this->line_start_ = true;
+ return mpl::true_();
+ }
+
+ template<typename Traits, typename ICase>
+ mpl::false_ accept(literal_matcher<Traits, ICase, mpl::false_> const &xpr)
+ {
+ this->bset_.set_char(xpr.ch_, ICase(), this->get_traits_<Traits>());
+ return mpl::false_();
+ }
+
+ template<typename Traits, typename ICase>
+ mpl::false_ accept(string_matcher<Traits, ICase> const &xpr)
+ {
+ this->bset_.set_char(xpr.str_[0], ICase(), this->get_traits_<Traits>());
+ this->str_.begin_ = detail::data_begin(xpr.str_);
+ this->str_.end_ = detail::data_end(xpr.str_);
+ this->str_.icase_ = ICase::value;
+ return mpl::false_();
+ }
+
+ template<typename Alternates, typename Traits>
+ mpl::false_ accept(alternate_matcher<Alternates, Traits> const &xpr)
+ {
+ BOOST_ASSERT(0 != xpr.bset_.count());
+ this->bset_.set_bitset(xpr.bset_);
+ return mpl::false_();
+ }
+
+ template<typename Matcher, typename Traits, typename ICase>
+ mpl::false_ accept(attr_matcher<Matcher, Traits, ICase> const &xpr)
+ {
+ xpr.sym_.peek(char_sink<Traits, ICase::value>(this->bset_, this->get_traits_<Traits>()));
+ return mpl::false_();
+ }
+
+ template<typename Xpr, typename Greedy>
+ mpl::false_ accept(optional_matcher<Xpr, Greedy> const &)
+ {
+ this->fail(); // a union of xpr and next
+ return mpl::false_();
+ }
+
+ template<typename Xpr, typename Greedy>
+ mpl::false_ accept(optional_mark_matcher<Xpr, Greedy> const &)
+ {
+ this->fail(); // a union of xpr and next
+ return mpl::false_();
+ }
+
+ //template<typename Xpr, typename Greedy>
+ //mpl::true_ accept(optional_matcher<Xpr, Greedy> const &xpr)
+ //{
+ // xpr.xpr_.peek(*this); // a union of xpr and next
+ // return mpl::true_();
+ //}
+
+ //template<typename Xpr, typename Greedy>
+ //mpl::true_ accept(optional_mark_matcher<Xpr, Greedy> const &xpr)
+ //{
+ // xpr.xpr_.peek(*this); // a union of xpr and next
+ // return mpl::true_();
+ //}
+
+ template<typename Traits>
+ mpl::false_ accept(posix_charset_matcher<Traits> const &xpr)
+ {
+ this->bset_.set_class(xpr.mask_, xpr.not_, this->get_traits_<Traits>());
+ return mpl::false_();
+ }
+
+ template<typename ICase, typename Traits>
+ typename enable_if<is_narrow_char<typename Traits::char_type>, mpl::false_>::type
+ accept(charset_matcher<Traits, ICase, basic_chset<Char> > const &xpr)
+ {
+ BOOST_ASSERT(0 != xpr.charset_.base().count());
+ this->bset_.set_charset(xpr.charset_, ICase());
+ return mpl::false_();
+ }
+
+ template<typename Traits, typename ICase>
+ mpl::false_ accept(range_matcher<Traits, ICase> const &xpr)
+ {
+ this->bset_.set_range(xpr.ch_min_, xpr.ch_max_, xpr.not_, ICase(), this->get_traits_<Traits>());
+ return mpl::false_();
+ }
+
+ template<typename Xpr, typename Greedy>
+ mpl::false_ accept(simple_repeat_matcher<Xpr, Greedy> const &xpr)
+ {
+ if(Greedy() && 1U == xpr.width_)
+ {
+ ++this->leading_simple_repeat_;
+ xpr.leading_ = this->leading_simple_repeat();
+ }
+ 0 != xpr.min_ ? xpr.xpr_.peek(*this) : this->fail(); // could be a union of xpr and next
+ return mpl::false_();
+ }
+
+ template<typename Xpr>
+ mpl::false_ accept(keeper_matcher<Xpr> const &xpr)
+ {
+ xpr.xpr_.peek(*this);
+ return mpl::false_();
+ }
+
+ template<typename Traits>
+ void set_traits(Traits const &tr)
+ {
+ if(0 == this->traits_)
+ {
+ this->traits_ = &tr;
+ this->traits_type_ = &typeid(Traits);
+ }
+ else if(*this->traits_type_ != typeid(Traits) || this->get_traits_<Traits>() != tr)
+ {
+ this->fail(); // traits mis-match! set all and bail
+ }
+ }
+
+private:
+ xpression_peeker(xpression_peeker const &);
+ xpression_peeker &operator =(xpression_peeker const &);
+
+ template<typename Traits>
+ Traits const &get_traits_() const
+ {
+ BOOST_ASSERT(!!(*this->traits_type_ == typeid(Traits)));
+ return *static_cast<Traits const *>(this->traits_);
+ }
+
+ hash_peek_bitset<Char> &bset_;
+ peeker_string<Char> str_;
+ bool str_icase_;
+ bool line_start_;
+ void const *traits_;
+ std::type_info const *traits_type_;
+ int leading_simple_repeat_;
+ bool has_backrefs_;
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/quant_style.hpp b/boost/xpressive/detail/core/quant_style.hpp
new file mode 100644
index 0000000000..ae3b0cfdc7
--- /dev/null
+++ b/boost/xpressive/detail/core/quant_style.hpp
@@ -0,0 +1,129 @@
+///////////////////////////////////////////////////////////////////////////////
+// quant_style.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_QUANT_STYLE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_QUANT_STYLE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/xpressive/detail/utility/width.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+BOOST_MPL_HAS_XXX_TRAIT_DEF(is_boost_xpressive_xpression_)
+
+///////////////////////////////////////////////////////////////////////////////
+// is_xpr
+//
+template<typename Xpr>
+struct is_xpr
+ : has_is_boost_xpressive_xpression_<Xpr>
+{};
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_enum
+//
+enum quant_enum
+{
+ quant_none,
+ quant_fixed_width,
+ quant_variable_width
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_style
+//
+template<quant_enum QuantStyle, std::size_t Width = unknown_width::value, bool Pure = true>
+struct quant_style
+{
+ typedef void is_boost_xpressive_xpression_;
+
+ // Which quantification strategy to use?
+ BOOST_STATIC_CONSTANT(int, quant = QuantStyle);
+
+ // how many characters this matcher consumes
+ BOOST_STATIC_CONSTANT(std::size_t, width = Width);
+
+ // whether this matcher has observable side-effects
+ BOOST_STATIC_CONSTANT(bool, pure = Pure);
+
+ static detail::width get_width()
+ {
+ return width;
+ }
+};
+
+#define BOOST_XPR_QUANT_STYLE(Style, Width, Pure) \
+ typedef void is_boost_xpressive_xpression_; \
+ BOOST_STATIC_CONSTANT(int, quant = Style); \
+ BOOST_STATIC_CONSTANT(std::size_t, width = Width); \
+ BOOST_STATIC_CONSTANT(bool, pure = Pure); \
+ static detail::width get_width() { return width; } \
+ /**/
+
+// // Replace transmogrify stupidity with rebindable matchers/placeholders
+//#define BOOST_XPR_IDENTITY_REBIND(TYPE) \/
+// template<typename BidiIter, typename ICase, typename Traits> \/
+// struct rebind \/
+// { \/
+// typedef TYPE type; \/
+// }; \/
+// /**/
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_style_none
+// this sub-expression cannot be quantified
+typedef quant_style<quant_none> quant_style_none;
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_style_fixed_unknown_width
+// this sub-expression is fixed width for the purpose of quantification, but
+// the width cannot be determined at compile time. An example would be the
+// string_matcher or the mark_matcher.
+typedef quant_style<quant_fixed_width> quant_style_fixed_unknown_width;
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_style_variable_width
+// this sub-expression can match a variable number of characters
+typedef quant_style<quant_variable_width> quant_style_variable_width;
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_style_fixed_width
+// for when the sub-expression has a fixed width that is known at compile time
+template<std::size_t Width>
+struct quant_style_fixed_width
+ : quant_style<quant_fixed_width, Width>
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_style_assertion
+// a zero-width assertion.
+struct quant_style_assertion
+ : quant_style<quant_none, 0>
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// quant_type
+//
+template<typename Matcher>
+struct quant_type
+ : mpl::int_<Matcher::quant>
+{
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/regex_domain.hpp b/boost/xpressive/detail/core/regex_domain.hpp
new file mode 100644
index 0000000000..18f34809be
--- /dev/null
+++ b/boost/xpressive/detail/core/regex_domain.hpp
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_domain.hpp
+/// Contains the definition of the regex_domain type
+//
+// Copyright 2009 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_REGEX_DOMAIN_HPP_EAN_12_12_2009
+#define BOOST_XPRESSIVE_DETAIL_CORE_REGEX_DOMAIN_HPP_EAN_12_12_2009
+
+#include <boost/xpressive/xpressive_fwd.hpp>
+#include <boost/proto/traits.hpp>
+#include <boost/proto/domain.hpp>
+#include <boost/proto/generate.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ struct regex_domain
+ : proto::domain<proto::default_generator, proto::not_<proto::address_of<proto::_> > >
+ {};
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/core/regex_impl.hpp b/boost/xpressive/detail/core/regex_impl.hpp
new file mode 100644
index 0000000000..8c3194632b
--- /dev/null
+++ b/boost/xpressive/detail/core/regex_impl.hpp
@@ -0,0 +1,212 @@
+///////////////////////////////////////////////////////////////////////////////
+// regex_impl.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_REGEX_IMPL_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_REGEX_IMPL_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <vector>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/xpressive/regex_traits.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/dynamic/matchable.hpp>
+#include <boost/xpressive/detail/utility/tracking_ptr.hpp>
+#include <boost/xpressive/detail/utility/counted_base.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// finder
+template<typename BidiIter>
+struct finder
+ : counted_base<finder<BidiIter> >
+{
+ virtual ~finder() {}
+ virtual bool ok_for_partial_matches() const { return true; }
+ virtual bool operator ()(match_state<BidiIter> &state) const = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// traits
+template<typename Char>
+struct traits
+ : counted_base<traits<Char> >
+{
+ virtual ~traits() {}
+ virtual Char tolower(Char ch) const = 0;
+ virtual Char toupper(Char ch) const = 0;
+ virtual bool in_range(Char from, Char to, Char ch) const = 0;
+ virtual int value(Char ch, int radix) const = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// named_mark
+template<typename Char>
+struct named_mark
+{
+ typedef typename detail::string_type<Char>::type string_type;
+
+ named_mark(string_type name, std::size_t mark_nbr)
+ : name_(name)
+ , mark_nbr_(mark_nbr)
+ {}
+
+ string_type name_;
+ std::size_t mark_nbr_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// traits_holder
+template<typename Traits>
+struct traits_holder
+ : traits<typename Traits::char_type>
+{
+ typedef typename Traits::char_type char_type;
+
+ explicit traits_holder(Traits const &tr)
+ : traits_(tr)
+ {
+ }
+
+ Traits const &traits() const
+ {
+ return this->traits_;
+ }
+
+ char_type tolower(char_type ch) const
+ {
+ return this->tolower_(ch, typename Traits::version_tag());
+ }
+
+ char_type toupper(char_type ch) const
+ {
+ return this->toupper_(ch, typename Traits::version_tag());
+ }
+
+ int value(char_type ch, int radix) const
+ {
+ return this->traits_.value(ch, radix);
+ }
+
+ bool in_range(char_type from, char_type to, char_type ch) const
+ {
+ return this->traits_.in_range(from, to, ch);
+ }
+
+private:
+ char_type tolower_(char_type ch, regex_traits_version_1_tag) const
+ {
+ return ch;
+ }
+
+ char_type toupper_(char_type ch, regex_traits_version_1_tag) const
+ {
+ return ch;
+ }
+
+ char_type tolower_(char_type ch, regex_traits_version_2_tag) const
+ {
+ return this->traits_.tolower(ch);
+ }
+
+ char_type toupper_(char_type ch, regex_traits_version_2_tag) const
+ {
+ return this->traits_.toupper(ch);
+ }
+
+ Traits traits_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_impl
+//
+template<typename BidiIter>
+struct regex_impl
+ : enable_reference_tracking<regex_impl<BidiIter> >
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ regex_impl()
+ : enable_reference_tracking<regex_impl<BidiIter> >()
+ , xpr_()
+ , traits_()
+ , finder_()
+ , named_marks_()
+ , mark_count_(0)
+ , hidden_mark_count_(0)
+ {
+ #ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
+ ++instances;
+ #endif
+ }
+
+ regex_impl(regex_impl<BidiIter> const &that)
+ : enable_reference_tracking<regex_impl<BidiIter> >(that)
+ , xpr_(that.xpr_)
+ , traits_(that.traits_)
+ , finder_(that.finder_)
+ , named_marks_(that.named_marks_)
+ , mark_count_(that.mark_count_)
+ , hidden_mark_count_(that.hidden_mark_count_)
+ {
+ #ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
+ ++instances;
+ #endif
+ }
+
+ ~regex_impl()
+ {
+ #ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
+ --instances;
+ #endif
+ }
+
+ void swap(regex_impl<BidiIter> &that)
+ {
+ enable_reference_tracking<regex_impl<BidiIter> >::swap(that);
+ this->xpr_.swap(that.xpr_);
+ this->traits_.swap(that.traits_);
+ this->finder_.swap(that.finder_);
+ this->named_marks_.swap(that.named_marks_);
+ std::swap(this->mark_count_, that.mark_count_);
+ std::swap(this->hidden_mark_count_, that.hidden_mark_count_);
+ }
+
+ intrusive_ptr<matchable_ex<BidiIter> const> xpr_;
+ intrusive_ptr<traits<char_type> const> traits_;
+ intrusive_ptr<finder<BidiIter> > finder_;
+ std::vector<named_mark<char_type> > named_marks_;
+ std::size_t mark_count_;
+ std::size_t hidden_mark_count_;
+
+ #ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
+ static int instances;
+ #endif
+
+private:
+ regex_impl &operator =(regex_impl const &);
+};
+
+template<typename BidiIter>
+void swap(regex_impl<BidiIter> &left, regex_impl<BidiIter> &right)
+{
+ left.swap(right);
+}
+
+#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
+template<typename BidiIter>
+int regex_impl<BidiIter>::instances = 0;
+#endif
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/results_cache.hpp b/boost/xpressive/detail/core/results_cache.hpp
new file mode 100644
index 0000000000..702c61e7d3
--- /dev/null
+++ b/boost/xpressive/detail/core/results_cache.hpp
@@ -0,0 +1,134 @@
+///////////////////////////////////////////////////////////////////////////////
+// results_cache.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <cstddef>
+#include <boost/detail/workaround.hpp>
+#include <boost/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/list.hpp>
+#include <boost/xpressive/detail/core/access.hpp>
+#include <boost/xpressive/match_results.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // nested_results
+ #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
+ template<typename BidiIter>
+ struct nested_results
+ : detail::list<match_results<BidiIter> >
+ {
+ friend struct results_cache<BidiIter>;
+ friend struct match_results<BidiIter>;
+ };
+ #else
+ template<typename BidiIter>
+ struct nested_results
+ : private detail::list<match_results<BidiIter> >
+ {
+ friend struct results_cache<BidiIter>;
+ friend struct xpressive::match_results<BidiIter>;
+ typedef list<xpressive::match_results<BidiIter> > base_type;
+
+ typedef typename base_type::iterator iterator;
+ typedef typename base_type::const_iterator const_iterator;
+ typedef typename base_type::pointer pointer;
+ typedef typename base_type::const_pointer const_pointer;
+ typedef typename base_type::reference reference;
+ typedef typename base_type::const_reference const_reference;
+ typedef typename base_type::size_type size_type;
+ using base_type::begin;
+ using base_type::end;
+ using base_type::size;
+ using base_type::empty;
+ using base_type::front;
+ using base_type::back;
+ };
+ #endif
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // results_cache
+ //
+ // cache storage for reclaimed match_results structs
+ template<typename BidiIter>
+ struct results_cache
+ {
+ typedef core_access<BidiIter> access;
+
+ match_results<BidiIter> &append_new(nested_results<BidiIter> &out)
+ {
+ if(this->cache_.empty())
+ {
+ out.push_back(match_results<BidiIter>());
+ }
+ else
+ {
+ BOOST_ASSERT(access::get_nested_results(this->cache_.back()).empty());
+ out.splice(out.end(), this->cache_, --this->cache_.end());
+ }
+ return out.back();
+ }
+
+ // move the last match_results struct into the cache
+ void reclaim_last(nested_results<BidiIter> &out)
+ {
+ BOOST_ASSERT(!out.empty());
+ // first, reclaim any nested results
+ nested_results<BidiIter> &nested = access::get_nested_results(out.back());
+ if(!nested.empty())
+ {
+ this->reclaim_all(nested);
+ }
+ // then, reclaim the last match_results
+ this->cache_.splice(this->cache_.end(), out, --out.end());
+ }
+
+ // move the last n match_results structs into the cache
+ void reclaim_last_n(nested_results<BidiIter> &out, std::size_t count)
+ {
+ for(; 0 != count; --count)
+ {
+ this->reclaim_last(out);
+ }
+ }
+
+ void reclaim_all(nested_results<BidiIter> &out)
+ {
+ typedef typename nested_results<BidiIter>::iterator iter_type;
+
+ // first, recursively reclaim all the nested results
+ for(iter_type begin = out.begin(); begin != out.end(); ++begin)
+ {
+ nested_results<BidiIter> &nested = access::get_nested_results(*begin);
+
+ if(!nested.empty())
+ {
+ this->reclaim_all(nested);
+ }
+ }
+
+ // next, reclaim the results themselves
+ this->cache_.splice(this->cache_.end(), out);
+ }
+
+ private:
+
+ nested_results<BidiIter> cache_;
+ };
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/state.hpp b/boost/xpressive/detail/core/state.hpp
new file mode 100644
index 0000000000..e20c91572e
--- /dev/null
+++ b/boost/xpressive/detail/core/state.hpp
@@ -0,0 +1,401 @@
+///////////////////////////////////////////////////////////////////////////////
+// state.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/access.hpp>
+#include <boost/xpressive/detail/core/action.hpp>
+#include <boost/xpressive/detail/core/sub_match_vector.hpp>
+#include <boost/xpressive/detail/utility/sequence_stack.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// match_context
+//
+template<typename BidiIter>
+struct match_context
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ match_context()
+ : results_ptr_(0)
+ , prev_context_(0)
+ , next_ptr_(0)
+ , traits_(0)
+ {
+ }
+
+ // pointer to the current match results, passed to actions as a parameter.
+ match_results<BidiIter> *results_ptr_;
+
+ // The previous match context, if this match_context corresponds to a nested regex invocation
+ match_context<BidiIter> *prev_context_;
+
+ // If this is a nested match, the "next" sub-expression to execute after the nested match
+ matchable<BidiIter> const *next_ptr_;
+
+ // A pointer to the current traits object
+ detail::traits<char_type> const *traits_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// attr_context
+//
+struct attr_context
+{
+ // Slots for holding type-erased pointers to attributes
+ void const **attr_slots_;
+
+ // The previous attr context, if one exists
+ attr_context *prev_attr_context_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// match_flags
+//
+struct match_flags
+{
+ bool match_all_;
+ bool match_prev_avail_;
+ bool match_bol_;
+ bool match_eol_;
+ bool match_not_bow_;
+ bool match_not_eow_;
+ bool match_not_null_;
+ bool match_continuous_;
+ bool match_partial_;
+
+ explicit match_flags(regex_constants::match_flag_type flags)
+ : match_all_(false)
+ , match_prev_avail_(0 != (flags & regex_constants::match_prev_avail))
+ , match_bol_(match_prev_avail_ || 0 == (flags & regex_constants::match_not_bol))
+ , match_eol_(0 == (flags & regex_constants::match_not_eol))
+ , match_not_bow_(!match_prev_avail_ && 0 != (flags & regex_constants::match_not_bow))
+ , match_not_eow_(0 != (flags & regex_constants::match_not_eow))
+ , match_not_null_(0 != (flags & regex_constants::match_not_null))
+ , match_continuous_(0 != (flags & regex_constants::match_continuous))
+ , match_partial_(0 != (flags & regex_constants::match_partial))
+ {
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// match_state
+//
+template<typename BidiIter>
+struct match_state
+ : noncopyable
+{
+ typedef BidiIter iterator;
+ typedef core_access<BidiIter> access;
+ typedef detail::match_context<BidiIter> match_context;
+ typedef detail::results_extras<BidiIter> results_extras;
+ typedef detail::regex_impl<BidiIter> regex_impl;
+ typedef detail::matchable<BidiIter> matchable;
+ typedef xpressive::match_results<BidiIter> match_results;
+ typedef detail::sub_match_impl<BidiIter> sub_match_impl;
+ typedef detail::actionable actionable;
+
+ BidiIter cur_;
+ sub_match_impl *sub_matches_;
+ std::size_t mark_count_;
+ BidiIter begin_;
+ BidiIter end_;
+
+ match_flags flags_;
+ bool found_partial_match_;
+
+ match_context context_;
+ results_extras *extras_;
+ actionable action_list_;
+ actionable const **action_list_tail_;
+ action_args_type *action_args_;
+ attr_context attr_context_;
+ BidiIter next_search_;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ match_state
+ (
+ BidiIter begin
+ , BidiIter end
+ , match_results &what
+ , regex_impl const &impl
+ , regex_constants::match_flag_type flags
+ )
+ : cur_(begin)
+ , sub_matches_(0)
+ , mark_count_(0)
+ , begin_(begin)
+ , end_(end)
+ , flags_(flags)
+ , found_partial_match_(false)
+ , context_() // zero-initializes the fields of context_
+ , extras_(&core_access<BidiIter>::get_extras(what))
+ , action_list_()
+ , action_list_tail_(&action_list_.next)
+ , action_args_(&core_access<BidiIter>::get_action_args(what))
+ , attr_context_() // zero-initializes the fields of attr_context_
+ , next_search_(begin)
+ {
+ // reclaim any cached memory in the match_results struct
+ this->extras_->sub_match_stack_.unwind();
+
+ // initialize the context_ struct
+ this->init_(impl, what);
+
+ // move all the nested match_results structs into the match_results cache
+ this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // reset
+ void reset(match_results &what, regex_impl const &impl)
+ {
+ this->extras_ = &core_access<BidiIter>::get_extras(what);
+ this->action_list_.next = 0;
+ this->action_list_tail_ = &action_list_.next;
+ this->action_args_ = &core_access<BidiIter>::get_action_args(what);
+ this->attr_context_ = attr_context();
+ this->context_.prev_context_ = 0;
+ this->found_partial_match_ = false;
+ this->extras_->sub_match_stack_.unwind();
+ this->init_(impl, what);
+ this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // push_context
+ // called to prepare the state object for a regex match
+ match_context push_context(regex_impl const &impl, matchable const &next, match_context &prev)
+ {
+ // save state
+ match_context context = this->context_;
+
+ // create a new nested match_results for this regex
+ nested_results<BidiIter> &nested = access::get_nested_results(*context.results_ptr_);
+ match_results &what = this->extras_->results_cache_.append_new(nested);
+
+ // (re)initialize the match context
+ this->init_(impl, what);
+
+ // create a linked list of match_context structs
+ this->context_.prev_context_ = &prev;
+ this->context_.next_ptr_ = &next;
+
+ // record the start of the zero-th sub-match
+ this->sub_matches_[0].begin_ = this->cur_;
+
+ return context;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // pop_context
+ // called after a nested match failed to restore the context
+ bool pop_context(regex_impl const &impl, bool success)
+ {
+ match_context &context = *this->context_.prev_context_;
+ if(!success)
+ {
+ match_results &what = *context.results_ptr_;
+ this->uninit_(impl, what);
+
+ // send the match_results struct back to the cache
+ nested_results<BidiIter> &nested = access::get_nested_results(what);
+ this->extras_->results_cache_.reclaim_last(nested);
+ }
+
+ // restore the state
+ this->context_ = context;
+ match_results &results = *this->context_.results_ptr_;
+ this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
+ this->mark_count_ = results.size();
+ return success;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // swap_context
+ void swap_context(match_context &context)
+ {
+ std::swap(this->context_, context);
+ match_results &results = *this->context_.results_ptr_;
+ this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
+ this->mark_count_ = results.size();
+ }
+
+ // beginning of buffer
+ bool bos() const
+ {
+ return this->cur_ == this->begin_;
+ }
+
+ // end of buffer
+ bool eos()
+ {
+ return this->cur_ == this->end_ && this->found_partial_match();
+ }
+
+ // is this the regex that is currently executing?
+ bool is_active_regex(regex_impl const &impl) const
+ {
+ return impl.xpr_.get() == this->context_.results_ptr_->regex_id();
+ }
+
+ // fetch the n-th sub_match
+ sub_match_impl &sub_match(int n)
+ {
+ return this->sub_matches_[n];
+ }
+
+ // called when a partial match has succeeded
+ void set_partial_match()
+ {
+ sub_match_impl &sub0 = this->sub_match(0);
+ sub0.first = sub0.begin_;
+ sub0.second = this->end_;
+ sub0.matched = false;
+ }
+
+ template<typename Traits>
+ Traits const &get_traits() const
+ {
+ return static_cast<traits_holder<Traits> const *>(this->context_.traits_)->traits();
+ }
+
+private:
+
+ void init_(regex_impl const &impl, match_results &what)
+ {
+ regex_id_type const id = impl.xpr_.get();
+ std::size_t const total_mark_count = impl.mark_count_ + impl.hidden_mark_count_ + 1;
+
+ // initialize the context and the sub_match vector
+ this->context_.results_ptr_ = &what;
+ this->context_.traits_ = impl.traits_.get();
+ this->mark_count_ = impl.mark_count_ + 1;
+ this->sub_matches_ = this->extras_->sub_match_stack_.push_sequence(total_mark_count, sub_match_impl(begin_), detail::fill);
+ this->sub_matches_ += impl.hidden_mark_count_;
+
+ // initialize the match_results struct
+ access::init_match_results(what, id, impl.traits_, this->sub_matches_, this->mark_count_, impl.named_marks_);
+ }
+
+ void uninit_(regex_impl const &impl, match_results &)
+ {
+ extras_->sub_match_stack_.unwind_to(this->sub_matches_ - impl.hidden_mark_count_);
+ }
+
+ bool found_partial_match()
+ {
+ this->found_partial_match_ = true;
+ return true;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// memento
+//
+template<typename BidiIter>
+struct memento
+{
+ sub_match_impl<BidiIter> *old_sub_matches_;
+ std::size_t nested_results_count_;
+ actionable const *action_list_head_;
+ actionable const **action_list_tail_;
+ attr_context attr_context_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// save_sub_matches
+//
+template<typename BidiIter>
+inline memento<BidiIter> save_sub_matches(match_state<BidiIter> &state)
+{
+ memento<BidiIter> mem =
+ {
+ state.extras_->sub_match_stack_.push_sequence(state.mark_count_, sub_match_impl<BidiIter>(state.begin_))
+ , state.context_.results_ptr_->nested_results().size()
+ , state.action_list_.next
+ , state.action_list_tail_
+ , state.attr_context_
+ };
+ state.action_list_.next = 0;
+ state.action_list_tail_ = &state.action_list_.next;
+ std::copy(state.sub_matches_, state.sub_matches_ + state.mark_count_, mem.old_sub_matches_);
+ return mem;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// restore_action_queue
+//
+template<typename BidiIter>
+inline void restore_action_queue(memento<BidiIter> const &mem, match_state<BidiIter> &state)
+{
+ state.action_list_.next = mem.action_list_head_;
+ state.action_list_tail_ = mem.action_list_tail_;
+ *state.action_list_tail_ = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// restore_sub_matches
+//
+template<typename BidiIter>
+inline void restore_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state)
+{
+ typedef core_access<BidiIter> access;
+ nested_results<BidiIter> &nested = access::get_nested_results(*state.context_.results_ptr_);
+ std::size_t count = nested.size() - mem.nested_results_count_;
+ state.extras_->results_cache_.reclaim_last_n(nested, count);
+ std::copy(mem.old_sub_matches_, mem.old_sub_matches_ + state.mark_count_, state.sub_matches_);
+ state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
+ state.attr_context_ = mem.attr_context_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// reclaim_sub_matches
+//
+template<typename BidiIter>
+inline void reclaim_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state, bool success)
+{
+ std::size_t count = state.context_.results_ptr_->nested_results().size() - mem.nested_results_count_;
+ if(count == 0)
+ {
+ state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
+ }
+ // else we have we must orphan this block of backrefs because we are using the stack
+ // space above it.
+
+ if(!success)
+ {
+ state.attr_context_ = mem.attr_context_;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// traits_cast
+//
+template<typename Traits, typename BidiIter>
+inline Traits const &traits_cast(match_state<BidiIter> const &state)
+{
+ return state.template get_traits<Traits>();
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/sub_match_impl.hpp b/boost/xpressive/detail/core/sub_match_impl.hpp
new file mode 100644
index 0000000000..0301dd48eb
--- /dev/null
+++ b/boost/xpressive/detail/core/sub_match_impl.hpp
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+// sub_match_impl.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_IMPL_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_IMPL_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/sub_match.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+// TODO: sub_match_impl is a POD IFF BidiIter is POD. Pool allocation
+// of them can be made more efficient if they are. Or maybe all they
+// need is trivial constructor/destructor. (???)
+
+///////////////////////////////////////////////////////////////////////////////
+// sub_match_impl
+//
+template<typename BidiIter>
+struct sub_match_impl
+ : sub_match<BidiIter>
+{
+ unsigned int repeat_count_;
+ BidiIter begin_;
+ bool zero_width_;
+
+ sub_match_impl(BidiIter const &begin)
+ : sub_match<BidiIter>(begin, begin)
+ , repeat_count_(0)
+ , begin_(begin)
+ , zero_width_(false)
+ {
+ }
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/core/sub_match_vector.hpp b/boost/xpressive/detail/core/sub_match_vector.hpp
new file mode 100644
index 0000000000..d10ee7641c
--- /dev/null
+++ b/boost/xpressive/detail/core/sub_match_vector.hpp
@@ -0,0 +1,171 @@
+///////////////////////////////////////////////////////////////////////////////
+// sub_match_vector.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_VECTOR_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_VECTOR_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/iterator_adaptors.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/sub_match_impl.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
+
+//////////////////////////////////////////////////////////////////////////
+// sub_match_iterator
+//
+template<typename Value, typename MainIter>
+struct sub_match_iterator
+ : iterator_adaptor
+ <
+ sub_match_iterator<Value, MainIter>
+ , MainIter
+ , Value
+ , std::random_access_iterator_tag
+ >
+{
+ typedef iterator_adaptor
+ <
+ sub_match_iterator<Value, MainIter>
+ , MainIter
+ , Value
+ , std::random_access_iterator_tag
+ > base_t;
+
+ sub_match_iterator(MainIter baseiter)
+ : base_t(baseiter)
+ {
+ }
+};
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+// sub_match_vector
+//
+template<typename BidiIter>
+struct sub_match_vector
+ : private noncopyable
+{
+private:
+ struct dummy { int i_; };
+ typedef int dummy::*bool_type;
+
+public:
+ typedef sub_match<BidiIter> value_type;
+ typedef std::size_t size_type;
+ typedef value_type const &const_reference;
+ typedef const_reference reference;
+ typedef typename iterator_difference<BidiIter>::type difference_type;
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef typename sub_match<BidiIter>::string_type string_type;
+
+#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
+
+ typedef sub_match_iterator
+ <
+ value_type const
+ , sub_match_impl<BidiIter> const *
+ > const_iterator;
+
+#else
+
+ typedef iterator_adaptor
+ <
+ sub_match_impl<BidiIter> const *
+ , default_iterator_policies
+ , value_type
+ , value_type const &
+ , value_type const *
+ > const_iterator;
+
+#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
+
+ typedef const_iterator iterator;
+
+ sub_match_vector()
+ : size_(0)
+ , sub_matches_(0)
+ {
+ }
+
+ const_reference operator [](size_type index) const
+ {
+ static value_type const s_null;
+ return (index >= this->size_)
+ ? s_null
+ : *static_cast<value_type const *>(&this->sub_matches_[ index ]);
+ }
+
+ size_type size() const
+ {
+ return this->size_;
+ }
+
+ bool empty() const
+ {
+ return 0 == this->size();
+ }
+
+ const_iterator begin() const
+ {
+ return const_iterator(this->sub_matches_);
+ }
+
+ const_iterator end() const
+ {
+ return const_iterator(this->sub_matches_ + this->size_);
+ }
+
+ operator bool_type() const
+ {
+ return (!this->empty() && (*this)[0].matched) ? &dummy::i_ : 0;
+ }
+
+ bool operator !() const
+ {
+ return this->empty() || !(*this)[0].matched;
+ }
+
+ void swap(sub_match_vector<BidiIter> &that)
+ {
+ std::swap(this->size_, that.size_);
+ std::swap(this->sub_matches_, that.sub_matches_);
+ }
+
+private:
+ friend struct detail::core_access<BidiIter>;
+
+ void init_(sub_match_impl<BidiIter> *sub_matches, size_type size)
+ {
+ this->size_ = size;
+ this->sub_matches_ = sub_matches;
+ }
+
+ void init_(sub_match_impl<BidiIter> *sub_matches, size_type size, sub_match_vector<BidiIter> const &that)
+ {
+ BOOST_ASSERT(size == that.size_);
+ this->size_ = size;
+ this->sub_matches_ = sub_matches;
+ std::copy(that.sub_matches_, that.sub_matches_ + that.size_, this->sub_matches_);
+ }
+
+ size_type size_;
+ sub_match_impl<BidiIter> *sub_matches_;
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/detail_fwd.hpp b/boost/xpressive/detail/detail_fwd.hpp
new file mode 100644
index 0000000000..52deaae9a8
--- /dev/null
+++ b/boost/xpressive/detail/detail_fwd.hpp
@@ -0,0 +1,486 @@
+///////////////////////////////////////////////////////////////////////////////
+// detail_fwd.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DETAIL_FWD_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_DETAIL_FWD_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <map>
+#include <string>
+#include <vector>
+#include <climits> // for INT_MAX
+#include <typeinfo>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/size_t.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/xpressive/xpressive_fwd.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ typedef unsigned int uint_t;
+
+ template<uint_t Min, uint_t Max = Min>
+ struct generic_quant_tag;
+
+ struct modifier_tag;
+
+ struct check_tag;
+
+ typedef mpl::size_t<INT_MAX / 2 - 1> unknown_width;
+
+ struct type_info_less;
+
+ typedef std::map<std::type_info const *, void *, type_info_less> action_args_type;
+
+ struct action_context;
+
+ struct ReplaceAlgo;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // placeholders
+ //
+ struct mark_placeholder;
+
+ struct posix_charset_placeholder;
+
+ template<typename Cond>
+ struct assert_word_placeholder;
+
+ template<typename Char>
+ struct range_placeholder;
+
+ struct assert_bol_placeholder;
+
+ struct assert_eol_placeholder;
+
+ struct logical_newline_placeholder;
+
+ struct self_placeholder;
+
+ template<typename Nbr>
+ struct attribute_placeholder;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // matchers
+ //
+ struct end_matcher;
+
+ struct independent_end_matcher;
+
+ struct assert_bos_matcher;
+
+ struct assert_eos_matcher;
+
+ template<typename Traits>
+ struct assert_bol_matcher;
+
+ template<typename Traits>
+ struct assert_eol_matcher;
+
+ template<typename Cond, typename Traits>
+ struct assert_word_matcher;
+
+ struct true_matcher;
+
+ template<typename Alternates, typename Traits>
+ struct alternate_matcher;
+
+ struct alternate_end_matcher;
+
+ template<typename Traits>
+ struct posix_charset_matcher;
+
+ template<typename BidiIter>
+ struct sequence;
+
+ template<typename Traits, typename ICase>
+ struct mark_matcher;
+
+ struct mark_begin_matcher;
+
+ struct mark_end_matcher;
+
+ template<typename BidiIter>
+ struct regex_matcher;
+
+ template<typename BidiIter>
+ struct regex_byref_matcher;
+
+ template<typename Traits>
+ struct compound_charset;
+
+ template<typename Traits, typename ICase, typename CharSet = compound_charset<Traits> >
+ struct charset_matcher;
+
+ template<typename Traits, typename ICase>
+ struct range_matcher;
+
+ template<typename Traits, typename Size>
+ struct set_matcher;
+
+ template<typename Xpr, typename Greedy>
+ struct simple_repeat_matcher;
+
+ struct repeat_begin_matcher;
+
+ template<typename Greedy>
+ struct repeat_end_matcher;
+
+ template<typename Traits, typename ICase, typename Not>
+ struct literal_matcher;
+
+ template<typename Traits, typename ICase>
+ struct string_matcher;
+
+ template<typename Actor>
+ struct action_matcher;
+
+ template<typename Predicate>
+ struct predicate_matcher;
+
+ template<typename Xpr, typename Greedy>
+ struct optional_matcher;
+
+ template<typename Xpr, typename Greedy>
+ struct optional_mark_matcher;
+
+ template<typename Matcher, typename Traits, typename ICase>
+ struct attr_matcher;
+
+ template<typename Nbr>
+ struct attr_begin_matcher;
+
+ struct attr_end_matcher;
+
+ template<typename Xpr>
+ struct is_modifiable;
+
+ template<typename Head, typename Tail>
+ struct alternates_list;
+
+ template<typename Modifier>
+ struct modifier_op;
+
+ struct icase_modifier;
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct xpression_visitor;
+
+ template<typename BidiIter>
+ struct regex_impl;
+
+ struct epsilon_matcher;
+
+ template<typename BidiIter>
+ struct nested_results;
+
+ template<typename BidiIter>
+ struct regex_id_filter_predicate;
+
+ template<typename Xpr>
+ struct keeper_matcher;
+
+ template<typename Xpr>
+ struct lookahead_matcher;
+
+ template<typename Xpr>
+ struct lookbehind_matcher;
+
+ template<typename IsBoundary>
+ struct word_boundary;
+
+ template<typename BidiIter, typename Matcher>
+ sequence<BidiIter> make_dynamic(Matcher const &matcher);
+
+ template<typename Char>
+ struct xpression_linker;
+
+ template<typename Char>
+ struct xpression_peeker;
+
+ struct any_matcher;
+
+ template<typename Traits>
+ struct logical_newline_matcher;
+
+ typedef proto::expr<proto::tag::terminal, proto::term<logical_newline_placeholder>, 0> logical_newline_xpression;
+
+ struct set_initializer;
+
+ typedef proto::expr<proto::tag::terminal, proto::term<set_initializer>, 0> set_initializer_type;
+
+ struct lookahead_tag;
+
+ struct lookbehind_tag;
+
+ struct keeper_tag;
+
+ template<typename Locale>
+ struct locale_modifier;
+
+ template<typename Matcher>
+ struct matcher_wrapper;
+
+ template<typename Locale, typename BidiIter>
+ struct regex_traits_type;
+
+ template<typename Expr>
+ struct let_;
+
+ template<typename Args, typename BidiIter>
+ void bind_args(let_<Args> const &, match_results<BidiIter> &);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ struct no_next;
+
+ template<typename BidiIter>
+ struct core_access;
+
+ template<typename BidiIter>
+ struct match_state;
+
+ template<typename BidiIter>
+ struct matchable;
+
+ template<typename BidiIter>
+ struct matchable_ex;
+
+ template<typename Matcher, typename BidiIter>
+ struct dynamic_xpression;
+
+ template<typename BidiIter>
+ struct shared_matchable;
+
+ template<typename BidiIter>
+ struct alternates_vector;
+
+ template<typename Matcher, typename Next>
+ struct static_xpression;
+
+ typedef static_xpression<end_matcher, no_next> end_xpression;
+
+ typedef static_xpression<alternate_end_matcher, no_next> alternate_end_xpression;
+
+ typedef static_xpression<independent_end_matcher, no_next> independent_end_xpression;
+
+ typedef static_xpression<true_matcher, no_next> true_xpression;
+
+ template<typename Matcher, typename Next = end_xpression>
+ struct static_xpression;
+
+ template<typename Top, typename Next>
+ struct stacked_xpression;
+
+ template<typename Xpr>
+ struct is_static_xpression;
+
+ template<typename BidiIter>
+ struct sub_match_impl;
+
+ template<typename T>
+ struct list;
+
+ template<typename BidiIter>
+ struct results_cache;
+
+ template<typename T>
+ struct sequence_stack;
+
+ template<typename BidiIter>
+ struct results_extras;
+
+ template<typename BidiIter>
+ struct match_context;
+
+ template<typename BidiIter>
+ struct sub_match_vector;
+
+ template<typename T, typename U>
+ struct action_arg;
+
+ struct actionable;
+
+ template<typename Char>
+ struct traits;
+
+ template<typename Traits, typename BidiIter>
+ Traits const &traits_cast(match_state<BidiIter> const &state);
+
+ template<typename Char>
+ struct basic_chset;
+
+ template<typename Char>
+ struct named_mark;
+
+ template<typename BidiIter>
+ struct memento;
+
+ template<typename Char, typename Traits>
+ void set_char(compound_charset<Traits> &chset, Char ch, Traits const &tr, bool icase);
+
+ template<typename Char, typename Traits>
+ void set_range(compound_charset<Traits> &chset, Char from, Char to, Traits const &tr, bool icase);
+
+ template<typename Traits>
+ void set_class(compound_charset<Traits> &chset, typename Traits::char_class_type char_class, bool no, Traits const &tr);
+
+ template<typename Char, typename Traits>
+ void set_char(basic_chset<Char> &chset, Char ch, Traits const &tr, bool icase);
+
+ template<typename Char, typename Traits>
+ void set_range(basic_chset<Char> &chset, Char from, Char to, Traits const &tr, bool icase);
+
+ template<typename Char, typename Traits>
+ void set_class(basic_chset<Char> &chset, typename Traits::char_class_type char_class, bool no, Traits const &tr);
+
+ template<typename Matcher>
+ static_xpression<Matcher> const
+ make_static(Matcher const &matcher);
+
+ template<typename Matcher, typename Next>
+ static_xpression<Matcher, Next> const
+ make_static(Matcher const &matcher, Next const &next);
+
+ int get_mark_number(basic_mark_tag const &);
+
+ template<typename Xpr, typename BidiIter>
+ void static_compile(Xpr const &xpr, shared_ptr<regex_impl<BidiIter> > const &impl);
+
+ struct quant_spec;
+
+ template<typename BidiIter, typename Xpr>
+ void make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq, Xpr const &xpr);
+
+ template<typename BidiIter>
+ void make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq);
+
+ template<typename BidiIter>
+ void make_repeat(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr);
+
+ template<typename BidiIter>
+ void make_repeat(quant_spec const &spec, sequence<BidiIter> &seq);
+
+ template<typename BidiIter>
+ void make_optional(quant_spec const &spec, sequence<BidiIter> &seq);
+
+ template<typename BidiIter>
+ void make_optional(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr);
+
+ template<typename Char>
+ struct string_type
+ {
+ typedef std::vector<Char> type;
+ };
+
+ template<>
+ struct string_type<char>
+ {
+ typedef std::string type;
+ };
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ template<>
+ struct string_type<wchar_t>
+ {
+ typedef std::wstring type;
+ };
+ #endif
+
+}}} // namespace boost::xpressive::detail
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+ using proto::_;
+ using proto::or_;
+ using proto::if_;
+ using proto::call;
+ using proto::when;
+ using proto::otherwise;
+ using proto::switch_;
+ using proto::make;
+ using proto::_child;
+ using proto::_value;
+ using proto::_left;
+ using proto::_right;
+ using proto::not_;
+ using proto::_state;
+ using proto::_data;
+ using proto::callable;
+ using proto::transform;
+ using proto::fold;
+ using proto::reverse_fold;
+ using proto::fold_tree;
+ using proto::reverse_fold_tree;
+ using proto::terminal;
+ using proto::shift_right;
+ using proto::bitwise_or;
+ using proto::logical_not;
+ using proto::dereference;
+ using proto::unary_plus;
+ using proto::negate;
+ using proto::complement;
+ using proto::comma;
+ using proto::assign;
+ using proto::subscript;
+ using proto::nary_expr;
+ using proto::unary_expr;
+ using proto::binary_expr;
+ using proto::_deep_copy;
+ using proto::vararg;
+ namespace tag = proto::tag;
+}}}
+
+namespace boost { namespace xpressive { namespace op
+{
+ struct push;
+ struct push_back;
+ struct pop;
+ struct push_front;
+ struct pop_back;
+ struct pop_front;
+ struct back;
+ struct front;
+ struct top;
+ struct first;
+ struct second;
+ struct matched;
+ struct length;
+ struct str;
+ struct insert;
+ struct make_pair;
+
+ template<typename T>
+ struct as;
+ template<typename T>
+ struct static_cast_;
+ template<typename T>
+ struct dynamic_cast_;
+ template<typename T>
+ struct const_cast_;
+ template<typename T>
+ struct construct;
+ template<typename T>
+ struct throw_;
+}}} // namespace boost::xpressive::op
+
+/// INTERNAL ONLY
+namespace boost { namespace xpressive
+{
+
+ /// INTERNAL ONLY
+ template<typename Traits, std::size_t N>
+ typename Traits::char_class_type
+ lookup_classname(Traits const &traits, char const (&cname)[N], bool icase = false);
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/detail/dynamic/dynamic.hpp b/boost/xpressive/detail/dynamic/dynamic.hpp
new file mode 100644
index 0000000000..afbff0c145
--- /dev/null
+++ b/boost/xpressive/detail/dynamic/dynamic.hpp
@@ -0,0 +1,337 @@
+///////////////////////////////////////////////////////////////////////////////
+// dynamic.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <vector>
+#include <utility>
+#include <algorithm>
+#include <boost/assert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/dynamic/matchable.hpp>
+#include <boost/xpressive/detail/dynamic/sequence.hpp>
+#include <boost/xpressive/detail/core/icase.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// invalid_xpression
+template<typename BidiIter>
+struct invalid_xpression
+ : matchable_ex<BidiIter>
+{
+ invalid_xpression()
+ : matchable_ex<BidiIter>()
+ {
+ intrusive_ptr_add_ref(this); // keep alive forever
+ }
+
+ bool match(match_state<BidiIter> &) const
+ {
+ BOOST_ASSERT(false);
+ return false;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// get_invalid_xpression
+template<typename BidiIter>
+inline shared_matchable<BidiIter> const &get_invalid_xpression()
+{
+ static invalid_xpression<BidiIter> const invalid_xpr;
+ static intrusive_ptr<matchable_ex<BidiIter> const> const invalid_ptr(&invalid_xpr);
+ static shared_matchable<BidiIter> const invalid_matchable(invalid_ptr);
+ return invalid_matchable;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// dynamic_xpression
+template<typename Matcher, typename BidiIter>
+struct dynamic_xpression
+ : Matcher
+ , matchable_ex<BidiIter>
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+
+ dynamic_xpression(Matcher const &matcher = Matcher())
+ : Matcher(matcher)
+ , next_(get_invalid_xpression<BidiIter>())
+ {
+ }
+
+ virtual bool match(match_state<BidiIter> &state) const
+ {
+ return this->Matcher::match(state, *this->next_.matchable());
+ }
+
+ virtual void link(xpression_linker<char_type> &linker) const
+ {
+ linker.accept(*static_cast<Matcher const *>(this), this->next_.matchable().get());
+ this->next_.link(linker);
+ }
+
+ virtual void peek(xpression_peeker<char_type> &peeker) const
+ {
+ this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker);
+ }
+
+ virtual void repeat(quant_spec const &spec, sequence<BidiIter> &seq) const
+ {
+ this->repeat_(spec, seq, quant_type<Matcher>(), is_same<Matcher, mark_begin_matcher>());
+ }
+
+private:
+ friend struct sequence<BidiIter>;
+
+ void peek_next_(mpl::true_, xpression_peeker<char_type> &peeker) const
+ {
+ this->next_.peek(peeker);
+ }
+
+ void peek_next_(mpl::false_, xpression_peeker<char_type> &) const
+ {
+ // no-op
+ }
+
+ void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_none>, mpl::false_) const
+ {
+ if(quant_none == seq.quant())
+ {
+ BOOST_THROW_EXCEPTION(
+ regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
+ );
+ }
+ else
+ {
+ this->repeat_(spec, seq, mpl::int_<quant_variable_width>(), mpl::false_());
+ }
+ }
+
+ void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::false_) const
+ {
+ if(this->next_ == get_invalid_xpression<BidiIter>())
+ {
+ make_simple_repeat(spec, seq, matcher_wrapper<Matcher>(*this));
+ }
+ else
+ {
+ this->repeat_(spec, seq, mpl::int_<quant_variable_width>(), mpl::false_());
+ }
+ }
+
+ void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_variable_width>, mpl::false_) const
+ {
+ if(!is_unknown(seq.width()) && seq.pure())
+ {
+ make_simple_repeat(spec, seq);
+ }
+ else
+ {
+ make_repeat(spec, seq);
+ }
+ }
+
+ void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::true_) const
+ {
+ make_repeat(spec, seq, this->mark_number_);
+ }
+
+ shared_matchable<BidiIter> next_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// make_dynamic
+template<typename BidiIter, typename Matcher>
+inline sequence<BidiIter> make_dynamic(Matcher const &matcher)
+{
+ typedef dynamic_xpression<Matcher, BidiIter> xpression_type;
+ intrusive_ptr<xpression_type> xpr(new xpression_type(matcher));
+ return sequence<BidiIter>(xpr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// alternates_vector
+template<typename BidiIter>
+struct alternates_vector
+ : std::vector<shared_matchable<BidiIter> >
+{
+ BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
+ BOOST_STATIC_CONSTANT(bool, pure = false);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// matcher_wrapper
+template<typename Matcher>
+struct matcher_wrapper
+ : Matcher
+{
+ matcher_wrapper(Matcher const &matcher = Matcher())
+ : Matcher(matcher)
+ {
+ }
+
+ template<typename BidiIter>
+ bool match(match_state<BidiIter> &state) const
+ {
+ return this->Matcher::match(state, matcher_wrapper<true_matcher>());
+ }
+
+ template<typename Char>
+ void link(xpression_linker<Char> &linker) const
+ {
+ linker.accept(*static_cast<Matcher const *>(this), 0);
+ }
+
+ template<typename Char>
+ void peek(xpression_peeker<Char> &peeker) const
+ {
+ peeker.accept(*static_cast<Matcher const *>(this));
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// make_simple_repeat
+template<typename BidiIter, typename Xpr>
+inline void
+make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq, Xpr const &xpr)
+{
+ if(spec.greedy_)
+ {
+ simple_repeat_matcher<Xpr, mpl::true_> quant(xpr, spec.min_, spec.max_, seq.width().value());
+ seq = make_dynamic<BidiIter>(quant);
+ }
+ else
+ {
+ simple_repeat_matcher<Xpr, mpl::false_> quant(xpr, spec.min_, spec.max_, seq.width().value());
+ seq = make_dynamic<BidiIter>(quant);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// make_simple_repeat
+template<typename BidiIter>
+inline void
+make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq)
+{
+ seq += make_dynamic<BidiIter>(true_matcher());
+ make_simple_repeat(spec, seq, seq.xpr());
+}
+
+//////////////////////////////////////////////////////////////////////////
+// make_optional
+template<typename BidiIter>
+inline void
+make_optional(quant_spec const &spec, sequence<BidiIter> &seq)
+{
+ typedef shared_matchable<BidiIter> xpr_type;
+ seq += make_dynamic<BidiIter>(alternate_end_matcher());
+ if(spec.greedy_)
+ {
+ optional_matcher<xpr_type, mpl::true_> opt(seq.xpr());
+ seq = make_dynamic<BidiIter>(opt);
+ }
+ else
+ {
+ optional_matcher<xpr_type, mpl::false_> opt(seq.xpr());
+ seq = make_dynamic<BidiIter>(opt);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// make_optional
+template<typename BidiIter>
+inline void
+make_optional(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr)
+{
+ typedef shared_matchable<BidiIter> xpr_type;
+ seq += make_dynamic<BidiIter>(alternate_end_matcher());
+ if(spec.greedy_)
+ {
+ optional_mark_matcher<xpr_type, mpl::true_> opt(seq.xpr(), mark_nbr);
+ seq = make_dynamic<BidiIter>(opt);
+ }
+ else
+ {
+ optional_mark_matcher<xpr_type, mpl::false_> opt(seq.xpr(), mark_nbr);
+ seq = make_dynamic<BidiIter>(opt);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// make_repeat
+template<typename BidiIter>
+inline void
+make_repeat(quant_spec const &spec, sequence<BidiIter> &seq)
+{
+ // only bother creating a repeater if max is greater than one
+ if(1 < spec.max_)
+ {
+ // create a hidden mark so this expression can be quantified
+ int mark_nbr = -static_cast<int>(++*spec.hidden_mark_count_);
+ seq = make_dynamic<BidiIter>(mark_begin_matcher(mark_nbr)) + seq
+ + make_dynamic<BidiIter>(mark_end_matcher(mark_nbr));
+ make_repeat(spec, seq, mark_nbr);
+ return;
+ }
+
+ // if min is 0, the repeat must be made optional
+ if(0 == spec.min_)
+ {
+ make_optional(spec, seq);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// make_repeat
+template<typename BidiIter>
+inline void
+make_repeat(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr)
+{
+ BOOST_ASSERT(spec.max_); // we should never get here if max is 0
+
+ // only bother creating a repeater if max is greater than one
+ if(1 < spec.max_)
+ {
+ // TODO: statically bind the repeat matchers to the mark matchers for better perf
+ unsigned int min = spec.min_ ? spec.min_ : 1U;
+ repeat_begin_matcher repeat_begin(mark_nbr);
+ if(spec.greedy_)
+ {
+ repeat_end_matcher<mpl::true_> repeat_end(mark_nbr, min, spec.max_);
+ seq = make_dynamic<BidiIter>(repeat_begin) + seq
+ + make_dynamic<BidiIter>(repeat_end);
+ }
+ else
+ {
+ repeat_end_matcher<mpl::false_> repeat_end(mark_nbr, min, spec.max_);
+ seq = make_dynamic<BidiIter>(repeat_begin) + seq
+ + make_dynamic<BidiIter>(repeat_end);
+ }
+ }
+
+ // if min is 0, the repeat must be made optional
+ if(0 == spec.min_)
+ {
+ make_optional(spec, seq, mark_nbr);
+ }
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/dynamic/matchable.hpp b/boost/xpressive/detail/dynamic/matchable.hpp
new file mode 100644
index 0000000000..320bc698af
--- /dev/null
+++ b/boost/xpressive/detail/dynamic/matchable.hpp
@@ -0,0 +1,177 @@
+///////////////////////////////////////////////////////////////////////////////
+// matchable.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/utility/counted_base.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/dynamic/sequence.hpp>
+#include <boost/xpressive/regex_error.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+//////////////////////////////////////////////////////////////////////////
+// quant_spec
+struct quant_spec
+{
+ unsigned int min_;
+ unsigned int max_;
+ bool greedy_;
+ std::size_t *hidden_mark_count_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// matchable
+template<typename BidiIter>
+struct matchable
+{
+ typedef BidiIter iterator_type;
+ typedef typename iterator_value<iterator_type>::type char_type;
+ virtual ~matchable() {}
+ virtual bool match(match_state<BidiIter> &state) const = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// matchable_ex
+template<typename BidiIter>
+struct matchable_ex
+ : matchable<BidiIter>
+ , counted_base<matchable_ex<BidiIter> >
+{
+ typedef BidiIter iterator_type;
+ typedef typename iterator_value<iterator_type>::type char_type;
+
+ virtual void link(xpression_linker<char_type> &) const
+ {
+ }
+
+ virtual void peek(xpression_peeker<char_type> &peeker) const
+ {
+ peeker.fail();
+ }
+
+ virtual void repeat(quant_spec const &, sequence<BidiIter> &) const
+ {
+ BOOST_THROW_EXCEPTION(
+ regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
+ );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // The following 4 functions (push_match, top_match, pop_match and skip_match) are
+ // used to implement looping and branching across the matchers. Call push_match to record
+ // a position. Then, another matcher further down the xpression chain has the
+ // option to call either top_match, pop_match or skip_match. top_match and pop_match will
+ // jump back to the place recorded by push_match, whereas skip_match will skip the jump and
+ // pass execution down the xpression chain. top_match will leave the xpression on top of the
+ // stack, whereas pop_match will remove it. Each function comes in 2 flavors: one for
+ // statically bound xpressions and one for dynamically bound xpressions.
+ //
+
+ template<typename Top>
+ bool push_match(match_state<BidiIter> &state) const
+ {
+ BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
+ return this->match(state);
+ }
+
+ static bool top_match(match_state<BidiIter> &state, void const *top)
+ {
+ return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
+ }
+
+ static bool pop_match(match_state<BidiIter> &state, void const *top)
+ {
+ return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
+ }
+
+ bool skip_match(match_state<BidiIter> &state) const
+ {
+ return this->match(state);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// shared_matchable
+template<typename BidiIter>
+struct shared_matchable
+{
+ typedef BidiIter iterator_type;
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef intrusive_ptr<matchable_ex<BidiIter> const> matchable_ptr;
+
+ BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
+ BOOST_STATIC_CONSTANT(bool, pure = false);
+
+ shared_matchable(matchable_ptr const &xpr = matchable_ptr())
+ : xpr_(xpr)
+ {
+ }
+
+ bool operator !() const
+ {
+ return !this->xpr_;
+ }
+
+ friend bool operator ==(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
+ {
+ return left.xpr_ == right.xpr_;
+ }
+
+ friend bool operator !=(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
+ {
+ return left.xpr_ != right.xpr_;
+ }
+
+ matchable_ptr const &matchable() const
+ {
+ return this->xpr_;
+ }
+
+ bool match(match_state<BidiIter> &state) const
+ {
+ return this->xpr_->match(state);
+ }
+
+ void link(xpression_linker<char_type> &linker) const
+ {
+ this->xpr_->link(linker);
+ }
+
+ void peek(xpression_peeker<char_type> &peeker) const
+ {
+ this->xpr_->peek(peeker);
+ }
+
+ // BUGBUG yuk!
+ template<typename Top>
+ bool push_match(match_state<BidiIter> &state) const
+ {
+ BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
+ return this->match(state);
+ }
+
+private:
+ matchable_ptr xpr_;
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/dynamic/parse_charset.hpp b/boost/xpressive/detail/dynamic/parse_charset.hpp
new file mode 100644
index 0000000000..d4e3671d4b
--- /dev/null
+++ b/boost/xpressive/detail/dynamic/parse_charset.hpp
@@ -0,0 +1,365 @@
+///////////////////////////////////////////////////////////////////////////////
+// parse_charset.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSE_CHARSET_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSE_CHARSET_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/integer.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/numeric/conversion/converter.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/dynamic/parser_enum.hpp>
+#include <boost/xpressive/detail/utility/literals.hpp>
+#include <boost/xpressive/detail/utility/chset/chset.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+enum escape_type
+{
+ escape_char
+ , escape_mark
+ , escape_class
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// escape_value
+//
+template<typename Char, typename Class>
+struct escape_value
+{
+ Char ch_;
+ int mark_nbr_;
+ Class class_;
+ escape_type type_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// char_overflow_handler
+//
+struct char_overflow_handler
+{
+ void operator ()(numeric::range_check_result result) const // throw(regex_error)
+ {
+ if(numeric::cInRange != result)
+ {
+ BOOST_THROW_EXCEPTION(
+ regex_error(
+ regex_constants::error_escape
+ , "character escape too large to fit in target character type"
+ )
+ );
+ }
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// parse_escape
+//
+template<typename FwdIter, typename CompilerTraits>
+escape_value<typename iterator_value<FwdIter>::type, typename CompilerTraits::regex_traits::char_class_type>
+parse_escape(FwdIter &begin, FwdIter end, CompilerTraits &tr)
+{
+ using namespace regex_constants;
+ typedef typename iterator_value<FwdIter>::type char_type;
+ typedef typename CompilerTraits::regex_traits regex_traits;
+ typedef typename regex_traits::char_class_type char_class_type;
+
+ // define an unsigned type the same size as char_type
+ typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
+ BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
+ typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
+
+ BOOST_XPR_ENSURE_(begin != end, error_escape, "unexpected end of pattern found");
+ numeric::converter<int, uchar_t, converstion_traits, char_overflow_handler> converter;
+ escape_value<char_type,char_class_type> esc = { 0, 0, 0, escape_char };
+ bool const icase = (0 != (regex_constants::icase_ & tr.flags()));
+ regex_traits const &rxtraits = tr.traits();
+ FwdIter tmp;
+
+ esc.class_ = rxtraits.lookup_classname(begin, begin + 1, icase);
+ if(0 != esc.class_)
+ {
+ esc.type_ = escape_class;
+ return esc;
+ }
+
+ if(-1 != rxtraits.value(*begin, 8))
+ {
+ esc.ch_ = converter(toi(begin, end, rxtraits, 8, 0777));
+ return esc;
+ }
+
+ switch(*begin)
+ {
+ // bell character
+ case BOOST_XPR_CHAR_(char_type, 'a'):
+ esc.ch_ = BOOST_XPR_CHAR_(char_type, '\a');
+ ++begin;
+ break;
+ // escape character
+ case BOOST_XPR_CHAR_(char_type, 'e'):
+ esc.ch_ = converter(27);
+ ++begin;
+ break;
+ // control character
+ case BOOST_XPR_CHAR_(char_type, 'c'):
+ BOOST_XPR_ENSURE_(++begin != end, error_escape, "unexpected end of pattern found");
+ BOOST_XPR_ENSURE_
+ (
+ rxtraits.in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *begin)
+ || rxtraits.in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *begin)
+ , error_escape
+ , "invalid escape control letter; must be one of a-z or A-Z"
+ );
+ // Convert to character according to ECMA-262, section 15.10.2.10:
+ esc.ch_ = converter(*begin % 32);
+ ++begin;
+ break;
+ // formfeed character
+ case BOOST_XPR_CHAR_(char_type, 'f'):
+ esc.ch_ = BOOST_XPR_CHAR_(char_type, '\f');
+ ++begin;
+ break;
+ // newline
+ case BOOST_XPR_CHAR_(char_type, 'n'):
+ esc.ch_ = BOOST_XPR_CHAR_(char_type, '\n');
+ ++begin;
+ break;
+ // return
+ case BOOST_XPR_CHAR_(char_type, 'r'):
+ esc.ch_ = BOOST_XPR_CHAR_(char_type, '\r');
+ ++begin;
+ break;
+ // horizontal tab
+ case BOOST_XPR_CHAR_(char_type, 't'):
+ esc.ch_ = BOOST_XPR_CHAR_(char_type, '\t');
+ ++begin;
+ break;
+ // vertical tab
+ case BOOST_XPR_CHAR_(char_type, 'v'):
+ esc.ch_ = BOOST_XPR_CHAR_(char_type, '\v');
+ ++begin;
+ break;
+ // hex escape sequence
+ case BOOST_XPR_CHAR_(char_type, 'x'):
+ BOOST_XPR_ENSURE_(++begin != end, error_escape, "unexpected end of pattern found");
+ tmp = begin;
+ esc.ch_ = converter(toi(begin, end, rxtraits, 16, 0xff));
+ BOOST_XPR_ENSURE_(2 == std::distance(tmp, begin), error_escape, "invalid hex escape : "
+ "must be \\x HexDigit HexDigit");
+ break;
+ // Unicode escape sequence
+ case BOOST_XPR_CHAR_(char_type, 'u'):
+ BOOST_XPR_ENSURE_(++begin != end, error_escape, "unexpected end of pattern found");
+ tmp = begin;
+ esc.ch_ = converter(toi(begin, end, rxtraits, 16, 0xffff));
+ BOOST_XPR_ENSURE_(4 == std::distance(tmp, begin), error_escape, "invalid Unicode escape : "
+ "must be \\u HexDigit HexDigit HexDigit HexDigit");
+ break;
+ // backslash
+ case BOOST_XPR_CHAR_(char_type, '\\'):
+ //esc.ch_ = BOOST_XPR_CHAR_(char_type, '\\');
+ //++begin;
+ //break;
+ // all other escaped characters represent themselves
+ default:
+ esc.ch_ = *begin;
+ ++begin;
+ break;
+ }
+
+ return esc;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// parse_charset
+//
+template<typename FwdIter, typename RegexTraits, typename CompilerTraits>
+inline void parse_charset
+(
+ FwdIter &begin
+ , FwdIter end
+ , compound_charset<RegexTraits> &chset
+ , CompilerTraits &tr
+)
+{
+ using namespace regex_constants;
+ typedef typename RegexTraits::char_type char_type;
+ typedef typename RegexTraits::char_class_type char_class_type;
+ BOOST_ASSERT(begin != end);
+ RegexTraits const &rxtraits = tr.traits();
+ bool const icase = (0 != (regex_constants::icase_ & tr.flags()));
+ FwdIter iprev = FwdIter();
+ escape_value<char_type, char_class_type> esc = {0, 0, 0, escape_char};
+ bool invert = false;
+
+ // check to see if we have an inverse charset
+ if(begin != end && token_charset_invert == tr.get_charset_token(iprev = begin, end))
+ {
+ begin = iprev;
+ invert = true;
+ }
+
+ // skip the end token if-and-only-if it is the first token in the charset
+ if(begin != end && token_charset_end == tr.get_charset_token(iprev = begin, end))
+ {
+ for(; begin != iprev; ++begin)
+ {
+ chset.set_char(*begin, rxtraits, icase);
+ }
+ }
+
+ compiler_token_type tok;
+ char_type ch_prev = char_type(), ch_next = char_type();
+ bool have_prev = false;
+
+ BOOST_XPR_ENSURE_(begin != end, error_brack, "unexpected end of pattern found");
+
+ // remember the current position and grab the next token
+ iprev = begin;
+ tok = tr.get_charset_token(begin, end);
+ do
+ {
+ BOOST_XPR_ENSURE_(begin != end, error_brack, "unexpected end of pattern found");
+
+ if(token_charset_hyphen == tok && have_prev)
+ {
+ // remember the current position
+ FwdIter iprev2 = begin;
+ have_prev = false;
+
+ // ch_prev is lower bound of a range
+ switch(tr.get_charset_token(begin, end))
+ {
+ case token_charset_hyphen:
+ case token_charset_invert:
+ begin = iprev2; // un-get these tokens and fall through
+ case token_literal:
+ ch_next = *begin++;
+ BOOST_XPR_ENSURE_(ch_prev <= ch_next, error_range, "invalid charset range");
+ chset.set_range(ch_prev, ch_next, rxtraits, icase);
+ continue;
+ case token_charset_backspace:
+ ch_next = char_type(8); // backspace
+ BOOST_XPR_ENSURE_(ch_prev <= ch_next, error_range, "invalid charset range");
+ chset.set_range(ch_prev, ch_next, rxtraits, icase);
+ continue;
+ case token_escape:
+ esc = parse_escape(begin, end, tr);
+ if(escape_char == esc.type_)
+ {
+ BOOST_XPR_ENSURE_(ch_prev <= esc.ch_, error_range, "invalid charset range");
+ chset.set_range(ch_prev, esc.ch_, rxtraits, icase);
+ continue;
+ }
+ case token_charset_end: // fall through
+ default: // not a range.
+ begin = iprev; // backup to hyphen token
+ chset.set_char(ch_prev, rxtraits, icase);
+ chset.set_char(*begin++, rxtraits, icase);
+ continue;
+ }
+ }
+
+ if(have_prev)
+ {
+ chset.set_char(ch_prev, rxtraits, icase);
+ have_prev = false;
+ }
+
+ switch(tok)
+ {
+ case token_charset_hyphen:
+ case token_charset_invert:
+ case token_charset_end:
+ case token_posix_charset_end:
+ begin = iprev; // un-get these tokens
+ ch_prev = *begin++;
+ have_prev = true;
+ continue;
+
+ case token_charset_backspace:
+ ch_prev = char_type(8); // backspace
+ have_prev = true;
+ continue;
+
+ case token_posix_charset_begin:
+ {
+ FwdIter tmp = begin, start = begin;
+ bool invert = (token_charset_invert == tr.get_charset_token(tmp, end));
+ if(invert)
+ {
+ begin = start = tmp;
+ }
+ while(token_literal == (tok = tr.get_charset_token(begin, end)))
+ {
+ tmp = ++begin;
+ BOOST_XPR_ENSURE_(begin != end, error_brack, "unexpected end of pattern found");
+ }
+ if(token_posix_charset_end == tok)
+ {
+ char_class_type chclass = rxtraits.lookup_classname(start, tmp, icase);
+ BOOST_XPR_ENSURE_(0 != chclass, error_ctype, "unknown class name");
+ chset.set_class(chclass, invert);
+ continue;
+ }
+ begin = iprev; // un-get this token
+ ch_prev = *begin++;
+ have_prev = true;
+ }
+ continue;
+
+ case token_escape:
+ esc = parse_escape(begin, end, tr);
+ if(escape_char == esc.type_)
+ {
+ ch_prev = esc.ch_;
+ have_prev = true;
+ }
+ else if(escape_class == esc.type_)
+ {
+ char_class_type upper_ = lookup_classname(rxtraits, "upper");
+ BOOST_ASSERT(0 != upper_);
+ chset.set_class(esc.class_, rxtraits.isctype(*begin++, upper_));
+ }
+ else
+ {
+ BOOST_ASSERT(false);
+ }
+ continue;
+
+ default:
+ ch_prev = *begin++;
+ have_prev = true;
+ continue;
+ }
+ }
+ while(BOOST_XPR_ENSURE_((iprev = begin) != end, error_brack, "unexpected end of pattern found"),
+ token_charset_end != (tok = tr.get_charset_token(begin, end)));
+
+ if(have_prev)
+ {
+ chset.set_char(ch_prev, rxtraits, icase);
+ }
+
+ if(invert)
+ {
+ chset.inverse();
+ }
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/dynamic/parser.hpp b/boost/xpressive/detail/dynamic/parser.hpp
new file mode 100644
index 0000000000..0c25f33346
--- /dev/null
+++ b/boost/xpressive/detail/dynamic/parser.hpp
@@ -0,0 +1,360 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file parser.hpp
+/// Contains the definition of regex_compiler, a factory for building regex objects
+/// from strings.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/matchers.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+#include <boost/xpressive/detail/dynamic/dynamic.hpp>
+
+// The Regular Expression grammar, in pseudo BNF:
+//
+// expression = alternates ;
+//
+// alternates = sequence, *('|', sequence) ;
+//
+// sequence = quant, *(quant) ;
+//
+// quant = atom, [*+?] ;
+//
+// atom = literal |
+// '.' |
+// '\' any |
+// '(' expression ')' ;
+//
+// literal = not a meta-character ;
+//
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// make_char_xpression
+//
+template<typename BidiIter, typename Char, typename Traits>
+inline sequence<BidiIter> make_char_xpression
+(
+ Char ch
+ , regex_constants::syntax_option_type flags
+ , Traits const &tr
+)
+{
+ if(0 != (regex_constants::icase_ & flags))
+ {
+ literal_matcher<Traits, mpl::true_, mpl::false_> matcher(ch, tr);
+ return make_dynamic<BidiIter>(matcher);
+ }
+ else
+ {
+ literal_matcher<Traits, mpl::false_, mpl::false_> matcher(ch, tr);
+ return make_dynamic<BidiIter>(matcher);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_any_xpression
+//
+template<typename BidiIter, typename Traits>
+inline sequence<BidiIter> make_any_xpression
+(
+ regex_constants::syntax_option_type flags
+ , Traits const &tr
+)
+{
+ using namespace regex_constants;
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef detail::set_matcher<Traits, mpl::int_<2> > set_matcher;
+ typedef literal_matcher<Traits, mpl::false_, mpl::true_> literal_matcher;
+
+ char_type const newline = tr.widen('\n');
+ set_matcher s;
+ s.set_[0] = newline;
+ s.set_[1] = 0;
+ s.inverse();
+
+ switch(((int)not_dot_newline | not_dot_null) & flags)
+ {
+ case not_dot_null:
+ return make_dynamic<BidiIter>(literal_matcher(char_type(0), tr));
+
+ case not_dot_newline:
+ return make_dynamic<BidiIter>(literal_matcher(newline, tr));
+
+ case (int)not_dot_newline | not_dot_null:
+ return make_dynamic<BidiIter>(s);
+
+ default:
+ return make_dynamic<BidiIter>(any_matcher());
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_literal_xpression
+//
+template<typename BidiIter, typename Traits>
+inline sequence<BidiIter> make_literal_xpression
+(
+ typename Traits::string_type const &literal
+ , regex_constants::syntax_option_type flags
+ , Traits const &tr
+)
+{
+ BOOST_ASSERT(0 != literal.size());
+ if(1 == literal.size())
+ {
+ return make_char_xpression<BidiIter>(literal[0], flags, tr);
+ }
+
+ if(0 != (regex_constants::icase_ & flags))
+ {
+ string_matcher<Traits, mpl::true_> matcher(literal, tr);
+ return make_dynamic<BidiIter>(matcher);
+ }
+ else
+ {
+ string_matcher<Traits, mpl::false_> matcher(literal, tr);
+ return make_dynamic<BidiIter>(matcher);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_backref_xpression
+//
+template<typename BidiIter, typename Traits>
+inline sequence<BidiIter> make_backref_xpression
+(
+ int mark_nbr
+ , regex_constants::syntax_option_type flags
+ , Traits const &tr
+)
+{
+ if(0 != (regex_constants::icase_ & flags))
+ {
+ return make_dynamic<BidiIter>
+ (
+ mark_matcher<Traits, mpl::true_>(mark_nbr, tr)
+ );
+ }
+ else
+ {
+ return make_dynamic<BidiIter>
+ (
+ mark_matcher<Traits, mpl::false_>(mark_nbr, tr)
+ );
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// merge_charset
+//
+template<typename Char, typename Traits>
+inline void merge_charset
+(
+ basic_chset<Char> &basic
+ , compound_charset<Traits> const &compound
+ , Traits const &tr
+)
+{
+ detail::ignore_unused(tr);
+ if(0 != compound.posix_yes())
+ {
+ typename Traits::char_class_type mask = compound.posix_yes();
+ for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
+ {
+ if(tr.isctype((Char)i, mask))
+ {
+ basic.set((Char)i);
+ }
+ }
+ }
+
+ if(!compound.posix_no().empty())
+ {
+ for(std::size_t j = 0; j < compound.posix_no().size(); ++j)
+ {
+ typename Traits::char_class_type mask = compound.posix_no()[j];
+ for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
+ {
+ if(!tr.isctype((Char)i, mask))
+ {
+ basic.set((Char)i);
+ }
+ }
+ }
+ }
+
+ if(compound.is_inverted())
+ {
+ basic.inverse();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_charset_xpression
+//
+template<typename BidiIter, typename Traits>
+inline sequence<BidiIter> make_charset_xpression
+(
+ compound_charset<Traits> &chset
+ , Traits const &tr
+ , regex_constants::syntax_option_type flags
+)
+{
+ typedef typename Traits::char_type char_type;
+ bool const icase = (0 != (regex_constants::icase_ & flags));
+ bool const optimize = is_narrow_char<char_type>::value && 0 != (regex_constants::optimize & flags);
+
+ // don't care about compile speed -- fold eveything into a bitset<256>
+ if(optimize)
+ {
+ typedef basic_chset<char_type> charset_type;
+ charset_type charset(chset.base());
+ if(icase)
+ {
+ charset_matcher<Traits, mpl::true_, charset_type> matcher(charset);
+ merge_charset(matcher.charset_, chset, tr);
+ return make_dynamic<BidiIter>(matcher);
+ }
+ else
+ {
+ charset_matcher<Traits, mpl::false_, charset_type> matcher(charset);
+ merge_charset(matcher.charset_, chset, tr);
+ return make_dynamic<BidiIter>(matcher);
+ }
+ }
+
+ // special case to make [[:digit:]] fast
+ else if(chset.base().empty() && chset.posix_no().empty())
+ {
+ BOOST_ASSERT(0 != chset.posix_yes());
+ posix_charset_matcher<Traits> matcher(chset.posix_yes(), chset.is_inverted());
+ return make_dynamic<BidiIter>(matcher);
+ }
+
+ // default, slow
+ else
+ {
+ if(icase)
+ {
+ charset_matcher<Traits, mpl::true_> matcher(chset);
+ return make_dynamic<BidiIter>(matcher);
+ }
+ else
+ {
+ charset_matcher<Traits, mpl::false_> matcher(chset);
+ return make_dynamic<BidiIter>(matcher);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_posix_charset_xpression
+//
+template<typename BidiIter, typename Traits>
+inline sequence<BidiIter> make_posix_charset_xpression
+(
+ typename Traits::char_class_type m
+ , bool no
+ , regex_constants::syntax_option_type //flags
+ , Traits const & //traits
+)
+{
+ posix_charset_matcher<Traits> charset(m, no);
+ return make_dynamic<BidiIter>(charset);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_assert_begin_line
+//
+template<typename BidiIter, typename Traits>
+inline sequence<BidiIter> make_assert_begin_line
+(
+ regex_constants::syntax_option_type flags
+ , Traits const &tr
+)
+{
+ if(0 != (regex_constants::single_line & flags))
+ {
+ return detail::make_dynamic<BidiIter>(detail::assert_bos_matcher());
+ }
+ else
+ {
+ detail::assert_bol_matcher<Traits> matcher(tr);
+ return detail::make_dynamic<BidiIter>(matcher);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_assert_end_line
+//
+template<typename BidiIter, typename Traits>
+inline sequence<BidiIter> make_assert_end_line
+(
+ regex_constants::syntax_option_type flags
+ , Traits const &tr
+)
+{
+ if(0 != (regex_constants::single_line & flags))
+ {
+ return detail::make_dynamic<BidiIter>(detail::assert_eos_matcher());
+ }
+ else
+ {
+ detail::assert_eol_matcher<Traits> matcher(tr);
+ return detail::make_dynamic<BidiIter>(matcher);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_assert_word
+//
+template<typename BidiIter, typename Cond, typename Traits>
+inline sequence<BidiIter> make_assert_word(Cond, Traits const &tr)
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+ return detail::make_dynamic<BidiIter>
+ (
+ detail::assert_word_matcher<Cond, Traits>(tr)
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// make_independent_end_xpression
+//
+template<typename BidiIter>
+inline sequence<BidiIter> make_independent_end_xpression(bool pure)
+{
+ if(pure)
+ {
+ return detail::make_dynamic<BidiIter>(detail::true_matcher());
+ }
+ else
+ {
+ return detail::make_dynamic<BidiIter>(detail::independent_end_matcher());
+ }
+}
+
+}}} // namespace boost::xpressive::detail
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/dynamic/parser_enum.hpp b/boost/xpressive/detail/dynamic/parser_enum.hpp
new file mode 100644
index 0000000000..521f723b11
--- /dev/null
+++ b/boost/xpressive/detail/dynamic/parser_enum.hpp
@@ -0,0 +1,81 @@
+///////////////////////////////////////////////////////////////////////////////
+// parser_enum.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_ENUM_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_ENUM_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+namespace boost { namespace xpressive { namespace regex_constants
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// compiler_token_type
+//
+enum compiler_token_type
+{
+ token_literal,
+ token_any, // .
+ token_escape, //
+ token_group_begin, // (
+ token_group_end, // )
+ token_alternate, // |
+ token_invalid_quantifier, // {
+ token_charset_begin, // [
+ token_charset_end, // ]
+ token_charset_invert, // ^
+ token_charset_hyphen, // -
+ token_charset_backspace, // \b
+ token_posix_charset_begin, // [:
+ token_posix_charset_end, // :]
+ token_equivalence_class_begin, // [=
+ token_equivalence_class_end, // =]
+ token_collation_element_begin, // [.
+ token_collation_element_end, // .]
+
+ token_quote_meta_begin, // \Q
+ token_quote_meta_end, // \E
+
+ token_no_mark, // ?:
+ token_positive_lookahead, // ?=
+ token_negative_lookahead, // ?!
+ token_positive_lookbehind, // ?<=
+ token_negative_lookbehind, // ?<!
+ token_independent_sub_expression, // ?>
+ token_comment, // ?#
+ token_recurse, // ?R
+ token_rule_assign, // ?$[name]=
+ token_rule_ref, // ?$[name]
+ token_named_mark, // ?P<name>
+ token_named_mark_ref, // ?P=name
+
+ token_assert_begin_sequence, // \A
+ token_assert_end_sequence, // \Z
+ token_assert_begin_line, // ^
+ token_assert_end_line, // $
+ token_assert_word_begin, // \<
+ token_assert_word_end, // \>
+ token_assert_word_boundary, // \b
+ token_assert_not_word_boundary, // \B
+
+ token_escape_newline, // \n
+ token_escape_escape, // \e
+ token_escape_formfeed, // \f
+ token_escape_horizontal_tab, // \t
+ token_escape_vertical_tab, // \v
+ token_escape_bell, // \a
+ token_escape_control, // \c
+
+ token_end_of_pattern
+};
+
+}}} // namespace boost::xpressive::regex_constants
+
+#endif
diff --git a/boost/xpressive/detail/dynamic/parser_traits.hpp b/boost/xpressive/detail/dynamic/parser_traits.hpp
new file mode 100644
index 0000000000..6c3e152cac
--- /dev/null
+++ b/boost/xpressive/detail/dynamic/parser_traits.hpp
@@ -0,0 +1,474 @@
+///////////////////////////////////////////////////////////////////////////////
+// detail/dynamic/parser_traits.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_TRAITS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_TRAITS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <string>
+#include <climits>
+#include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/xpressive/regex_error.hpp>
+#include <boost/xpressive/regex_traits.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/dynamic/matchable.hpp>
+#include <boost/xpressive/detail/dynamic/parser_enum.hpp>
+#include <boost/xpressive/detail/utility/literals.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+
+namespace boost { namespace xpressive
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// compiler_traits
+// this works for char and wchar_t. it must be specialized for anything else.
+//
+template<typename RegexTraits>
+struct compiler_traits
+{
+ typedef RegexTraits regex_traits;
+ typedef typename regex_traits::char_type char_type;
+ typedef typename regex_traits::string_type string_type;
+ typedef typename regex_traits::locale_type locale_type;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // constructor
+ explicit compiler_traits(RegexTraits const &traits = RegexTraits())
+ : traits_(traits)
+ , flags_(regex_constants::ECMAScript)
+ , space_(lookup_classname(traits_, "space"))
+ , alnum_(lookup_classname(traits_, "alnum"))
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // flags
+ regex_constants::syntax_option_type flags() const
+ {
+ return this->flags_;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // flags
+ void flags(regex_constants::syntax_option_type flags)
+ {
+ this->flags_ = flags;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // traits
+ regex_traits &traits()
+ {
+ return this->traits_;
+ }
+
+ regex_traits const &traits() const
+ {
+ return this->traits_;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // imbue
+ locale_type imbue(locale_type const &loc)
+ {
+ locale_type oldloc = this->traits().imbue(loc);
+ this->space_ = lookup_classname(this->traits(), "space");
+ this->alnum_ = lookup_classname(this->traits(), "alnum");
+ return oldloc;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // getloc
+ locale_type getloc() const
+ {
+ return this->traits().getloc();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // get_token
+ // get a token and advance the iterator
+ template<typename FwdIter>
+ regex_constants::compiler_token_type get_token(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ if(this->eat_ws_(begin, end) == end)
+ {
+ return regex_constants::token_end_of_pattern;
+ }
+
+ switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, '\\'): return this->get_escape_token(++begin, end);
+ case BOOST_XPR_CHAR_(char_type, '.'): ++begin; return token_any;
+ case BOOST_XPR_CHAR_(char_type, '^'): ++begin; return token_assert_begin_line;
+ case BOOST_XPR_CHAR_(char_type, '$'): ++begin; return token_assert_end_line;
+ case BOOST_XPR_CHAR_(char_type, '('): ++begin; return token_group_begin;
+ case BOOST_XPR_CHAR_(char_type, ')'): ++begin; return token_group_end;
+ case BOOST_XPR_CHAR_(char_type, '|'): ++begin; return token_alternate;
+ case BOOST_XPR_CHAR_(char_type, '['): ++begin; return token_charset_begin;
+
+ case BOOST_XPR_CHAR_(char_type, '*'):
+ case BOOST_XPR_CHAR_(char_type, '+'):
+ case BOOST_XPR_CHAR_(char_type, '?'):
+ return token_invalid_quantifier;
+
+ case BOOST_XPR_CHAR_(char_type, ']'):
+ case BOOST_XPR_CHAR_(char_type, '{'):
+ default:
+ return token_literal;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // get_quant_spec
+ template<typename FwdIter>
+ bool get_quant_spec(FwdIter &begin, FwdIter end, detail::quant_spec &spec)
+ {
+ using namespace regex_constants;
+ FwdIter old_begin;
+
+ if(this->eat_ws_(begin, end) == end)
+ {
+ return false;
+ }
+
+ switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, '*'):
+ spec.min_ = 0;
+ spec.max_ = (std::numeric_limits<unsigned int>::max)();
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '+'):
+ spec.min_ = 1;
+ spec.max_ = (std::numeric_limits<unsigned int>::max)();
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '?'):
+ spec.min_ = 0;
+ spec.max_ = 1;
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '{'):
+ old_begin = this->eat_ws_(++begin, end);
+ spec.min_ = spec.max_ = detail::toi(begin, end, this->traits());
+ BOOST_XPR_ENSURE_
+ (
+ begin != old_begin && begin != end, error_brace, "invalid quantifier"
+ );
+
+ if(*begin == BOOST_XPR_CHAR_(char_type, ','))
+ {
+ old_begin = this->eat_ws_(++begin, end);
+ spec.max_ = detail::toi(begin, end, this->traits());
+ BOOST_XPR_ENSURE_
+ (
+ begin != end && BOOST_XPR_CHAR_(char_type, '}') == *begin
+ , error_brace, "invalid quantifier"
+ );
+
+ if(begin == old_begin)
+ {
+ spec.max_ = (std::numeric_limits<unsigned int>::max)();
+ }
+ else
+ {
+ BOOST_XPR_ENSURE_
+ (
+ spec.min_ <= spec.max_, error_badbrace, "invalid quantification range"
+ );
+ }
+ }
+ else
+ {
+ BOOST_XPR_ENSURE_
+ (
+ BOOST_XPR_CHAR_(char_type, '}') == *begin, error_brace, "invalid quantifier"
+ );
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ spec.greedy_ = true;
+ if(this->eat_ws_(++begin, end) != end && BOOST_XPR_CHAR_(char_type, '?') == *begin)
+ {
+ ++begin;
+ spec.greedy_ = false;
+ }
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_group_type
+ template<typename FwdIter>
+ regex_constants::compiler_token_type get_group_type(FwdIter &begin, FwdIter end, string_type &name)
+ {
+ using namespace regex_constants;
+ if(this->eat_ws_(begin, end) != end && BOOST_XPR_CHAR_(char_type, '?') == *begin)
+ {
+ this->eat_ws_(++begin, end);
+ BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
+
+ switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, ':'): ++begin; return token_no_mark;
+ case BOOST_XPR_CHAR_(char_type, '>'): ++begin; return token_independent_sub_expression;
+ case BOOST_XPR_CHAR_(char_type, '#'): ++begin; return token_comment;
+ case BOOST_XPR_CHAR_(char_type, '='): ++begin; return token_positive_lookahead;
+ case BOOST_XPR_CHAR_(char_type, '!'): ++begin; return token_negative_lookahead;
+ case BOOST_XPR_CHAR_(char_type, 'R'): ++begin; return token_recurse;
+ case BOOST_XPR_CHAR_(char_type, '$'):
+ this->get_name_(++begin, end, name);
+ BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
+ if(BOOST_XPR_CHAR_(char_type, '=') == *begin)
+ {
+ ++begin;
+ return token_rule_assign;
+ }
+ return token_rule_ref;
+
+ case BOOST_XPR_CHAR_(char_type, '<'):
+ this->eat_ws_(++begin, end);
+ BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
+ switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, '='): ++begin; return token_positive_lookbehind;
+ case BOOST_XPR_CHAR_(char_type, '!'): ++begin; return token_negative_lookbehind;
+ default:
+ BOOST_THROW_EXCEPTION(regex_error(error_badbrace, "unrecognized extension"));
+ }
+
+ case BOOST_XPR_CHAR_(char_type, 'P'):
+ this->eat_ws_(++begin, end);
+ BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
+ switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, '<'):
+ this->get_name_(++begin, end, name);
+ BOOST_XPR_ENSURE_(begin != end && BOOST_XPR_CHAR_(char_type, '>') == *begin++, error_paren, "incomplete extension");
+ return token_named_mark;
+ case BOOST_XPR_CHAR_(char_type, '='):
+ this->get_name_(++begin, end, name);
+ BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
+ return token_named_mark_ref;
+ default:
+ BOOST_THROW_EXCEPTION(regex_error(error_badbrace, "unrecognized extension"));
+ }
+
+ case BOOST_XPR_CHAR_(char_type, 'i'):
+ case BOOST_XPR_CHAR_(char_type, 'm'):
+ case BOOST_XPR_CHAR_(char_type, 's'):
+ case BOOST_XPR_CHAR_(char_type, 'x'):
+ case BOOST_XPR_CHAR_(char_type, '-'):
+ return this->parse_mods_(begin, end);
+
+ default:
+ BOOST_THROW_EXCEPTION(regex_error(error_badbrace, "unrecognized extension"));
+ }
+ }
+
+ return token_literal;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // get_charset_token
+ // NOTE: white-space is *never* ignored in a charset.
+ template<typename FwdIter>
+ regex_constants::compiler_token_type get_charset_token(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ BOOST_ASSERT(begin != end);
+ switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, '^'): ++begin; return token_charset_invert;
+ case BOOST_XPR_CHAR_(char_type, '-'): ++begin; return token_charset_hyphen;
+ case BOOST_XPR_CHAR_(char_type, ']'): ++begin; return token_charset_end;
+ case BOOST_XPR_CHAR_(char_type, '['):
+ {
+ FwdIter next = begin; ++next;
+ if(next != end)
+ {
+ BOOST_XPR_ENSURE_(
+ *next != BOOST_XPR_CHAR_(char_type, '=')
+ , error_collate
+ , "equivalence classes are not yet supported"
+ );
+
+ BOOST_XPR_ENSURE_(
+ *next != BOOST_XPR_CHAR_(char_type, '.')
+ , error_collate
+ , "collation sequences are not yet supported"
+ );
+
+ if(*next == BOOST_XPR_CHAR_(char_type, ':'))
+ {
+ begin = ++next;
+ return token_posix_charset_begin;
+ }
+ }
+ }
+ break;
+ case BOOST_XPR_CHAR_(char_type, ':'):
+ {
+ FwdIter next = begin; ++next;
+ if(next != end && *next == BOOST_XPR_CHAR_(char_type, ']'))
+ {
+ begin = ++next;
+ return token_posix_charset_end;
+ }
+ }
+ break;
+ case BOOST_XPR_CHAR_(char_type, '\\'):
+ if(++begin != end)
+ {
+ switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, 'b'): ++begin; return token_charset_backspace;
+ default:;
+ }
+ }
+ return token_escape;
+ default:;
+ }
+ return token_literal;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // get_escape_token
+ template<typename FwdIter>
+ regex_constants::compiler_token_type get_escape_token(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ if(begin != end)
+ {
+ switch(*begin)
+ {
+ //case BOOST_XPR_CHAR_(char_type, 'a'): ++begin; return token_escape_bell;
+ //case BOOST_XPR_CHAR_(char_type, 'c'): ++begin; return token_escape_control;
+ //case BOOST_XPR_CHAR_(char_type, 'e'): ++begin; return token_escape_escape;
+ //case BOOST_XPR_CHAR_(char_type, 'f'): ++begin; return token_escape_formfeed;
+ //case BOOST_XPR_CHAR_(char_type, 'n'): ++begin; return token_escape_newline;
+ //case BOOST_XPR_CHAR_(char_type, 't'): ++begin; return token_escape_horizontal_tab;
+ //case BOOST_XPR_CHAR_(char_type, 'v'): ++begin; return token_escape_vertical_tab;
+ case BOOST_XPR_CHAR_(char_type, 'A'): ++begin; return token_assert_begin_sequence;
+ case BOOST_XPR_CHAR_(char_type, 'b'): ++begin; return token_assert_word_boundary;
+ case BOOST_XPR_CHAR_(char_type, 'B'): ++begin; return token_assert_not_word_boundary;
+ case BOOST_XPR_CHAR_(char_type, 'E'): ++begin; return token_quote_meta_end;
+ case BOOST_XPR_CHAR_(char_type, 'Q'): ++begin; return token_quote_meta_begin;
+ case BOOST_XPR_CHAR_(char_type, 'Z'): ++begin; return token_assert_end_sequence;
+ // Non-standard extension to ECMAScript syntax
+ case BOOST_XPR_CHAR_(char_type, '<'): ++begin; return token_assert_word_begin;
+ case BOOST_XPR_CHAR_(char_type, '>'): ++begin; return token_assert_word_end;
+ default:; // fall-through
+ }
+ }
+
+ return token_escape;
+ }
+
+private:
+
+ //////////////////////////////////////////////////////////////////////////
+ // parse_mods_
+ template<typename FwdIter>
+ regex_constants::compiler_token_type parse_mods_(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ bool set = true;
+ do switch(*begin)
+ {
+ case BOOST_XPR_CHAR_(char_type, 'i'): this->flag_(set, icase_); break;
+ case BOOST_XPR_CHAR_(char_type, 'm'): this->flag_(!set, single_line); break;
+ case BOOST_XPR_CHAR_(char_type, 's'): this->flag_(!set, not_dot_newline); break;
+ case BOOST_XPR_CHAR_(char_type, 'x'): this->flag_(set, ignore_white_space); break;
+ case BOOST_XPR_CHAR_(char_type, ':'): ++begin; // fall-through
+ case BOOST_XPR_CHAR_(char_type, ')'): return token_no_mark;
+ case BOOST_XPR_CHAR_(char_type, '-'): if(false == (set = !set)) break; // else fall-through
+ default: BOOST_THROW_EXCEPTION(regex_error(error_paren, "unknown pattern modifier"));
+ }
+ while(BOOST_XPR_ENSURE_(++begin != end, error_paren, "incomplete extension"));
+ // this return is technically unreachable, but this must
+ // be here to work around a bug in gcc 4.0
+ return token_no_mark;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // flag_
+ void flag_(bool set, regex_constants::syntax_option_type flag)
+ {
+ this->flags_ = set ? (this->flags_ | flag) : (this->flags_ & ~flag);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // is_space_
+ bool is_space_(char_type ch) const
+ {
+ return 0 != this->space_ && this->traits().isctype(ch, this->space_);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // is_alnum_
+ bool is_alnum_(char_type ch) const
+ {
+ return 0 != this->alnum_ && this->traits().isctype(ch, this->alnum_);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_name_
+ template<typename FwdIter>
+ void get_name_(FwdIter &begin, FwdIter end, string_type &name)
+ {
+ this->eat_ws_(begin, end);
+ for(name.clear(); begin != end && this->is_alnum_(*begin); ++begin)
+ {
+ name.push_back(*begin);
+ }
+ this->eat_ws_(begin, end);
+ BOOST_XPR_ENSURE_(!name.empty(), regex_constants::error_paren, "incomplete extension");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // eat_ws_
+ template<typename FwdIter>
+ FwdIter &eat_ws_(FwdIter &begin, FwdIter end)
+ {
+ if(0 != (regex_constants::ignore_white_space & this->flags()))
+ {
+ while(end != begin && (BOOST_XPR_CHAR_(char_type, '#') == *begin || this->is_space_(*begin)))
+ {
+ if(BOOST_XPR_CHAR_(char_type, '#') == *begin++)
+ {
+ while(end != begin && BOOST_XPR_CHAR_(char_type, '\n') != *begin++) {}
+ }
+ else
+ {
+ for(; end != begin && this->is_space_(*begin); ++begin) {}
+ }
+ }
+ }
+
+ return begin;
+ }
+
+ regex_traits traits_;
+ regex_constants::syntax_option_type flags_;
+ typename regex_traits::char_class_type space_;
+ typename regex_traits::char_class_type alnum_;
+};
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/detail/dynamic/sequence.hpp b/boost/xpressive/detail/dynamic/sequence.hpp
new file mode 100644
index 0000000000..f1670f683b
--- /dev/null
+++ b/boost/xpressive/detail/dynamic/sequence.hpp
@@ -0,0 +1,175 @@
+///////////////////////////////////////////////////////////////////////////////
+// sequence.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_SEQUENCE_HPP_EAN_04_10_2006
+#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_SEQUENCE_HPP_EAN_04_10_2006
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/xpressive/detail/utility/width.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// sequence
+template<typename BidiIter>
+struct sequence
+{
+ sequence()
+ : pure_(true)
+ , width_(0)
+ , quant_(quant_none)
+ , head_()
+ , tail_(0)
+ , alt_end_xpr_()
+ , alternates_(0)
+ {
+ }
+
+ template<typename Matcher>
+ sequence(intrusive_ptr<dynamic_xpression<Matcher, BidiIter> > const &xpr)
+ : pure_(Matcher::pure)
+ , width_(xpr->Matcher::get_width())
+ , quant_(static_cast<quant_enum>(Matcher::quant))
+ , head_(xpr)
+ , tail_(&xpr->next_)
+ , alt_end_xpr_()
+ , alternates_(0)
+ {
+ }
+
+ template<typename Traits>
+ sequence(intrusive_ptr<dynamic_xpression<alternate_matcher<alternates_vector<BidiIter>, Traits>, BidiIter> > const &xpr)
+ : pure_(true)
+ , width_(0)
+ , quant_(quant_none)
+ , head_(xpr)
+ , tail_(&xpr->next_)
+ , alt_end_xpr_()
+ , alternates_(&xpr->alternates_)
+ {
+ }
+
+ bool empty() const
+ {
+ return !this->head_;
+ }
+
+ sequence<BidiIter> &operator +=(sequence<BidiIter> const &that)
+ {
+ if(this->empty())
+ {
+ *this = that;
+ }
+ else if(!that.empty())
+ {
+ *this->tail_ = that.head_;
+ this->tail_ = that.tail_;
+ // keep track of sequence width and purity
+ this->width_ += that.width_;
+ this->pure_ = this->pure_ && that.pure_;
+ this->set_quant_();
+ }
+ return *this;
+ }
+
+ sequence<BidiIter> &operator |=(sequence<BidiIter> that)
+ {
+ BOOST_ASSERT(!this->empty());
+ BOOST_ASSERT(0 != this->alternates_);
+
+ // Keep track of width and purity
+ if(this->alternates_->empty())
+ {
+ this->width_ = that.width_;
+ this->pure_ = that.pure_;
+ }
+ else
+ {
+ this->width_ |= that.width_;
+ this->pure_ = this->pure_ && that.pure_;
+ }
+
+ // through the wonders of reference counting, all alternates_ can share an end_alternate
+ if(!this->alt_end_xpr_)
+ {
+ this->alt_end_xpr_ = new alt_end_xpr_type;
+ }
+
+ // terminate each alternate with an alternate_end_matcher
+ that += sequence(this->alt_end_xpr_);
+ this->alternates_->push_back(that.head_);
+ this->set_quant_();
+ return *this;
+ }
+
+ void repeat(quant_spec const &spec)
+ {
+ this->xpr().matchable()->repeat(spec, *this);
+ }
+
+ shared_matchable<BidiIter> const &xpr() const
+ {
+ return this->head_;
+ }
+
+ detail::width width() const
+ {
+ return this->width_;
+ }
+
+ bool pure() const
+ {
+ return this->pure_;
+ }
+
+ quant_enum quant() const
+ {
+ return this->quant_;
+ }
+
+private:
+ typedef dynamic_xpression<alternate_end_matcher, BidiIter> alt_end_xpr_type;
+
+ void set_quant_()
+ {
+ this->quant_ = (!is_unknown(this->width_) && this->pure_)
+ ? (!this->width_ ? quant_none : quant_fixed_width)
+ : quant_variable_width;
+ }
+
+ bool pure_;
+ detail::width width_;
+ quant_enum quant_;
+ shared_matchable<BidiIter> head_;
+ shared_matchable<BidiIter> *tail_;
+ intrusive_ptr<alt_end_xpr_type> alt_end_xpr_;
+ alternates_vector<BidiIter> *alternates_;
+};
+
+template<typename BidiIter>
+inline sequence<BidiIter> operator +(sequence<BidiIter> left, sequence<BidiIter> const &right)
+{
+ return left += right;
+}
+
+template<typename BidiIter>
+inline sequence<BidiIter> operator |(sequence<BidiIter> left, sequence<BidiIter> const &right)
+{
+ return left |= right;
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/static/compile.hpp b/boost/xpressive/detail/static/compile.hpp
new file mode 100644
index 0000000000..bc8af05bf4
--- /dev/null
+++ b/boost/xpressive/detail/static/compile.hpp
@@ -0,0 +1,104 @@
+///////////////////////////////////////////////////////////////////////////////
+// compile.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_COMPILE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_COMPILE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/xpressive/regex_traits.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/core/linker.hpp>
+#include <boost/xpressive/detail/core/optimize.hpp>
+#include <boost/xpressive/detail/core/adaptor.hpp>
+#include <boost/xpressive/detail/core/matcher/end_matcher.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/xpressive/detail/static/visitor.hpp>
+#include <boost/xpressive/detail/static/grammar.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // static_compile_impl2
+ template<typename Xpr, typename BidiIter, typename Traits>
+ void static_compile_impl2(Xpr const &xpr, shared_ptr<regex_impl<BidiIter> > const &impl, Traits const &tr)
+ {
+ typedef typename iterator_value<BidiIter>::type char_type;
+ impl->tracking_clear();
+ impl->traits_ = new traits_holder<Traits>(tr);
+
+ // "compile" the regex and wrap it in an xpression_adaptor.
+ typedef xpression_visitor<BidiIter, mpl::false_, Traits> visitor_type;
+ visitor_type visitor(tr, impl);
+ intrusive_ptr<matchable_ex<BidiIter> const> adxpr = make_adaptor<matchable_ex<BidiIter> >(
+ typename Grammar<char_type>::template impl<Xpr const &, end_xpression, visitor_type &>()(
+ xpr
+ , end_xpression()
+ , visitor
+ )
+ );
+
+ // Link and optimize the regex
+ common_compile(adxpr, *impl, visitor.traits());
+
+ // References changed, update dependencies.
+ impl->tracking_update();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // pattern for imbued regexes.
+ struct XpressiveLocaleModifier
+ : proto::binary_expr<
+ modifier_tag
+ , proto::terminal<locale_modifier<proto::_> >
+ , proto::_
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // static_compile_impl1
+ template<typename Xpr, typename BidiIter>
+ typename disable_if<proto::matches<Xpr, XpressiveLocaleModifier> >::type
+ static_compile_impl1(Xpr const &xpr, shared_ptr<regex_impl<BidiIter> > const &impl)
+ {
+ // use default traits
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef typename default_regex_traits<char_type>::type traits_type;
+ traits_type tr;
+ static_compile_impl2(xpr, impl, tr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // static_compile_impl1
+ template<typename Xpr, typename BidiIter>
+ typename enable_if<proto::matches<Xpr, XpressiveLocaleModifier> >::type
+ static_compile_impl1(Xpr const &xpr, shared_ptr<regex_impl<BidiIter> > const &impl)
+ {
+ // use specified traits
+ typedef typename proto::result_of::value<typename proto::result_of::left<Xpr>::type>::type::locale_type locale_type;
+ typedef typename regex_traits_type<locale_type, BidiIter>::type traits_type;
+ static_compile_impl2(proto::right(xpr), impl, traits_type(proto::value(proto::left(xpr)).getloc()));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // static_compile
+ template<typename Xpr, typename BidiIter>
+ void static_compile(Xpr const &xpr, shared_ptr<regex_impl<BidiIter> > const &impl)
+ {
+ static_compile_impl1(xpr, impl);
+ }
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/static/grammar.hpp b/boost/xpressive/detail/static/grammar.hpp
new file mode 100644
index 0000000000..82d1adc3c7
--- /dev/null
+++ b/boost/xpressive/detail/static/grammar.hpp
@@ -0,0 +1,365 @@
+///////////////////////////////////////////////////////////////////////////////
+// grammar.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_GRAMMAR_HPP_EAN_11_12_2006
+#define BOOST_XPRESSIVE_DETAIL_STATIC_GRAMMAR_HPP_EAN_11_12_2006
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/xpressive/detail/static/is_pure.hpp>
+#include <boost/xpressive/detail/static/transforms/as_matcher.hpp>
+#include <boost/xpressive/detail/static/transforms/as_alternate.hpp>
+#include <boost/xpressive/detail/static/transforms/as_sequence.hpp>
+#include <boost/xpressive/detail/static/transforms/as_quantifier.hpp>
+#include <boost/xpressive/detail/static/transforms/as_marker.hpp>
+#include <boost/xpressive/detail/static/transforms/as_set.hpp>
+#include <boost/xpressive/detail/static/transforms/as_independent.hpp>
+#include <boost/xpressive/detail/static/transforms/as_modifier.hpp>
+#include <boost/xpressive/detail/static/transforms/as_inverse.hpp>
+#include <boost/xpressive/detail/static/transforms/as_action.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+#define BOOST_XPRESSIVE_CHECK_REGEX(Expr, Char)\
+ BOOST_MPL_ASSERT\
+ ((\
+ typename boost::mpl::if_c<\
+ boost::xpressive::is_valid_regex<Expr, Char>::value\
+ , boost::mpl::true_\
+ , boost::xpressive::INVALID_REGULAR_EXPRESSION\
+ >::type\
+ ));
+
+//////////////////////////////////////////////////////////////////////////
+//**********************************************************************//
+//* << NOTE! >> *//
+//* *//
+//* Whenever you change this grammar, you MUST also make corresponding *//
+//* changes to width_of.hpp and is_pure.hpp. *//
+//* *//
+//**********************************************************************//
+//////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace xpressive
+{
+ template<typename Char>
+ struct Grammar;
+
+ template<typename Char>
+ struct ActionableGrammar;
+
+ namespace grammar_detail
+ {
+ ///////////////////////////////////////////////////////////////////////////
+ // CharLiteral
+ template<typename Char>
+ struct CharLiteral;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ListSet
+ template<typename Char>
+ struct ListSet;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // as_repeat
+ template<typename Char, typename Gram, typename Greedy>
+ struct as_repeat
+ : if_<
+ make<detail::use_simple_repeat<_child, Char> >
+ , as_simple_quantifier<Gram, Greedy>
+ , as_default_quantifier<Greedy>
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // NonGreedyRepeatCases
+ template<typename Gram>
+ struct NonGreedyRepeatCases
+ {
+ template<typename Tag, typename Dummy = void>
+ struct case_
+ : not_<_>
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::dereference, Dummy>
+ : dereference<Gram>
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::unary_plus, Dummy>
+ : unary_plus<Gram>
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::logical_not, Dummy>
+ : logical_not<Gram>
+ {};
+
+ template<uint_t Min, uint_t Max, typename Dummy>
+ struct case_<detail::generic_quant_tag<Min, Max>, Dummy>
+ : unary_expr<detail::generic_quant_tag<Min, Max>, Gram>
+ {};
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // InvertibleCases
+ template<typename Char, typename Gram>
+ struct InvertibleCases
+ {
+ template<typename Tag, typename Dummy = void>
+ struct case_
+ : not_<_>
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::comma, Dummy>
+ : when<ListSet<Char>, as_list_set_matcher<Char> >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::assign, Dummy>
+ : when<ListSet<Char>, as_list_set_matcher<Char> >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::subscript, Dummy>
+ : when<subscript<detail::set_initializer_type, Gram>, call<as_set_matcher<Gram>(_right)> >
+ {};
+
+ template<typename Dummy>
+ struct case_<detail::lookahead_tag, Dummy>
+ : when<
+ unary_expr<detail::lookahead_tag, Gram>
+ , as_lookahead<Gram>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<detail::lookbehind_tag, Dummy>
+ : when<
+ unary_expr<detail::lookbehind_tag, Gram>
+ , as_lookbehind<Gram>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::terminal, Dummy>
+ : when<
+ or_<
+ CharLiteral<Char>
+ , terminal<detail::posix_charset_placeholder>
+ , terminal<detail::range_placeholder<_> >
+ , terminal<detail::logical_newline_placeholder>
+ , terminal<detail::assert_word_placeholder<detail::word_boundary<mpl::true_> > >
+ >
+ , as_matcher
+ >
+ {};
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Cases
+ template<typename Char, typename Gram>
+ struct Cases
+ {
+ template<typename Tag, typename Dummy = void>
+ struct case_
+ : not_<_>
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::terminal, Dummy>
+ : when<
+ _
+ , in_sequence<as_matcher>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::shift_right, Dummy>
+ : when<
+ shift_right<Gram, Gram>
+ , reverse_fold<_, _state, Gram>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::bitwise_or, Dummy>
+ : when<
+ bitwise_or<Gram, Gram>
+ , in_sequence<
+ as_alternate_matcher<
+ reverse_fold_tree<_, make<fusion::nil>, in_alternate_list<Gram> >
+ >
+ >
+ >
+ {};
+
+ template<typename Dummy, typename Greedy>
+ struct case_<optional_tag<Greedy> , Dummy>
+ : when<
+ unary_expr<optional_tag<Greedy>, Gram>
+ , in_sequence<call<as_optional<Gram, Greedy>(_child)> >
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::dereference, Dummy>
+ : when<
+ dereference<Gram>
+ , call<Gram(as_repeat<Char, Gram, mpl::true_>)>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::unary_plus, Dummy>
+ : when<
+ unary_plus<Gram>
+ , call<Gram(as_repeat<Char, Gram, mpl::true_>)>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::logical_not, Dummy>
+ : when<
+ logical_not<Gram>
+ , call<Gram(as_repeat<Char, Gram, mpl::true_>)>
+ >
+ {};
+
+ template<uint_t Min, uint_t Max, typename Dummy>
+ struct case_<detail::generic_quant_tag<Min, Max>, Dummy>
+ : when<
+ unary_expr<detail::generic_quant_tag<Min, Max>, Gram>
+ , call<Gram(as_repeat<Char, Gram, mpl::true_>)>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::negate, Dummy>
+ : when<
+ negate<switch_<NonGreedyRepeatCases<Gram> > >
+ , call<Gram(call<as_repeat<Char, Gram, mpl::false_>(_child)>)>
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::complement, Dummy>
+ : when<
+ complement<switch_<InvertibleCases<Char, Gram> > >
+ , in_sequence<call<as_inverse(call<switch_<InvertibleCases<Char, Gram> >(_child)>)> >
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<detail::modifier_tag, Dummy>
+ : when<binary_expr<detail::modifier_tag, _, Gram>, as_modifier<Gram> >
+ {};
+
+ template<typename Dummy>
+ struct case_<detail::lookahead_tag, Dummy>
+ : when<
+ unary_expr<detail::lookahead_tag, Gram>
+ , in_sequence<as_lookahead<Gram> >
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<detail::lookbehind_tag, Dummy>
+ : when<
+ unary_expr<detail::lookbehind_tag, Gram>
+ , in_sequence<as_lookbehind<Gram> >
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<detail::keeper_tag, Dummy>
+ : when<
+ unary_expr<detail::keeper_tag, Gram>
+ , in_sequence<as_keeper<Gram> >
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::comma, Dummy>
+ : when<ListSet<Char>, in_sequence<as_list_set_matcher<Char> > >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::assign, Dummy>
+ : or_<
+ when<assign<detail::basic_mark_tag, Gram>, call<Gram(as_marker)> >
+ , when<ListSet<Char>, in_sequence<as_list_set_matcher<Char> > >
+ >
+ {};
+
+ template<typename Dummy>
+ struct case_<tag::subscript, Dummy>
+ : or_<
+ when<subscript<detail::set_initializer_type, Gram>, in_sequence<call<as_set_matcher<Gram>(_right)> > >
+ , when<subscript<ActionableGrammar<Char>, _>, call<ActionableGrammar<Char>(as_action)> >
+ >
+ {};
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ActionableCases
+ template<typename Char, typename Gram>
+ struct ActionableCases
+ {
+ template<typename Tag, typename Dummy = void>
+ struct case_
+ : Cases<Char, Gram>::template case_<Tag>
+ {};
+
+ // Only in sub-expressions with actions attached do we allow attribute assignements
+ template<typename Dummy>
+ struct case_<proto::tag::assign, Dummy>
+ : or_<
+ typename Cases<Char, Gram>::template case_<proto::tag::assign>
+ , when<proto::assign<terminal<detail::attribute_placeholder<_> >, _>, in_sequence<as_attr_matcher> >
+ >
+ {};
+ };
+
+ } // namespace detail
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Grammar
+ template<typename Char>
+ struct Grammar
+ : proto::switch_<grammar_detail::Cases<Char, Grammar<Char> > >
+ {};
+
+ template<typename Char>
+ struct ActionableGrammar
+ : proto::switch_<grammar_detail::ActionableCases<Char, ActionableGrammar<Char> > >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // INVALID_REGULAR_EXPRESSION
+ struct INVALID_REGULAR_EXPRESSION
+ : mpl::false_
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // is_valid_regex
+ template<typename Expr, typename Char>
+ struct is_valid_regex
+ : proto::matches<Expr, Grammar<Char> >
+ {};
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/detail/static/is_pure.hpp b/boost/xpressive/detail/static/is_pure.hpp
new file mode 100644
index 0000000000..f7da4f04bb
--- /dev/null
+++ b/boost/xpressive/detail/static/is_pure.hpp
@@ -0,0 +1,216 @@
+///////////////////////////////////////////////////////////////////////////////
+// is_pure.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_IS_PURE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_IS_PURE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/ref.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/not_equal_to.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/width_of.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // use_simple_repeat_terminal
+ //
+ template<typename Expr, typename Char, bool IsXpr = is_xpr<Expr>::value>
+ struct use_simple_repeat_terminal
+ : mpl::bool_<
+ Expr::quant == quant_fixed_width
+ || (Expr::width != unknown_width::value && Expr::pure)
+ >
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_terminal<Expr, Char, false>
+ : mpl::true_ // char literals, string literals, etc.
+ {};
+
+ template<typename BidiIter, typename Char>
+ struct use_simple_repeat_terminal<tracking_ptr<regex_impl<BidiIter> >, Char, false>
+ : mpl::false_ // basic_regex
+ {};
+
+ template<typename BidiIter, typename Char>
+ struct use_simple_repeat_terminal<reference_wrapper<basic_regex<BidiIter> >, Char, false>
+ : mpl::false_ // basic_regex
+ {};
+
+ template<typename BidiIter, typename Char>
+ struct use_simple_repeat_terminal<reference_wrapper<basic_regex<BidiIter> const>, Char, false>
+ : mpl::false_ // basic_regex
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // use_simple_repeat_
+ //
+ template<typename Expr, typename Char, typename Tag = typename Expr::proto_tag>
+ struct use_simple_repeat_
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::terminal>
+ : use_simple_repeat_terminal<typename proto::result_of::value<Expr>::type, Char>
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::shift_right>
+ : mpl::and_<
+ use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ , use_simple_repeat_<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
+ >
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::bitwise_or>
+ : mpl::and_<
+ mpl::not_equal_to<unknown_width, width_of<Expr, Char> >
+ , use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ , use_simple_repeat_<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
+ >
+ {};
+
+ template<typename Left>
+ struct use_simple_repeat_assign
+ {};
+
+ template<>
+ struct use_simple_repeat_assign<mark_placeholder>
+ : mpl::false_
+ {};
+
+ template<>
+ struct use_simple_repeat_assign<set_initializer>
+ : mpl::true_
+ {};
+
+ template<typename Nbr>
+ struct use_simple_repeat_assign<attribute_placeholder<Nbr> >
+ : mpl::false_
+ {};
+
+ // either (s1 = ...) or (a1 = ...) or (set = ...)
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::assign>
+ : use_simple_repeat_assign<
+ typename proto::result_of::value<
+ typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr
+ >::type
+ >
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, modifier_tag>
+ : use_simple_repeat_<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, lookahead_tag>
+ : mpl::false_
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, lookbehind_tag>
+ : mpl::false_
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, keeper_tag>
+ : mpl::false_
+ {};
+
+ // when complementing a set or an assertion, the purity is that of the set (true) or the assertion
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::complement>
+ : use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ {};
+
+ // The comma is used in list-initialized sets, which are pure
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::comma>
+ : mpl::true_
+ {};
+
+ // The subscript operator[] is used for sets, as in set['a' | range('b','h')]
+ // It is also used for actions, which by definition have side-effects and thus are impure
+ template<typename Expr, typename Char, typename Left>
+ struct use_simple_repeat_subscript
+ : mpl::false_
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_subscript<Expr, Char, set_initializer_type>
+ : mpl::true_
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::subscript>
+ : use_simple_repeat_subscript<Expr, Char, typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr>
+ {};
+
+ // Quantified expressions are variable-width and cannot use the simple quantifier
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::unary_plus>
+ : mpl::false_
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::dereference>
+ : mpl::false_
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::logical_not>
+ : mpl::false_
+ {};
+
+ template<typename Expr, typename Char, uint_t Min, uint_t Max>
+ struct use_simple_repeat_<Expr, Char, generic_quant_tag<Min, Max> >
+ : mpl::false_
+ {};
+
+ template<typename Expr, typename Char, uint_t Count>
+ struct use_simple_repeat_<Expr, Char, generic_quant_tag<Count, Count> >
+ : use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ {};
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat_<Expr, Char, proto::tag::negate>
+ : use_simple_repeat_<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // use_simple_repeat
+ //
+ template<typename Expr, typename Char>
+ struct use_simple_repeat
+ : use_simple_repeat_<Expr, Char>
+ {
+ // should never try to repeat something of 0-width
+ BOOST_MPL_ASSERT_RELATION(0, !=, (width_of<Expr, Char>::value));
+ };
+
+ template<typename Expr, typename Char>
+ struct use_simple_repeat<Expr &, Char>
+ : use_simple_repeat_<Expr, Char>
+ {
+ // should never try to repeat something of 0-width
+ BOOST_MPL_ASSERT_RELATION(0, !=, (width_of<Expr, Char>::value));
+ };
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/static/modifier.hpp b/boost/xpressive/detail/static/modifier.hpp
new file mode 100644
index 0000000000..82e4a76faf
--- /dev/null
+++ b/boost/xpressive/detail/static/modifier.hpp
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////////
+// modifier.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_MODIFIER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_MODIFIER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4510) // default constructor could not be generated
+# pragma warning(disable : 4610) // user defined constructor required
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/proto/traits.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // modifier
+ template<typename Modifier>
+ struct modifier_op
+ {
+ typedef regex_constants::syntax_option_type opt_type;
+
+ template<typename Expr>
+ struct apply
+ {
+ typedef typename proto::binary_expr<
+ modifier_tag
+ , typename proto::terminal<Modifier>::type
+ , typename proto::result_of::as_child<Expr const>::type
+ >::type type;
+ };
+
+ template<typename Expr>
+ typename apply<Expr>::type const
+ operator ()(Expr const &expr) const
+ {
+ typename apply<Expr>::type that = {{this->mod_}, proto::as_child(expr)};
+ return that;
+ }
+
+ operator opt_type() const
+ {
+ return this->opt_;
+ }
+
+ Modifier mod_;
+ opt_type opt_;
+ };
+
+}}}
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/static/placeholders.hpp b/boost/xpressive/detail/static/placeholders.hpp
new file mode 100644
index 0000000000..5c95538430
--- /dev/null
+++ b/boost/xpressive/detail/static/placeholders.hpp
@@ -0,0 +1,120 @@
+///////////////////////////////////////////////////////////////////////////////
+// placeholders.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_PLACEHOLDERS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_PLACEHOLDERS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable:4510) // default constructor could not be generated
+# pragma warning(disable:4610) // can never be instantiated - user defined constructor required
+#endif
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include <boost/xpressive/detail/core/quant_style.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// mark_placeholder
+//
+struct mark_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_variable_width, unknown_width::value, true)
+
+ int mark_number_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// posix_charset_placeholder
+//
+struct posix_charset_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_fixed_width, 1, true)
+
+ char const *name_;
+ bool not_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// assert_word_placeholder
+//
+template<typename Cond>
+struct assert_word_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// range_placeholder
+//
+template<typename Char>
+struct range_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_fixed_width, 1, true)
+
+ Char ch_min_;
+ Char ch_max_;
+ bool not_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// assert_bol_placeholder
+//
+struct assert_bol_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// assert_eol_placeholder
+//
+struct assert_eol_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// logical_newline_placeholder
+//
+struct logical_newline_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_variable_width, unknown_width::value, true)
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// self_placeholder
+//
+struct self_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_variable_width, unknown_width::value, false)
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// attribute_placeholder
+//
+template<typename Nbr>
+struct attribute_placeholder
+{
+ BOOST_XPR_QUANT_STYLE(quant_variable_width, unknown_width::value, false)
+
+ typedef Nbr nbr_type;
+ static Nbr nbr() { return Nbr(); }
+};
+
+}}} // namespace boost::xpressive::detail
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/static/static.hpp b/boost/xpressive/detail/static/static.hpp
new file mode 100644
index 0000000000..ed51b517aa
--- /dev/null
+++ b/boost/xpressive/detail/static/static.hpp
@@ -0,0 +1,259 @@
+///////////////////////////////////////////////////////////////////////////////
+// static.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_STATIC_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_STATIC_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/core/linker.hpp>
+#include <boost/xpressive/detail/core/peeker.hpp>
+#include <boost/xpressive/detail/static/placeholders.hpp>
+#include <boost/xpressive/detail/utility/width.hpp>
+
+// Random thoughts:
+// - must support indirect repeat counts {$n,$m}
+// - add ws to eat whitespace (make *ws illegal)
+// - a{n,m} -> repeat<n,m>(a)
+// - a{$n,$m} -> repeat(n,m)(a)
+// - add nil to match nothing
+// - instead of s1, s2, etc., how about s[1], s[2], etc.? Needlessly verbose?
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// stacked_xpression
+//
+template<typename Top, typename Next>
+struct stacked_xpression
+ : Next
+{
+ // match
+ // delegates to Next
+ template<typename BidiIter>
+ bool match(match_state<BidiIter> &state) const
+ {
+ return static_cast<Next const *>(this)->
+ BOOST_NESTED_TEMPLATE push_match<Top>(state);
+ }
+
+ // top_match
+ // jump back to the xpression on top of the xpression stack,
+ // and keep the xpression on the stack.
+ template<typename BidiIter>
+ static bool top_match(match_state<BidiIter> &state, void const *top)
+ {
+ return static_cast<Top const *>(top)->
+ BOOST_NESTED_TEMPLATE push_match<Top>(state);
+ }
+
+ // pop_match
+ // jump back to the xpression on top of the xpression stack,
+ // pop the xpression off the stack.
+ template<typename BidiIter>
+ static bool pop_match(match_state<BidiIter> &state, void const *top)
+ {
+ return static_cast<Top const *>(top)->match(state);
+ }
+
+ // skip_match
+ // pop the xpression off the top of the stack and ignore it; call
+ // match on next.
+ template<typename BidiIter>
+ bool skip_match(match_state<BidiIter> &state) const
+ {
+ // could be static_xpression::skip_impl or stacked_xpression::skip_impl
+ // depending on if there is 1 or more than 1 xpression on the
+ // xpression stack
+ return Top::skip_impl(*static_cast<Next const *>(this), state);
+ }
+
+//protected:
+
+ // skip_impl
+ // implementation of skip_match.
+ template<typename That, typename BidiIter>
+ static bool skip_impl(That const &that, match_state<BidiIter> &state)
+ {
+ return that.BOOST_NESTED_TEMPLATE push_match<Top>(state);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// stacked_xpression_cast
+//
+template<typename Top, typename Next>
+inline stacked_xpression<Top, Next> const &stacked_xpression_cast(Next const &next)
+{
+ // NOTE: this is a little white lie. The "next" object doesn't really have
+ // the type to which we're casting it. It is harmless, though. We are only using
+ // the cast to decorate the next object with type information. It is done
+ // this way to save stack space.
+ BOOST_MPL_ASSERT_RELATION(sizeof(stacked_xpression<Top, Next>), ==, sizeof(Next));
+ return *static_cast<stacked_xpression<Top, Next> const *>(&next);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static_xpression
+//
+template<typename Matcher, typename Next>
+struct static_xpression
+ : Matcher
+{
+ Next next_;
+
+ BOOST_STATIC_CONSTANT(bool, pure = Matcher::pure && Next::pure);
+ BOOST_STATIC_CONSTANT(
+ std::size_t
+ , width =
+ Matcher::width != unknown_width::value && Next::width != unknown_width::value
+ ? Matcher::width + Next::width
+ : unknown_width::value
+ );
+
+ static_xpression(Matcher const &matcher = Matcher(), Next const &next = Next())
+ : Matcher(matcher)
+ , next_(next)
+ {
+ }
+
+ // match
+ // delegates to the Matcher
+ template<typename BidiIter>
+ bool match(match_state<BidiIter> &state) const
+ {
+ return this->Matcher::match(state, this->next_);
+ }
+
+ // push_match
+ // call match on this, but also push "Top" onto the xpression
+ // stack so we know what we are jumping back to later.
+ template<typename Top, typename BidiIter>
+ bool push_match(match_state<BidiIter> &state) const
+ {
+ return this->Matcher::match(state, stacked_xpression_cast<Top>(this->next_));
+ }
+
+ // skip_impl
+ // implementation of skip_match, called from stacked_xpression::skip_match
+ template<typename That, typename BidiIter>
+ static bool skip_impl(That const &that, match_state<BidiIter> &state)
+ {
+ return that.match(state);
+ }
+
+ // for linking a compiled regular xpression
+ template<typename Char>
+ void link(xpression_linker<Char> &linker) const
+ {
+ linker.accept(*static_cast<Matcher const *>(this), &this->next_);
+ this->next_.link(linker);
+ }
+
+ // for building a lead-follow
+ template<typename Char>
+ void peek(xpression_peeker<Char> &peeker) const
+ {
+ this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker);
+ }
+
+ // for getting xpression width
+ detail::width get_width() const
+ {
+ return this->get_width_(mpl::size_t<width>());
+ }
+
+private:
+
+ static_xpression &operator =(static_xpression const &);
+
+ template<typename Char>
+ void peek_next_(mpl::true_, xpression_peeker<Char> &peeker) const
+ {
+ this->next_.peek(peeker);
+ }
+
+ template<typename Char>
+ void peek_next_(mpl::false_, xpression_peeker<Char> &) const
+ {
+ // no-op
+ }
+
+ template<std::size_t Width>
+ detail::width get_width_(mpl::size_t<Width>) const
+ {
+ return Width;
+ }
+
+ detail::width get_width_(unknown_width) const
+ {
+ // Should only be called in contexts where the width is
+ // known to be fixed.
+ return this->Matcher::get_width() + this->next_.get_width();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// make_static
+//
+template<typename Matcher>
+inline static_xpression<Matcher> const
+make_static(Matcher const &matcher)
+{
+ return static_xpression<Matcher>(matcher);
+}
+
+template<typename Matcher, typename Next>
+inline static_xpression<Matcher, Next> const
+make_static(Matcher const &matcher, Next const &next)
+{
+ return static_xpression<Matcher, Next>(matcher, next);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// no_next
+//
+struct no_next
+{
+ BOOST_STATIC_CONSTANT(std::size_t, width = 0);
+ BOOST_STATIC_CONSTANT(bool, pure = true);
+
+ template<typename Char>
+ void link(xpression_linker<Char> &) const
+ {
+ }
+
+ template<typename Char>
+ void peek(xpression_peeker<Char> &peeker) const
+ {
+ peeker.fail();
+ }
+
+ detail::width get_width() const
+ {
+ return 0;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// get_mark_number
+//
+inline int get_mark_number(basic_mark_tag const &mark)
+{
+ return proto::value(mark).mark_number_;
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_action.hpp b/boost/xpressive/detail/static/transforms/as_action.hpp
new file mode 100644
index 0000000000..4cda17bc23
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_action.hpp
@@ -0,0 +1,322 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_action.hpp
+//
+// Copyright 2008 Eric Niebler.
+// Copyright 2008 David Jenkins.
+//
+// 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_ACTION_HPP_EAN_04_05_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_ACTION_HPP_EAN_04_05_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/sizeof.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/matcher/attr_end_matcher.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/xpressive/detail/static/transforms/as_quantifier.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform/arg.hpp>
+#include <boost/proto/transform/call.hpp>
+#include <boost/proto/transform/make.hpp>
+#include <boost/proto/transform/when.hpp>
+#include <boost/proto/transform/fold.hpp>
+#include <boost/proto/transform/fold_tree.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // read_attr
+ // Placeholder that knows the slot number of an attribute as well as the type
+ // of the object stored in it.
+ template<typename Nbr, typename Matcher>
+ struct read_attr
+ {
+ typedef Nbr nbr_type;
+ typedef Matcher matcher_type;
+ static Nbr nbr() { return Nbr(); }
+ };
+
+ template<typename Nbr, typename Matcher>
+ struct read_attr<Nbr, Matcher &>
+ {
+ typedef Nbr nbr_type;
+ typedef Matcher matcher_type;
+ };
+
+}}}
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // FindAttr
+ // Look for patterns like (a1= terminal<RHS>) and return the type of the RHS.
+ template<typename Nbr>
+ struct FindAttr
+ : or_<
+ // Ignore nested actions, because attributes are scoped
+ when< subscript<_, _>, _state >
+ , when< terminal<_>, _state >
+ , when< proto::assign<terminal<detail::attribute_placeholder<Nbr> >, _>, call<_value(_right)> >
+ , otherwise< fold<_, _state, FindAttr<Nbr> > >
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_read_attr
+ // For patterns like (a1 = RHS)[ref(i) = a1], transform to
+ // (a1 = RHS)[ref(i) = read_attr<1, RHS>] so that when reading the attribute
+ // we know what type is stored in the attribute slot.
+ struct as_read_attr : proto::transform<as_read_attr>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::expr expr_type;
+ typedef
+ typename FindAttr<typename expr_type::proto_child0::nbr_type>::template impl<
+ State
+ , mpl::void_
+ , int
+ >::result_type
+ attr_type;
+
+ typedef
+ typename proto::terminal<
+ detail::read_attr<
+ typename expr_type::proto_child0::nbr_type
+ , BOOST_PROTO_UNCVREF(attr_type)
+ >
+ >::type
+ result_type;
+
+ result_type operator ()(proto::ignore, proto::ignore, proto::ignore) const
+ {
+ result_type that = {{}};
+ return that;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // DeepCopy
+ // Turn all refs into values, and also bind all attribute placeholders with
+ // the types from which they are being assigned.
+ struct DeepCopy
+ : or_<
+ when< terminal<detail::attribute_placeholder<_> >, as_read_attr>
+ , when< terminal<_>, proto::_deep_copy>
+ , otherwise< nary_expr<_, vararg<DeepCopy> > >
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // attr_nbr
+ // For an attribute placeholder, return the attribute's slot number.
+ struct attr_nbr : proto::transform<attr_nbr>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::expr expr_type;
+ typedef typename expr_type::proto_child0::nbr_type::type result_type;
+ };
+ };
+
+ struct max_attr;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // MaxAttr
+ // In an action (rx)[act], find the largest attribute slot being used.
+ struct MaxAttr
+ : or_<
+ when< terminal<detail::attribute_placeholder<_> >, attr_nbr>
+ , when< terminal<_>, make<mpl::int_<0> > >
+ // Ignore nested actions, because attributes are scoped:
+ , when< subscript<_, _>, make<mpl::int_<0> > >
+ , otherwise< fold<_, make<mpl::int_<0> >, max_attr> >
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // max_attr
+ // Take the maximum of the current attr slot number and the state.
+ struct max_attr : proto::transform<max_attr>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename mpl::max<
+ typename impl::state
+ , typename MaxAttr::template impl<Expr, State, Data>::result_type
+ >::type
+ result_type;
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_attr_matcher
+ // turn a1=matcher into attr_matcher<Matcher>(1)
+ struct as_attr_matcher : proto::transform<as_attr_matcher>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::expr expr_type;
+ typedef typename impl::data data_type;
+ typedef
+ detail::attr_matcher<
+ typename proto::result_of::value<typename expr_type::proto_child1>::type
+ , typename data_type::traits_type
+ , typename data_type::icase_type
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ return result_type(
+ proto::value(proto::left(expr)).nbr()
+ , proto::value(proto::right(expr))
+ , data.traits()
+ );
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // add_attrs
+ // Wrap an expression in attr_begin_matcher/attr_end_matcher pair
+ struct add_attrs : proto::transform<add_attrs>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ detail::attr_begin_matcher<
+ typename MaxAttr::template impl<Expr, mpl::int_<0>, int>::result_type
+ >
+ begin_type;
+
+ typedef typename impl::expr expr_type;
+
+ typedef
+ typename shift_right<
+ typename terminal<begin_type>::type
+ , typename shift_right<
+ Expr
+ , terminal<detail::attr_end_matcher>::type
+ >::type
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param
+ ) const
+ {
+ begin_type begin;
+ detail::attr_end_matcher end;
+ result_type that = {{begin}, {expr, {end}}};
+ return that;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // InsertAttrs
+ struct InsertAttrs
+ : if_<MaxAttr, add_attrs, _>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // CheckAssertion
+ struct CheckAssertion
+ : proto::function<terminal<detail::check_tag>, _>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // action_transform
+ // Turn A[B] into (mark_begin(n) >> A >> mark_end(n) >> action_matcher<B>(n))
+ // If A and B use attributes, wrap the above expression in
+ // a attr_begin_matcher<Count> / attr_end_matcher pair, where Count is
+ // the number of attribute slots used by the pattern/action.
+ struct as_action : proto::transform<as_action>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename proto::result_of::left<Expr>::type expr_type;
+ typedef typename proto::result_of::right<Expr>::type action_type;
+
+ typedef
+ typename DeepCopy::impl<action_type, expr_type, int>::result_type
+ action_copy_type;
+
+ typedef
+ typename InsertMark::impl<expr_type, State, Data>::result_type
+ marked_expr_type;
+
+ typedef
+ typename mpl::if_c<
+ proto::matches<action_type, CheckAssertion>::value
+ , detail::predicate_matcher<action_copy_type>
+ , detail::action_matcher<action_copy_type>
+ >::type
+ matcher_type;
+
+ typedef
+ typename proto::shift_right<
+ marked_expr_type
+ , typename proto::terminal<matcher_type>::type
+ >::type
+ no_attr_type;
+
+ typedef
+ typename InsertAttrs::impl<no_attr_type, State, Data>::result_type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ int dummy = 0;
+ marked_expr_type marked_expr =
+ InsertMark::impl<expr_type, State, Data>()(proto::left(expr), state, data);
+
+ no_attr_type that = {
+ marked_expr
+ , {
+ matcher_type(
+ DeepCopy::impl<action_type, expr_type, int>()(
+ proto::right(expr)
+ , proto::left(expr)
+ , dummy
+ )
+ , proto::value(proto::left(marked_expr)).mark_number_
+ )
+ }
+ };
+ return InsertAttrs::impl<no_attr_type, State, Data>()(that, state, data);
+ }
+ };
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_alternate.hpp b/boost/xpressive/detail/static/transforms/as_alternate.hpp
new file mode 100644
index 0000000000..521bb861e9
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_alternate.hpp
@@ -0,0 +1,131 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_alternate.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_ALTERNATE_HPP_EAN_04_01_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_ALTERNATE_HPP_EAN_04_01_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/xpressive/detail/core/matcher/alternate_matcher.hpp>
+#include <boost/xpressive/detail/utility/cons.hpp>
+
+namespace boost { namespace xpressive
+{
+ namespace detail
+ {
+ ///////////////////////////////////////////////////////////////////////////////
+ // alternates_list
+ // a fusion-compatible sequence of alternate expressions, that also keeps
+ // track of the list's width and purity.
+ template<typename Head, typename Tail>
+ struct alternates_list
+ : fusion::cons<Head, Tail>
+ {
+ BOOST_STATIC_CONSTANT(std::size_t, width = Head::width == Tail::width ? Head::width : detail::unknown_width::value);
+ BOOST_STATIC_CONSTANT(bool, pure = Head::pure && Tail::pure);
+
+ alternates_list(Head const &head, Tail const &tail)
+ : fusion::cons<Head, Tail>(head, tail)
+ {
+ }
+ };
+
+ template<typename Head>
+ struct alternates_list<Head, fusion::nil>
+ : fusion::cons<Head, fusion::nil>
+ {
+ BOOST_STATIC_CONSTANT(std::size_t, width = Head::width);
+ BOOST_STATIC_CONSTANT(bool, pure = Head::pure);
+
+ alternates_list(Head const &head, fusion::nil const &tail)
+ : fusion::cons<Head, fusion::nil>(head, tail)
+ {
+ }
+ };
+ }
+
+ namespace grammar_detail
+ {
+ ///////////////////////////////////////////////////////////////////////////////
+ // in_alternate_list
+ template<typename Grammar, typename Callable = proto::callable>
+ struct in_alternate_list : proto::transform<in_alternate_list<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ detail::alternates_list<
+ typename Grammar::template impl<
+ Expr
+ , detail::alternate_end_xpression
+ , Data
+ >::result_type
+ , State
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ return result_type(
+ typename Grammar::template impl<Expr, detail::alternate_end_xpression, Data>()(
+ expr
+ , detail::alternate_end_xpression()
+ , data
+ )
+ , state
+ );
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_alternate_matcher
+ template<typename Grammar, typename Callable = proto::callable>
+ struct as_alternate_matcher : proto::transform<as_alternate_matcher<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::data data_type;
+ typedef
+ detail::alternate_matcher<
+ typename Grammar::template impl<Expr, State, Data>::result_type
+ , typename data_type::traits_type
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ return result_type(
+ typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
+ );
+ }
+ };
+ };
+ }
+
+}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_independent.hpp b/boost/xpressive/detail/static/transforms/as_independent.hpp
new file mode 100644
index 0000000000..0001273575
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_independent.hpp
@@ -0,0 +1,215 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_independent.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_INDEPENDENT_HPP_EAN_04_05_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_INDEPENDENT_HPP_EAN_04_05_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/sizeof.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform/arg.hpp>
+#include <boost/proto/transform/when.hpp>
+#include <boost/proto/transform/fold.hpp>
+#include <boost/proto/transform/fold_tree.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ struct keeper_tag
+ {};
+
+ struct lookahead_tag
+ {};
+
+ struct lookbehind_tag
+ {};
+}}}
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+ // A grammar that only accepts static regexes that
+ // don't have semantic actions.
+ struct NotHasAction
+ : proto::switch_<struct NotHasActionCases>
+ {};
+
+ struct NotHasActionCases
+ {
+ template<typename Tag, int Dummy = 0>
+ struct case_
+ : proto::nary_expr<Tag, proto::vararg<NotHasAction> >
+ {};
+
+ template<int Dummy>
+ struct case_<proto::tag::terminal, Dummy>
+ : not_< or_<
+ proto::terminal<detail::tracking_ptr<detail::regex_impl<_> > >,
+ proto::terminal<reference_wrapper<_> >
+ > >
+ {};
+
+ template<int Dummy>
+ struct case_<proto::tag::comma, Dummy>
+ : proto::_ // because (set='a','b') can't contain an action
+ {};
+
+ template<int Dummy>
+ struct case_<proto::tag::complement, Dummy>
+ : proto::_ // because in ~X, X can't contain an unscoped action
+ {};
+
+ template<int Dummy>
+ struct case_<detail::lookahead_tag, Dummy>
+ : proto::_ // because actions in lookaheads are scoped
+ {};
+
+ template<int Dummy>
+ struct case_<detail::lookbehind_tag, Dummy>
+ : proto::_ // because actions in lookbehinds are scoped
+ {};
+
+ template<int Dummy>
+ struct case_<detail::keeper_tag, Dummy>
+ : proto::_ // because actions in keepers are scoped
+ {};
+
+ template<int Dummy>
+ struct case_<proto::tag::subscript, Dummy>
+ : proto::subscript<detail::set_initializer_type, _>
+ {}; // only accept set[...], not actions!
+ };
+
+ struct IndependentEndXpression
+ : or_<
+ when<NotHasAction, detail::true_xpression()>
+ , otherwise<detail::independent_end_xpression()>
+ >
+ {};
+
+ template<typename Grammar, typename Callable = proto::callable>
+ struct as_lookahead : proto::transform<as_lookahead<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename proto::result_of::child<Expr>::type arg_type;
+
+ typedef
+ typename IndependentEndXpression::impl<arg_type, int, int>::result_type
+ end_xpr_type;
+
+ typedef
+ typename Grammar::template impl<arg_type, end_xpr_type, Data>::result_type
+ xpr_type;
+
+ typedef
+ detail::lookahead_matcher<xpr_type>
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ int i = 0;
+ return result_type(
+ typename Grammar::template impl<arg_type, end_xpr_type, Data>()(
+ proto::child(expr)
+ , IndependentEndXpression::impl<arg_type, int, int>()(proto::child(expr), i, i)
+ , data
+ )
+ , false
+ );
+ }
+ };
+ };
+
+ template<typename Grammar, typename Callable = proto::callable>
+ struct as_lookbehind : proto::transform<as_lookbehind<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename proto::result_of::child<Expr>::type arg_type;
+
+ typedef
+ typename IndependentEndXpression::impl<arg_type, int, int>::result_type
+ end_xpr_type;
+
+ typedef
+ typename Grammar::template impl<arg_type, end_xpr_type, Data>::result_type
+ xpr_type;
+
+ typedef
+ detail::lookbehind_matcher<xpr_type>
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ int i = 0;
+ xpr_type expr2 = typename Grammar::template impl<arg_type, end_xpr_type, Data>()(
+ proto::child(expr)
+ , IndependentEndXpression::impl<arg_type, int, int>()(proto::child(expr), i, i)
+ , data
+ );
+ std::size_t width = expr2.get_width().value();
+ return result_type(expr2, width, false);
+ }
+ };
+ };
+
+ template<typename Grammar, typename Callable = proto::callable>
+ struct as_keeper : proto::transform<as_keeper<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename proto::result_of::child<Expr>::type arg_type;
+
+ typedef
+ typename IndependentEndXpression::impl<arg_type, int, int>::result_type
+ end_xpr_type;
+
+ typedef
+ typename Grammar::template impl<arg_type, end_xpr_type, Data>::result_type
+ xpr_type;
+
+ typedef
+ detail::keeper_matcher<xpr_type>
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ int i = 0;
+ return result_type(
+ typename Grammar::template impl<arg_type, end_xpr_type, Data>()(
+ proto::child(expr)
+ , IndependentEndXpression::impl<arg_type, int, int>()(proto::child(expr), i, i)
+ , data
+ )
+ );
+ }
+ };
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_inverse.hpp b/boost/xpressive/detail/static/transforms/as_inverse.hpp
new file mode 100644
index 0000000000..eef2d2e440
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_inverse.hpp
@@ -0,0 +1,94 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_inverse.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_INVERSE_HPP_EAN_04_05_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_INVERSE_HPP_EAN_04_05_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/sizeof.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/proto/core.hpp>
+
+#define UNCV(x) typename remove_const<x>::type
+#define UNREF(x) typename remove_reference<x>::type
+#define UNCVREF(x) UNCV(UNREF(x))
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+
+ template<typename T>
+ struct inverter
+ {
+ typedef T type;
+ static T call(T t)
+ {
+ t.inverse();
+ return t;
+ }
+ };
+
+ template<typename Traits, typename ICase, typename Not>
+ struct inverter<detail::literal_matcher<Traits, ICase, Not> >
+ {
+ typedef detail::literal_matcher<Traits, ICase, typename mpl::not_<Not>::type> type;
+ static type call(detail::literal_matcher<Traits, ICase, Not> t)
+ {
+ return type(t.ch_);
+ }
+ };
+
+ template<typename Traits>
+ struct inverter<detail::logical_newline_matcher<Traits> >
+ {
+ // ~_ln matches any one character that is not in the "newline" character class
+ typedef detail::posix_charset_matcher<Traits> type;
+ static type call(detail::logical_newline_matcher<Traits> t)
+ {
+ return type(t.newline(), true);
+ }
+ };
+
+ template<typename Traits>
+ struct inverter<detail::assert_word_matcher<detail::word_boundary<mpl::true_>, Traits> >
+ {
+ typedef detail::assert_word_matcher<detail::word_boundary<mpl::false_>, Traits> type;
+ static type call(detail::assert_word_matcher<detail::word_boundary<mpl::true_>, Traits> t)
+ {
+ return type(t.word());
+ }
+ };
+
+ struct as_inverse : proto::callable
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Matcher>
+ struct result<This(Matcher)>
+ : inverter<UNCVREF(Matcher)>
+ {};
+
+ template<typename Matcher>
+ typename inverter<Matcher>::type operator ()(Matcher const &matcher) const
+ {
+ return inverter<Matcher>::call(matcher);
+ }
+ };
+
+}}}
+
+#undef UNCV
+#undef UNREF
+#undef UNCVREF
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_marker.hpp b/boost/xpressive/detail/static/transforms/as_marker.hpp
new file mode 100644
index 0000000000..49ef8be124
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_marker.hpp
@@ -0,0 +1,58 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_marker.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_MARKER_HPP_EAN_04_01_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_MARKER_HPP_EAN_04_01_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/proto/core.hpp>
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_marker
+ // Insert mark tags before and after the expression
+ struct as_marker : proto::transform<as_marker>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename shift_right<
+ terminal<detail::mark_begin_matcher>::type
+ , typename shift_right<
+ typename proto::result_of::right<typename impl::expr>::type
+ , terminal<detail::mark_end_matcher>::type
+ >::type
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param
+ ) const
+ {
+ int mark_nbr = detail::get_mark_number(proto::left(expr));
+ detail::mark_begin_matcher begin(mark_nbr);
+ detail::mark_end_matcher end(mark_nbr);
+
+ result_type that = {{begin}, {proto::right(expr), {end}}};
+ return that;
+ }
+ };
+ };
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_matcher.hpp b/boost/xpressive/detail/static/transforms/as_matcher.hpp
new file mode 100644
index 0000000000..f8c6236196
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_matcher.hpp
@@ -0,0 +1,48 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_matcher.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_MATCHER_HPP_EAN_04_01_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_MATCHER_HPP_EAN_04_01_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+ struct as_matcher : proto::transform<as_matcher>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::data data_type;
+
+ typedef
+ typename data_type::template apply<
+ typename proto::result_of::value<typename impl::expr>::type
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ return data.call(proto::value(expr));
+ }
+ };
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_modifier.hpp b/boost/xpressive/detail/static/transforms/as_modifier.hpp
new file mode 100644
index 0000000000..6b1c587ab0
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_modifier.hpp
@@ -0,0 +1,85 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_modifier.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_MODIFIER_HPP_EAN_04_05_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_MODIFIER_HPP_EAN_04_05_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/sizeof.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/proto/core.hpp>
+
+#define UNCV(x) typename remove_const<x>::type
+#define UNREF(x) typename remove_reference<x>::type
+#define UNCVREF(x) UNCV(UNREF(x))
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // regex operator tags
+ struct modifier_tag
+ {};
+
+}}}
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_modifier
+ template<typename Grammar, typename Callable = proto::callable>
+ struct as_modifier : proto::transform<as_modifier<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename proto::result_of::value<
+ typename proto::result_of::left<typename impl::expr>::type
+ >::type
+ modifier_type;
+
+ typedef
+ typename modifier_type::template apply<typename impl::data>::type
+ visitor_type;
+
+ typedef
+ typename proto::result_of::right<Expr>::type
+ expr_type;
+
+ typedef
+ typename Grammar::template impl<expr_type, State, visitor_type &>::result_type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ visitor_type new_visitor(proto::value(proto::left(expr)).call(data));
+ return typename Grammar::template impl<expr_type, State, visitor_type &>()(
+ proto::right(expr)
+ , state
+ , new_visitor
+ );
+ }
+ };
+ };
+
+}}}
+
+#undef UNCV
+#undef UNREF
+#undef UNCVREF
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_quantifier.hpp b/boost/xpressive/detail/static/transforms/as_quantifier.hpp
new file mode 100644
index 0000000000..5770a8ed14
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_quantifier.hpp
@@ -0,0 +1,378 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_quantifier.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_QUANTIFIER_HPP_EAN_04_01_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_QUANTIFIER_HPP_EAN_04_01_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/proto/core.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // generic_quant_tag
+ template<uint_t Min, uint_t Max>
+ struct generic_quant_tag
+ {
+ typedef mpl::integral_c<uint_t, Min> min_type;
+ typedef mpl::integral_c<uint_t, Max> max_type;
+ };
+}}}
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+ using detail::uint_t;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // min_type / max_type
+ template<typename Tag>
+ struct min_type : Tag::min_type {};
+
+ template<>
+ struct min_type<proto::tag::unary_plus> : mpl::integral_c<uint_t, 1> {};
+
+ template<>
+ struct min_type<proto::tag::dereference> : mpl::integral_c<uint_t, 0> {};
+
+ template<>
+ struct min_type<proto::tag::logical_not> : mpl::integral_c<uint_t, 0> {};
+
+ template<typename Tag>
+ struct max_type : Tag::max_type {};
+
+ template<>
+ struct max_type<proto::tag::unary_plus> : mpl::integral_c<uint_t, UINT_MAX-1> {};
+
+ template<>
+ struct max_type<proto::tag::dereference> : mpl::integral_c<uint_t, UINT_MAX-1> {};
+
+ template<>
+ struct max_type<proto::tag::logical_not> : mpl::integral_c<uint_t, 1> {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_simple_quantifier
+ template<typename Grammar, typename Greedy, typename Callable = proto::callable>
+ struct as_simple_quantifier : proto::transform<as_simple_quantifier<Grammar, Greedy, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename proto::result_of::child<Expr>::type
+ arg_type;
+
+ typedef
+ typename Grammar::template impl<arg_type, detail::true_xpression, Data>::result_type
+ xpr_type;
+
+ typedef
+ detail::simple_repeat_matcher<xpr_type, Greedy>
+ matcher_type;
+
+ typedef
+ typename proto::terminal<matcher_type>::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ xpr_type xpr = typename Grammar::template impl<arg_type, detail::true_xpression, Data>()(
+ proto::child(expr)
+ , detail::true_xpression()
+ , data
+ );
+
+ typedef typename impl::expr expr_type;
+ matcher_type matcher(
+ xpr
+ , (uint_t)min_type<typename expr_type::proto_tag>::value
+ , (uint_t)max_type<typename expr_type::proto_tag>::value
+ , xpr.get_width().value()
+ );
+
+ return result_type::make(matcher);
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // add_hidden_mark
+ struct add_hidden_mark : proto::transform<add_hidden_mark>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::expr expr_type;
+ typedef
+ typename shift_right<
+ terminal<detail::mark_begin_matcher>::type
+ , typename shift_right<
+ Expr
+ , terminal<detail::mark_end_matcher>::type
+ >::type
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ // we're inserting a hidden mark ... so grab the next hidden mark number.
+ int mark_nbr = data.get_hidden_mark();
+ detail::mark_begin_matcher begin(mark_nbr);
+ detail::mark_end_matcher end(mark_nbr);
+
+ result_type that = {{begin}, {expr, {end}}};
+ return that;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // InsertMark
+ struct InsertMark
+ : or_<
+ when<proto::assign<detail::basic_mark_tag, _>, _>
+ , otherwise<add_hidden_mark>
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_default_quantifier_impl
+ template<typename Greedy, uint_t Min, uint_t Max>
+ struct as_default_quantifier_impl : proto::transform<as_default_quantifier_impl<Greedy, Min, Max> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename proto::result_of::child<Expr>::type
+ xpr_type;
+
+ typedef
+ typename InsertMark::impl<xpr_type, State, Data>::result_type
+ marked_sub_type;
+
+ typedef
+ typename shift_right<
+ terminal<detail::repeat_begin_matcher>::type
+ , typename shift_right<
+ marked_sub_type
+ , typename terminal<detail::repeat_end_matcher<Greedy> >::type
+ >::type
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ // Ensure this sub-expression is book-ended with mark matchers
+ marked_sub_type marked_sub =
+ InsertMark::impl<xpr_type, State, Data>()(proto::child(expr), state, data);
+
+ // Get the mark_number from the begin_mark_matcher
+ int mark_number = proto::value(proto::left(marked_sub)).mark_number_;
+ BOOST_ASSERT(0 != mark_number);
+
+ typedef typename impl::expr expr_type;
+ uint_t min_ = (uint_t)min_type<typename expr_type::proto_tag>();
+ uint_t max_ = (uint_t)max_type<typename expr_type::proto_tag>();
+
+ detail::repeat_begin_matcher begin(mark_number);
+ detail::repeat_end_matcher<Greedy> end(mark_number, min_, max_);
+
+ result_type that = {{begin}, {marked_sub, {end}}};
+ return that;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // optional_tag
+ template<typename Greedy>
+ struct optional_tag
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_default_optional
+ template<typename Grammar, typename Greedy, typename Callable = proto::callable>
+ struct as_default_optional : proto::transform<as_default_optional<Grammar, Greedy, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ detail::alternate_end_xpression
+ end_xpr;
+
+ typedef
+ detail::optional_matcher<
+ typename Grammar::template impl<Expr, end_xpr, Data>::result_type
+ , Greedy
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ return result_type(
+ typename Grammar::template impl<Expr, end_xpr, Data>()(expr, end_xpr(), data)
+ );
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_mark_optional
+ template<typename Grammar, typename Greedy, typename Callable = proto::callable>
+ struct as_mark_optional : proto::transform<as_mark_optional<Grammar, Greedy, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ detail::alternate_end_xpression
+ end_xpr;
+
+ typedef
+ detail::optional_mark_matcher<
+ typename Grammar::template impl<Expr, end_xpr, Data>::result_type
+ , Greedy
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ int mark_number = proto::value(proto::left(expr)).mark_number_;
+
+ return result_type(
+ typename Grammar::template impl<Expr, end_xpr, Data>()(expr, end_xpr(), data)
+ , mark_number
+ );
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // IsMarkerOrRepeater
+ struct IsMarkerOrRepeater
+ : or_<
+ shift_right<terminal<detail::repeat_begin_matcher>, _>
+ , assign<terminal<detail::mark_placeholder>, _>
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_optional
+ template<typename Grammar, typename Greedy>
+ struct as_optional
+ : or_<
+ when<IsMarkerOrRepeater, as_mark_optional<Grammar, Greedy> >
+ , otherwise<as_default_optional<Grammar, Greedy> >
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // make_optional_
+ template<typename Greedy, typename Callable = proto::callable>
+ struct make_optional_ : proto::transform<make_optional_<Greedy, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::expr expr_type;
+ typedef
+ typename unary_expr<
+ optional_tag<Greedy>
+ , Expr
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param
+ ) const
+ {
+ result_type that = {expr};
+ return that;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_default_quantifier_impl
+ template<typename Greedy, uint_t Max>
+ struct as_default_quantifier_impl<Greedy, 0, Max>
+ : call<make_optional_<Greedy>(as_default_quantifier_impl<Greedy, 1, Max>)>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_default_quantifier_impl
+ template<typename Greedy>
+ struct as_default_quantifier_impl<Greedy, 0, 1>
+ : call<make_optional_<Greedy>(_child)>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_default_quantifier
+ template<typename Greedy, typename Callable = proto::callable>
+ struct as_default_quantifier : proto::transform<as_default_quantifier<Greedy, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::expr expr_type;
+ typedef
+ as_default_quantifier_impl<
+ Greedy
+ , min_type<typename expr_type::proto_tag>::value
+ , max_type<typename expr_type::proto_tag>::value
+ >
+ other;
+
+ typedef
+ typename other::template impl<Expr, State, Data>::result_type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ return typename other::template impl<Expr, State, Data>()(expr, state, data);
+ }
+ };
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_sequence.hpp b/boost/xpressive/detail/static/transforms/as_sequence.hpp
new file mode 100644
index 0000000000..62301618f1
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_sequence.hpp
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_sequence.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SEQUENCE_HPP_EAN_04_01_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SEQUENCE_HPP_EAN_04_01_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+ template<typename Grammar, typename Callable = proto::callable>
+ struct in_sequence : proto::transform<in_sequence<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ detail::static_xpression<
+ typename Grammar::template impl<Expr, State, Data>::result_type
+ , State
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ return result_type(
+ typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
+ , state
+ );
+ }
+ };
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transforms/as_set.hpp b/boost/xpressive/detail/static/transforms/as_set.hpp
new file mode 100644
index 0000000000..6d5c252610
--- /dev/null
+++ b/boost/xpressive/detail/static/transforms/as_set.hpp
@@ -0,0 +1,224 @@
+///////////////////////////////////////////////////////////////////////////////
+// as_set.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SET_HPP_EAN_04_05_2007
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SET_HPP_EAN_04_05_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/assert.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/static/static.hpp>
+#include <boost/xpressive/detail/utility/chset/chset.hpp>
+#include <boost/xpressive/detail/utility/traits_utils.hpp>
+
+namespace boost { namespace xpressive { namespace grammar_detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////
+ // CharLiteral
+ template<typename Char>
+ struct CharLiteral
+ : or_<
+ terminal<char>
+ , terminal<Char>
+ >
+ {};
+
+ template<>
+ struct CharLiteral<char>
+ : terminal<char>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ListSet
+ // matches expressions like (set= 'a','b','c')
+ // calculates the size of the set
+ template<typename Char>
+ struct ListSet
+ : or_<
+ when<
+ comma<ListSet<Char>, CharLiteral<Char> >
+ , make<mpl::next<call<ListSet<Char>(_left)> > > // TODO make a custom transform for this...
+ >
+ , when<
+ assign<detail::set_initializer_type, CharLiteral<Char> >
+ , make<mpl::int_<1> >
+ >
+ >
+ {};
+
+ template<typename Char, typename Traits>
+ void fill_list_set(Char *&, detail::set_initializer_type, Traits const &)
+ {}
+
+ template<typename Char, typename Expr, typename Traits>
+ void fill_list_set(Char *&buffer, Expr const &expr, Traits const &traits)
+ {
+ fill_list_set(buffer, proto::left(expr), traits);
+ *buffer++ = traits.translate(detail::char_cast<Char>(proto::value(proto::right(expr)), traits));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // as_list_set_matcher
+ template<typename Char, typename Callable = proto::callable>
+ struct as_list_set_matcher : proto::transform<as_list_set_matcher<Char, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::data data_type;
+ typedef
+ detail::set_matcher<
+ typename data_type::traits_type
+ , typename ListSet<Char>::template impl<Expr, State, Data>::result_type
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ result_type set;
+ typedef typename impl::data data_type;
+ typename data_type::char_type *buffer = set.set_;
+ fill_list_set(buffer, expr, data.traits());
+ return set;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // merge_charset
+ //
+ template<typename Grammar, typename CharSet, typename Data>
+ struct merge_charset
+ {
+ typedef typename Data::traits_type traits_type;
+ typedef typename CharSet::char_type char_type;
+ typedef typename CharSet::icase_type icase_type;
+
+ merge_charset(CharSet &charset, Data &data)
+ : charset_(charset)
+ , visitor_(data)
+ {}
+
+ template<typename Expr>
+ void operator ()(Expr const &expr) const
+ {
+ this->call_(expr, typename Expr::proto_tag());
+ }
+
+ private:
+ merge_charset &operator =(merge_charset const &);
+
+ template<typename Expr, typename Tag>
+ void call_(Expr const &expr, Tag) const
+ {
+ this->set_(
+ typename Grammar::template impl<Expr const &, detail::end_xpression, Data &>()(
+ expr
+ , detail::end_xpression()
+ , this->visitor_
+ )
+ );
+ }
+
+ template<typename Expr>
+ void call_(Expr const &expr, tag::bitwise_or) const
+ {
+ (*this)(proto::left(expr));
+ (*this)(proto::right(expr));
+ }
+
+ template<typename Not>
+ void set_(detail::literal_matcher<traits_type, icase_type, Not> const &ch) const
+ {
+ // BUGBUG fixme!
+ BOOST_MPL_ASSERT_NOT((Not));
+ set_char(this->charset_.charset_, ch.ch_, this->visitor_.traits(), icase_type());
+ }
+
+ void set_(detail::range_matcher<traits_type, icase_type> const &rg) const
+ {
+ // BUGBUG fixme!
+ BOOST_ASSERT(!rg.not_);
+ set_range(this->charset_.charset_, rg.ch_min_, rg.ch_max_, this->visitor_.traits(), icase_type());
+ }
+
+ template<typename Size>
+ void set_(detail::set_matcher<traits_type, Size> const &set_) const
+ {
+ // BUGBUG fixme!
+ BOOST_ASSERT(!set_.not_);
+ for(int i = 0; i < Size::value; ++i)
+ {
+ set_char(this->charset_.charset_, set_.set_[i], this->visitor_.traits(), icase_type());
+ }
+ }
+
+ void set_(detail::posix_charset_matcher<traits_type> const &posix) const
+ {
+ set_class(this->charset_.charset_, posix.mask_, posix.not_, this->visitor_.traits());
+ }
+
+ CharSet &charset_;
+ Data &visitor_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ template<typename Grammar, typename Callable = proto::callable>
+ struct as_set_matcher : proto::transform<as_set_matcher<Grammar, Callable> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename impl::data data_type;
+ typedef typename data_type::char_type char_type;
+
+ // if sizeof(char_type)==1, merge everything into a basic_chset
+ // BUGBUG this is not optimal.
+ typedef
+ typename mpl::if_c<
+ detail::is_narrow_char<char_type>::value
+ , detail::basic_chset<char_type>
+ , detail::compound_charset<typename data_type::traits_type>
+ >::type
+ charset_type;
+
+ typedef
+ detail::charset_matcher<
+ typename data_type::traits_type
+ , typename data_type::icase_type
+ , charset_type
+ >
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param
+ , typename impl::data_param data
+ ) const
+ {
+ result_type matcher;
+ merge_charset<Grammar, result_type, typename impl::data> merge(matcher, data);
+ merge(expr); // Walks the tree and fills in the charset
+ return matcher;
+ }
+ };
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/transmogrify.hpp b/boost/xpressive/detail/static/transmogrify.hpp
new file mode 100644
index 0000000000..67f6588c22
--- /dev/null
+++ b/boost/xpressive/detail/static/transmogrify.hpp
@@ -0,0 +1,240 @@
+///////////////////////////////////////////////////////////////////////////////
+// transmogrify.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSMOGRIFY_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSMOGRIFY_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <cstring> // for std::strlen
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/matchers.hpp>
+#include <boost/xpressive/detail/static/placeholders.hpp>
+#include <boost/xpressive/detail/utility/dont_care.hpp>
+#include <boost/xpressive/detail/utility/traits_utils.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ template<typename T, typename Char>
+ struct is_char_literal
+ : mpl::or_<is_same<T, Char>, is_same<T, char> >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // transmogrify
+ //
+ template<typename BidiIter, typename ICase, typename Traits, typename Matcher, typename EnableIf = void>
+ struct default_transmogrify
+ {
+ typedef typename Traits::char_type char_type;
+ typedef typename Traits::string_type string_type;
+
+ typedef typename mpl::if_c
+ <
+ is_char_literal<Matcher, char_type>::value
+ , literal_matcher<Traits, ICase, mpl::false_>
+ , string_matcher<Traits, ICase>
+ >::type type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2 const &m, Visitor &visitor)
+ {
+ return default_transmogrify::call_(m, visitor, is_char_literal<Matcher2, char_type>());
+ }
+
+ template<typename Matcher2, typename Visitor>
+ static type call_(Matcher2 const &m, Visitor &visitor, mpl::true_)
+ {
+ char_type ch = char_cast<char_type>(m, visitor.traits());
+ return type(ch, visitor.traits());
+ }
+
+ template<typename Matcher2, typename Visitor>
+ static type call_(Matcher2 const &m, Visitor &visitor, mpl::false_)
+ {
+ string_type str = string_cast<string_type>(m, visitor.traits());
+ return type(str, visitor.traits());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits, typename Matcher>
+ struct default_transmogrify<BidiIter, ICase, Traits, Matcher, typename Matcher::is_boost_xpressive_xpression_>
+ {
+ typedef Matcher type;
+
+ template<typename Matcher2>
+ static Matcher2 const &call(Matcher2 const &m, dont_care)
+ {
+ return m;
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits, typename Matcher>
+ struct transmogrify
+ : default_transmogrify<BidiIter, ICase, Traits, Matcher>
+ {};
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, assert_bol_placeholder >
+ {
+ typedef assert_bol_matcher<Traits> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2, Visitor &visitor)
+ {
+ return type(visitor.traits());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, assert_eol_placeholder >
+ {
+ typedef assert_eol_matcher<Traits> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2, Visitor &visitor)
+ {
+ return type(visitor.traits());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, logical_newline_placeholder >
+ {
+ typedef logical_newline_matcher<Traits> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2, Visitor &visitor)
+ {
+ return type(visitor.traits());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits, typename Char>
+ struct transmogrify<BidiIter, ICase, Traits, range_placeholder<Char> >
+ {
+ // By design, we don't widen character ranges.
+ typedef typename iterator_value<BidiIter>::type char_type;
+ BOOST_MPL_ASSERT((is_same<Char, char_type>));
+ typedef range_matcher<Traits, ICase> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2 const &m, Visitor &visitor)
+ {
+ return type(m.ch_min_, m.ch_max_, m.not_, visitor.traits());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, mark_placeholder >
+ {
+ typedef mark_matcher<Traits, ICase> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2 const &m, Visitor &visitor)
+ {
+ return type(m.mark_number_, visitor.traits());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, posix_charset_placeholder >
+ {
+ typedef posix_charset_matcher<Traits> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2 const &m, Visitor &visitor)
+ {
+ char const *name_end = m.name_ + std::strlen(m.name_);
+ return type(visitor.traits().lookup_classname(m.name_, name_end, ICase::value), m.not_);
+ }
+ };
+
+ template<typename BidiIter, typename Traits, typename Size>
+ struct transmogrify<BidiIter, mpl::true_, Traits, set_matcher<Traits, Size> >
+ {
+ typedef set_matcher<Traits, Size> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2 m, Visitor &visitor)
+ {
+ m.nocase(visitor.traits());
+ return m;
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits, typename Cond>
+ struct transmogrify<BidiIter, ICase, Traits, assert_word_placeholder<Cond> >
+ {
+ typedef assert_word_matcher<Cond, Traits> type;
+
+ template<typename Visitor>
+ static type call(dont_care, Visitor &visitor)
+ {
+ return type(visitor.traits());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, reference_wrapper<basic_regex<BidiIter> > >
+ {
+ typedef regex_byref_matcher<BidiIter> type;
+
+ template<typename Matcher2>
+ static type call(Matcher2 const &m, dont_care)
+ {
+ return type(detail::core_access<BidiIter>::get_regex_impl(m.get()));
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, reference_wrapper<basic_regex<BidiIter> const> >
+ {
+ typedef regex_byref_matcher<BidiIter> type;
+
+ template<typename Matcher2>
+ static type call(Matcher2 const &m, dont_care)
+ {
+ return type(detail::core_access<BidiIter>::get_regex_impl(m.get()));
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, tracking_ptr<regex_impl<BidiIter> > >
+ {
+ typedef regex_matcher<BidiIter> type;
+
+ template<typename Matcher2>
+ static type call(Matcher2 const &m, dont_care)
+ {
+ return type(m.get());
+ }
+ };
+
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct transmogrify<BidiIter, ICase, Traits, self_placeholder >
+ {
+ typedef regex_byref_matcher<BidiIter> type;
+
+ template<typename Matcher2, typename Visitor>
+ static type call(Matcher2, Visitor &visitor)
+ {
+ return type(visitor.self());
+ }
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/type_traits.hpp b/boost/xpressive/detail/static/type_traits.hpp
new file mode 100644
index 0000000000..67ba77e328
--- /dev/null
+++ b/boost/xpressive/detail/static/type_traits.hpp
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+// type_traits.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TYPE_TRAITS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_TYPE_TRAITS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// is_static_xpression
+//
+template<typename T>
+struct is_static_xpression
+ : mpl::false_
+{
+};
+
+template<typename Matcher, typename Next>
+struct is_static_xpression<static_xpression<Matcher, Next> >
+ : mpl::true_
+{
+};
+
+template<typename Top, typename Next>
+struct is_static_xpression<stacked_xpression<Top, Next> >
+ : mpl::true_
+{
+};
+
+//////////////////////////////////////////////////////////////////////////
+// is_random
+//
+template<typename BidiIter>
+struct is_random
+ : is_convertible
+ <
+ typename iterator_category<BidiIter>::type
+ , std::random_access_iterator_tag
+ >
+{
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/static/visitor.hpp b/boost/xpressive/detail/static/visitor.hpp
new file mode 100644
index 0000000000..5a0213f695
--- /dev/null
+++ b/boost/xpressive/detail/static/visitor.hpp
@@ -0,0 +1,143 @@
+///////////////////////////////////////////////////////////////////////////////
+// visitor.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_VISITOR_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_VISITOR_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/ref.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/static/transmogrify.hpp>
+#include <boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ template<typename BidiIter>
+ struct xpression_visitor_base
+ {
+ explicit xpression_visitor_base(shared_ptr<regex_impl<BidiIter> > const &self)
+ : self_(self)
+ {
+ }
+
+ void swap(xpression_visitor_base<BidiIter> &that)
+ {
+ this->self_.swap(that.self_);
+ }
+
+ int get_hidden_mark()
+ {
+ return -(int)(++this->self_->hidden_mark_count_);
+ }
+
+ void mark_number(int mark_nbr)
+ {
+ if(0 < mark_nbr)
+ {
+ this->self_->mark_count_ =
+ (std::max)(this->self_->mark_count_, (std::size_t)mark_nbr);
+ }
+ }
+
+ shared_ptr<regex_impl<BidiIter> > &self()
+ {
+ return this->self_;
+ }
+
+ protected:
+
+ template<typename Matcher>
+ void visit_(Matcher const &)
+ {
+ }
+
+ void visit_(reference_wrapper<basic_regex<BidiIter> > const &rex)
+ {
+ // when visiting an embedded regex, track the references
+ this->self_->track_reference(*detail::core_access<BidiIter>::get_regex_impl(rex.get()));
+ }
+
+ void visit_(reference_wrapper<basic_regex<BidiIter> const> const &rex)
+ {
+ // when visiting an embedded regex, track the references
+ this->self_->track_reference(*detail::core_access<BidiIter>::get_regex_impl(rex.get()));
+ }
+
+ void visit_(tracking_ptr<regex_impl<BidiIter> > const &rex)
+ {
+ // when visiting an embedded regex, track the references
+ this->self_->track_reference(*rex.get());
+ }
+
+ void visit_(mark_placeholder const &backref)
+ {
+ // keep track of the largest mark number found
+ this->mark_number(backref.mark_number_);
+ }
+
+ void visit_(mark_begin_matcher const &mark_begin)
+ {
+ // keep track of the largest mark number found
+ this->mark_number(mark_begin.mark_number_);
+ }
+
+ private:
+ shared_ptr<regex_impl<BidiIter> > self_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ template<typename BidiIter, typename ICase, typename Traits>
+ struct xpression_visitor
+ : xpression_visitor_base<BidiIter>
+ {
+ typedef BidiIter iterator_type;
+ typedef ICase icase_type;
+ typedef Traits traits_type;
+ typedef typename boost::iterator_value<BidiIter>::type char_type;
+
+ explicit xpression_visitor(Traits const &tr, shared_ptr<regex_impl<BidiIter> > const &self)
+ : xpression_visitor_base<BidiIter>(self)
+ , traits_(tr)
+ {
+ }
+
+ template<typename Matcher>
+ struct apply
+ {
+ typedef typename transmogrify<BidiIter, ICase, Traits, Matcher>::type type;
+ };
+
+ template<typename Matcher>
+ typename apply<Matcher>::type
+ call(Matcher const &matcher)
+ {
+ this->visit_(matcher);
+ return transmogrify<BidiIter, ICase, Traits, Matcher>::call(matcher, *this);
+ }
+
+ Traits const &traits() const
+ {
+ return this->traits_;
+ }
+
+ private:
+
+ Traits traits_;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/static/width_of.hpp b/boost/xpressive/detail/static/width_of.hpp
new file mode 100644
index 0000000000..eec6e5491d
--- /dev/null
+++ b/boost/xpressive/detail/static/width_of.hpp
@@ -0,0 +1,287 @@
+///////////////////////////////////////////////////////////////////////////////
+// width_of.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_WIDTH_OF_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_STATIC_WIDTH_OF_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/ref.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/plus.hpp>
+#include <boost/mpl/times.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/size_t.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/proto/traits.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ template<typename Expr, typename Char, typename Tag = typename Expr::proto_tag>
+ struct width_of;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // add_widths
+ //
+ template<std::size_t N, std::size_t M>
+ struct add_widths
+ : mpl::size_t<N + M>
+ {};
+
+ template<std::size_t M>
+ struct add_widths<unknown_width::value, M>
+ : unknown_width
+ {};
+
+ template<std::size_t N>
+ struct add_widths<N, unknown_width::value>
+ : unknown_width
+ {};
+
+ template<>
+ struct add_widths<unknown_width::value, unknown_width::value>
+ : unknown_width
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // or_widths
+ //
+ template<std::size_t N, std::size_t M>
+ struct or_widths
+ : unknown_width
+ {};
+
+ template<std::size_t N>
+ struct or_widths<N, N>
+ : mpl::size_t<N>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // is_char
+ //
+ template<typename T>
+ struct is_char
+ : mpl::false_
+ {};
+
+ template<>
+ struct is_char<char>
+ : mpl::true_
+ {};
+
+ template<>
+ struct is_char<wchar_t>
+ : mpl::true_
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // width_of_terminal
+ //
+ template<typename Expr, typename Char, bool IsXpr = is_xpr<Expr>::value>
+ struct width_of_terminal
+ : mpl::size_t<Expr::width> // xpressive literals
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of_terminal<Expr, Char, false>
+ : unknown_width // unknown literals (eg, basic_string, basic_regex, etc.)
+ {};
+
+ template<typename Char>
+ struct width_of_terminal<Char, Char, false>
+ : mpl::size_t<1> // char literals
+ {};
+
+ template<typename Char>
+ struct width_of_terminal<char, Char, false>
+ : mpl::size_t<1> // char literals
+ {};
+
+ template<>
+ struct width_of_terminal<char, char, false>
+ : mpl::size_t<1> // char literals
+ {};
+
+ template<typename Elem, std::size_t N, typename Char>
+ struct width_of_terminal<Elem (&) [N], Char, false>
+ : mpl::size_t<N-is_char<Elem>::value> // string literals
+ {};
+
+ template<typename Elem, std::size_t N, typename Char>
+ struct width_of_terminal<Elem const (&) [N], Char, false>
+ : mpl::size_t<N-is_char<Elem>::value> // string literals
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // width_of
+ //
+ template<typename Expr, typename Char, typename Tag>
+ struct width_of
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::terminal>
+ : width_of_terminal<typename proto::result_of::value<Expr>::type, Char>
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::shift_right>
+ : add_widths<
+ width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>::value
+ , width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value
+ >
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::bitwise_or>
+ : or_widths<
+ width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>::value
+ , width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value
+ >
+ {};
+
+ template<typename Expr, typename Char, typename Left>
+ struct width_of_assign
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of_assign<Expr, Char, mark_placeholder>
+ : width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of_assign<Expr, Char, set_initializer>
+ : mpl::size_t<1>
+ {};
+
+ template<typename Expr, typename Char, typename Nbr>
+ struct width_of_assign<Expr, Char, attribute_placeholder<Nbr> >
+ : unknown_width
+ {};
+
+ // either (s1 = ...) or (a1 = ...) or (set = ...)
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::assign>
+ : width_of_assign<
+ Expr
+ , Char
+ , typename proto::result_of::value<
+ typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr
+ >::type
+ >
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, modifier_tag>
+ : width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, lookahead_tag>
+ : mpl::size_t<0>
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, lookbehind_tag>
+ : mpl::size_t<0>
+ {};
+
+ // keep() is used to turn off backtracking, so they should only be used
+ // for things that are variable-width (eg. quantified)
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, keeper_tag>
+ : unknown_width
+ {
+ // TODO: keep() now has a second meaning: execute actions immediately.
+ // In that sense, it is perfectly reasonable to put a fixed-width
+ // sub-expression in a keep. Can fixed-width keep() sub-expressions
+ // use the simple_repeat_matcher?
+ };
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::unary_plus>
+ : unknown_width
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::dereference>
+ : unknown_width
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::logical_not>
+ : unknown_width
+ {};
+
+ template<typename Expr, typename Char, uint_t Min, uint_t Max>
+ struct width_of<Expr, Char, generic_quant_tag<Min, Max> >
+ : unknown_width
+ {};
+
+ template<typename Expr, typename Char, uint_t Count>
+ struct width_of<Expr, Char, generic_quant_tag<Count, Count> >
+ : mpl::if_c<
+ mpl::equal_to<unknown_width, width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char> >::value
+ , unknown_width
+ , mpl::times<
+ width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ , mpl::size_t<Count>
+ >
+ >::type
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::negate>
+ : width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ {};
+
+ // when complementing a set or an assertion, the width is that of the set (1) or the assertion (0)
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::complement>
+ : width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
+ {};
+
+ // The comma is used in list-initialized sets, and the width of sets are 1
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::comma>
+ : mpl::size_t<1>
+ {};
+
+ // The subscript operator[] is used for sets, as in set['a' | range('b','h')],
+ // or for actions as in (any >> expr)[ action ]
+ template<typename Expr, typename Char, typename Left>
+ struct width_of_subscript
+ : width_of<Left, Char>
+ {};
+
+ template<typename Expr, typename Char>
+ struct width_of_subscript<Expr, Char, set_initializer_type>
+ : mpl::size_t<1>
+ {
+ // If Left is "set" then make sure that Right has a width_of 1
+ BOOST_MPL_ASSERT_RELATION(
+ 1
+ , ==
+ , (width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value));
+ };
+
+ template<typename Expr, typename Char>
+ struct width_of<Expr, Char, proto::tag::subscript>
+ : width_of_subscript<Expr, Char, typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr>
+ {};
+
+}}} // namespace boost::xpressive::detail
+
+#undef UNREF
+
+#endif
diff --git a/boost/xpressive/detail/utility/algorithm.hpp b/boost/xpressive/detail/utility/algorithm.hpp
new file mode 100644
index 0000000000..af722909c3
--- /dev/null
+++ b/boost/xpressive/detail/utility/algorithm.hpp
@@ -0,0 +1,174 @@
+///////////////////////////////////////////////////////////////////////////////
+// algorithm.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_ALGORITHM_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_ALGORITHM_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <string>
+#include <climits>
+#include <algorithm>
+#include <boost/version.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/size.hpp>
+#include <boost/range/value_type.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// any
+//
+template<typename InIter, typename Pred>
+inline bool any(InIter begin, InIter end, Pred pred)
+{
+ return end != std::find_if(begin, end, pred);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// find_nth_if
+//
+template<typename FwdIter, typename Diff, typename Pred>
+FwdIter find_nth_if(FwdIter begin, FwdIter end, Diff count, Pred pred)
+{
+ for(; begin != end; ++begin)
+ {
+ if(pred(*begin) && 0 == count--)
+ {
+ return begin;
+ }
+ }
+
+ return end;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// toi
+//
+template<typename InIter, typename Traits>
+int toi(InIter &begin, InIter end, Traits const &tr, int radix = 10, int max = INT_MAX)
+{
+ detail::ignore_unused(tr);
+ int i = 0, c = 0;
+ for(; begin != end && -1 != (c = tr.value(*begin, radix)); ++begin)
+ {
+ if(max < ((i *= radix) += c))
+ return i / radix;
+ }
+ return i;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// advance_to
+//
+template<typename BidiIter, typename Diff>
+inline bool advance_to_impl(BidiIter & iter, Diff diff, BidiIter end, std::bidirectional_iterator_tag)
+{
+ for(; 0 < diff && iter != end; --diff)
+ ++iter;
+ for(; 0 > diff && iter != end; ++diff)
+ --iter;
+ return 0 == diff;
+}
+
+template<typename RandIter, typename Diff>
+inline bool advance_to_impl(RandIter & iter, Diff diff, RandIter end, std::random_access_iterator_tag)
+{
+ if(0 < diff)
+ {
+ if((end - iter) < diff)
+ return false;
+ }
+ else if(0 > diff)
+ {
+ if((iter - end) < -diff)
+ return false;
+ }
+ iter += diff;
+ return true;
+}
+
+template<typename Iter, typename Diff>
+inline bool advance_to(Iter & iter, Diff diff, Iter end)
+{
+ return detail::advance_to_impl(iter, diff, end, typename iterator_category<Iter>::type());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// range_data
+//
+template<typename T>
+struct range_data
+ : range_value<T>
+{};
+
+template<typename T>
+struct range_data<T *>
+ : remove_const<T>
+{};
+
+template<typename T> std::ptrdiff_t is_null_terminated(T const &) { return 0; }
+#if BOOST_VERSION >= 103500
+inline std::ptrdiff_t is_null_terminated(char const *) { return 1; }
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+inline std::ptrdiff_t is_null_terminated(wchar_t const *) { return 1; }
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// data_begin/data_end
+//
+template<typename Cont>
+typename range_data<Cont>::type const *data_begin(Cont const &cont)
+{
+ return &*boost::begin(cont);
+}
+
+template<typename Cont>
+typename range_data<Cont>::type const *data_end(Cont const &cont)
+{
+ return &*boost::begin(cont) + boost::size(cont) - is_null_terminated(cont);
+}
+
+template<typename Char, typename Traits, typename Alloc>
+Char const *data_begin(std::basic_string<Char, Traits, Alloc> const &str)
+{
+ return str.data();
+}
+
+template<typename Char, typename Traits, typename Alloc>
+Char const *data_end(std::basic_string<Char, Traits, Alloc> const &str)
+{
+ return str.data() + str.size();
+}
+
+template<typename Char>
+Char const *data_begin(Char const *const &sz)
+{
+ return sz;
+}
+
+template<typename Char>
+Char const *data_end(Char const *const &sz)
+{
+ Char const *tmp = sz;
+ for(; *tmp; ++tmp)
+ ;
+ return tmp;
+}
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/utility/any.hpp b/boost/xpressive/detail/utility/any.hpp
new file mode 100644
index 0000000000..66ce4637da
--- /dev/null
+++ b/boost/xpressive/detail/utility/any.hpp
@@ -0,0 +1,108 @@
+///////////////////////////////////////////////////////////////////////////////
+// any.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_ANY_HPP_EAN_11_19_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_ANY_HPP_EAN_11_19_2005
+
+#include <boost/version.hpp>
+
+#if BOOST_VERSION >= 103300
+
+// In Boost 1.33+, we have a cons list in Fusion, so just include it.
+
+# if BOOST_VERSION >= 103500
+# include <boost/fusion/include/any.hpp> // Boost 1.35+ has Fusion2
+# else
+# include <boost/spirit/fusion/algorithm/any.hpp> // Fusion1
+# endif
+
+#else
+
+# include <boost/spirit/fusion/sequence/begin.hpp>
+# include <boost/spirit/fusion/sequence/end.hpp>
+# include <boost/spirit/fusion/iterator/equal_to.hpp>
+# include <boost/mpl/bool.hpp>
+# include <boost/spirit/fusion/iterator/equal_to.hpp>
+# include <boost/spirit/fusion/iterator/next.hpp>
+# include <boost/spirit/fusion/iterator/deref.hpp>
+
+namespace boost { namespace fusion
+{
+
+ namespace detail
+ {
+ template <typename First, typename Last, typename F>
+ inline bool
+ any(First const&, Last const&, F const&, mpl::true_)
+ {
+ return false;
+ }
+
+ template <typename First, typename Last, typename F>
+ inline bool
+ any(First const& first, Last const& last, F const& f, mpl::false_)
+ {
+ if(f(*first))
+ return true;
+ return detail::any(fusion::next(first), last, f
+ , meta::equal_to<BOOST_DEDUCED_TYPENAME meta::next<First>::type, Last>());
+ }
+ }
+
+ namespace meta
+ {
+ template <typename Sequence, typename F>
+ struct any
+ {
+ typedef bool type;
+ };
+ }
+
+ namespace function
+ {
+ struct any
+ {
+ template <typename Sequence, typename F>
+ struct apply
+ {
+ typedef bool type;
+ };
+
+ template <typename Sequence, typename F>
+ inline bool
+ operator()(Sequence const& seq, F const& f) const
+ {
+ return detail::any(
+ fusion::begin(seq)
+ , fusion::end(seq)
+ , f
+ , meta::equal_to<
+ BOOST_DEDUCED_TYPENAME meta::begin<Sequence>::type
+ , BOOST_DEDUCED_TYPENAME meta::end<Sequence>::type>());
+ }
+
+ template <typename Sequence, typename F>
+ inline bool
+ operator()(Sequence& seq, F const& f) const
+ {
+ return detail::any(
+ fusion::begin(seq)
+ , fusion::end(seq)
+ , f
+ , meta::equal_to<
+ BOOST_DEDUCED_TYPENAME meta::begin<Sequence>::type
+ , BOOST_DEDUCED_TYPENAME meta::end<Sequence>::type>());
+ }
+ };
+ }
+
+ function::any const any = function::any();
+}}
+
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/utility/boyer_moore.hpp b/boost/xpressive/detail/utility/boyer_moore.hpp
new file mode 100644
index 0000000000..08ca600b84
--- /dev/null
+++ b/boost/xpressive/detail/utility/boyer_moore.hpp
@@ -0,0 +1,198 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file boyer_moore.hpp
+/// Contains the boyer-moore implementation. Note: this is *not* a general-
+/// purpose boyer-moore implementation. It truncates the search string at
+/// 256 characters, but it is sufficient for the needs of xpressive.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_BOYER_MOORE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_BOYER_MOORE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+
+#include <climits> // for UCHAR_MAX
+#include <cstddef> // for std::ptrdiff_t
+#include <utility> // for std::max
+#include <vector>
+#include <boost/mpl/bool.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// boyer_moore
+//
+template<typename BidiIter, typename Traits>
+struct boyer_moore
+ : noncopyable
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef Traits traits_type;
+ typedef has_fold_case<Traits> case_fold;
+ typedef typename Traits::string_type string_type;
+
+ // initialize the Boyer-Moore search data structure, using the
+ // search sub-sequence to prime the pump.
+ boyer_moore(char_type const *begin, char_type const *end, Traits const &tr, bool icase)
+ : begin_(begin)
+ , last_(begin)
+ , fold_()
+ , find_fun_(
+ icase
+ ? (case_fold() ? &boyer_moore::find_nocase_fold_ : &boyer_moore::find_nocase_)
+ : &boyer_moore::find_
+ )
+ {
+ std::ptrdiff_t const uchar_max = UCHAR_MAX;
+ std::ptrdiff_t diff = std::distance(begin, end);
+ this->length_ = static_cast<unsigned char>((std::min)(diff, uchar_max));
+ std::fill_n(static_cast<unsigned char *>(this->offsets_), uchar_max + 1, this->length_);
+ --this->length_;
+
+ icase ? this->init_(tr, case_fold()) : this->init_(tr, mpl::false_());
+ }
+
+ BidiIter find(BidiIter begin, BidiIter end, Traits const &tr) const
+ {
+ return (this->*this->find_fun_)(begin, end, tr);
+ }
+
+private:
+
+ void init_(Traits const &tr, mpl::false_)
+ {
+ for(unsigned char offset = this->length_; offset; --offset, ++this->last_)
+ {
+ this->offsets_[tr.hash(*this->last_)] = offset;
+ }
+ }
+
+ void init_(Traits const &tr, mpl::true_)
+ {
+ this->fold_.reserve(this->length_ + 1);
+ for(unsigned char offset = this->length_; offset; --offset, ++this->last_)
+ {
+ this->fold_.push_back(tr.fold_case(*this->last_));
+ for(typename string_type::const_iterator beg = this->fold_.back().begin(), end = this->fold_.back().end();
+ beg != end; ++beg)
+ {
+ this->offsets_[tr.hash(*beg)] = offset;
+ }
+ }
+ this->fold_.push_back(tr.fold_case(*this->last_));
+ }
+
+ // case-sensitive Boyer-Moore search
+ BidiIter find_(BidiIter begin, BidiIter end, Traits const &tr) const
+ {
+ typedef typename boost::iterator_difference<BidiIter>::type diff_type;
+ diff_type const endpos = std::distance(begin, end);
+ diff_type offset = static_cast<diff_type>(this->length_);
+
+ for(diff_type curpos = offset; curpos < endpos; curpos += offset)
+ {
+ std::advance(begin, offset);
+
+ char_type const *pat_tmp = this->last_;
+ BidiIter str_tmp = begin;
+
+ for(; tr.translate(*str_tmp) == *pat_tmp; --pat_tmp, --str_tmp)
+ {
+ if(pat_tmp == this->begin_)
+ {
+ return str_tmp;
+ }
+ }
+
+ offset = this->offsets_[tr.hash(tr.translate(*begin))];
+ }
+
+ return end;
+ }
+
+ // case-insensitive Boyer-Moore search
+ BidiIter find_nocase_(BidiIter begin, BidiIter end, Traits const &tr) const
+ {
+ typedef typename boost::iterator_difference<BidiIter>::type diff_type;
+ diff_type const endpos = std::distance(begin, end);
+ diff_type offset = static_cast<diff_type>(this->length_);
+
+ for(diff_type curpos = offset; curpos < endpos; curpos += offset)
+ {
+ std::advance(begin, offset);
+
+ char_type const *pat_tmp = this->last_;
+ BidiIter str_tmp = begin;
+
+ for(; tr.translate_nocase(*str_tmp) == *pat_tmp; --pat_tmp, --str_tmp)
+ {
+ if(pat_tmp == this->begin_)
+ {
+ return str_tmp;
+ }
+ }
+
+ offset = this->offsets_[tr.hash(tr.translate_nocase(*begin))];
+ }
+
+ return end;
+ }
+
+ // case-insensitive Boyer-Moore search with case-folding
+ BidiIter find_nocase_fold_(BidiIter begin, BidiIter end, Traits const &tr) const
+ {
+ typedef typename boost::iterator_difference<BidiIter>::type diff_type;
+ diff_type const endpos = std::distance(begin, end);
+ diff_type offset = static_cast<diff_type>(this->length_);
+
+ for(diff_type curpos = offset; curpos < endpos; curpos += offset)
+ {
+ std::advance(begin, offset);
+
+ string_type const *pat_tmp = &this->fold_.back();
+ BidiIter str_tmp = begin;
+
+ for(; pat_tmp->end() != std::find(pat_tmp->begin(), pat_tmp->end(), *str_tmp);
+ --pat_tmp, --str_tmp)
+ {
+ if(pat_tmp == &this->fold_.front())
+ {
+ return str_tmp;
+ }
+ }
+
+ offset = this->offsets_[tr.hash(*begin)];
+ }
+
+ return end;
+ }
+
+private:
+
+ char_type const *begin_;
+ char_type const *last_;
+ std::vector<string_type> fold_;
+ BidiIter (boyer_moore::*const find_fun_)(BidiIter, BidiIter, Traits const &) const;
+ unsigned char length_;
+ unsigned char offsets_[UCHAR_MAX + 1];
+};
+
+}}} // namespace boost::xpressive::detail
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/utility/chset/basic_chset.hpp b/boost/xpressive/detail/utility/chset/basic_chset.hpp
new file mode 100644
index 0000000000..23316ce417
--- /dev/null
+++ b/boost/xpressive/detail/utility/chset/basic_chset.hpp
@@ -0,0 +1,172 @@
+/*=============================================================================
+ Copyright (c) 2001-2003 Joel de Guzman
+ Copyright (c) 2001-2003 Daniel Nuffer
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+#ifndef BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_HPP_EAN_10_04_2005
+
+///////////////////////////////////////////////////////////////////////////////
+#include <bitset>
+#include <boost/mpl/bool.hpp>
+#include <boost/xpressive/detail/utility/chset/range_run.ipp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////
+//
+// basic_chset: basic character set implementation using range_run
+//
+///////////////////////////////////////////////////////////////////////////
+template<typename Char>
+struct basic_chset
+{
+ basic_chset();
+ basic_chset(basic_chset const &arg);
+
+ bool empty() const;
+ void set(Char from, Char to);
+ template<typename Traits>
+ void set(Char from, Char to, Traits const &tr);
+ void set(Char c);
+ template<typename Traits>
+ void set(Char c, Traits const &tr);
+
+ void clear(Char from, Char to);
+ template<typename Traits>
+ void clear(Char from, Char to, Traits const &tr);
+ void clear(Char c);
+ template<typename Traits>
+ void clear(Char c, Traits const &tr);
+ void clear();
+
+ template<typename Traits>
+ bool test(Char v, Traits const &tr, mpl::false_) const; // case-sensitive
+ template<typename Traits>
+ bool test(Char v, Traits const &tr, mpl::true_) const; // case-insensitive
+
+ void inverse();
+ void swap(basic_chset& x);
+
+ basic_chset &operator |=(basic_chset const &x);
+ basic_chset &operator &=(basic_chset const &x);
+ basic_chset &operator -=(basic_chset const &x);
+ basic_chset &operator ^=(basic_chset const &x);
+
+private:
+ range_run<Char> rr_;
+};
+
+#if(CHAR_BIT == 8)
+
+///////////////////////////////////////////////////////////////////////////
+//
+// basic_chset: specializations for 8 bit chars using std::bitset
+//
+///////////////////////////////////////////////////////////////////////////
+template<typename Char>
+struct basic_chset_8bit
+{
+ basic_chset_8bit();
+ basic_chset_8bit(basic_chset_8bit const &arg);
+
+ bool empty() const;
+
+ void set(Char from, Char to);
+ template<typename Traits>
+ void set(Char from, Char to, Traits const &tr);
+ void set(Char c);
+ template<typename Traits>
+ void set(Char c, Traits const &tr);
+
+ void clear(Char from, Char to);
+ template<typename Traits>
+ void clear(Char from, Char to, Traits const &tr);
+ void clear(Char c);
+ template<typename Traits>
+ void clear(Char c, Traits const &tr);
+ void clear();
+
+ template<typename Traits>
+ bool test(Char v, Traits const &tr, mpl::false_) const; // case-sensitive
+ template<typename Traits>
+ bool test(Char v, Traits const &tr, mpl::true_) const; // case-insensitive
+
+ void inverse();
+ void swap(basic_chset_8bit& x);
+
+ basic_chset_8bit &operator |=(basic_chset_8bit const &x);
+ basic_chset_8bit &operator &=(basic_chset_8bit const &x);
+ basic_chset_8bit &operator -=(basic_chset_8bit const &x);
+ basic_chset_8bit &operator ^=(basic_chset_8bit const &x);
+
+ std::bitset<256> const &base() const;
+
+private:
+ std::bitset<256> bset_; // BUGBUG range-checking slows this down
+};
+
+/////////////////////////////////
+template<>
+struct basic_chset<char>
+ : basic_chset_8bit<char>
+{
+};
+
+/////////////////////////////////
+template<>
+struct basic_chset<signed char>
+ : basic_chset_8bit<signed char>
+{
+};
+
+/////////////////////////////////
+template<>
+struct basic_chset<unsigned char>
+ : basic_chset_8bit<unsigned char>
+{
+};
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// is_narrow_char
+template<typename Char>
+struct is_narrow_char
+ : mpl::false_
+{};
+
+template<>
+struct is_narrow_char<char>
+ : mpl::true_
+{};
+
+template<>
+struct is_narrow_char<signed char>
+ : mpl::true_
+{};
+
+template<>
+struct is_narrow_char<unsigned char>
+ : mpl::true_
+{};
+
+///////////////////////////////////////////////////////////////////////////////
+// helpers
+template<typename Char, typename Traits>
+void set_char(basic_chset<Char> &chset, Char ch, Traits const &tr, bool icase);
+
+template<typename Char, typename Traits>
+void set_range(basic_chset<Char> &chset, Char from, Char to, Traits const &tr, bool icase);
+
+template<typename Char, typename Traits>
+void set_class(basic_chset<Char> &chset, typename Traits::char_class_type char_class, bool no, Traits const &tr);
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/utility/chset/basic_chset.ipp b/boost/xpressive/detail/utility/chset/basic_chset.ipp
new file mode 100644
index 0000000000..71b99133ee
--- /dev/null
+++ b/boost/xpressive/detail/utility/chset/basic_chset.ipp
@@ -0,0 +1,409 @@
+/*=============================================================================
+ Copyright (c) 2001-2003 Joel de Guzman
+ Copyright (c) 2001-2003 Daniel Nuffer
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+#ifndef BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_IPP
+#define BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_IPP
+
+///////////////////////////////////////////////////////////////////////////////
+#include <bitset>
+#include <boost/xpressive/detail/utility/chset/basic_chset.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// basic_chset: character set implementation
+//
+///////////////////////////////////////////////////////////////////////////////
+template<typename Char>
+inline basic_chset<Char>::basic_chset()
+{
+}
+
+//////////////////////////////////
+template<typename Char>
+inline basic_chset<Char>::basic_chset(basic_chset const &arg)
+ : rr_(arg.rr_)
+{
+}
+
+//////////////////////////////////
+template<typename Char>
+inline bool basic_chset<Char>::empty() const
+{
+ return this->rr_.empty();
+}
+
+//////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline bool basic_chset<Char>::test(Char v, Traits const &, mpl::false_) const // case-sensitive
+{
+ return this->rr_.test(v);
+}
+
+//////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline bool basic_chset<Char>::test(Char v, Traits const &tr, mpl::true_) const // case-insensitive
+{
+ return this->rr_.test(v, tr);
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void basic_chset<Char>::set(Char from, Char to)
+{
+ this->rr_.set(range<Char>(from, to));
+}
+
+//////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset<Char>::set(Char from, Char to, Traits const &)
+{
+ this->rr_.set(range<Char>(from, to));
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void basic_chset<Char>::set(Char c)
+{
+ this->rr_.set(range<Char>(c, c));
+}
+
+//////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset<Char>::set(Char c, Traits const &)
+{
+ this->rr_.set(range<Char>(c, c));
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void basic_chset<Char>::clear(Char c)
+{
+ this->rr_.clear(range<Char>(c, c));
+}
+
+//////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset<Char>::clear(Char c, Traits const &)
+{
+ this->rr_.clear(range<Char>(c, c));
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void basic_chset<Char>::clear(Char from, Char to)
+{
+ this->rr_.clear(range<Char>(from, to));
+}
+
+//////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset<Char>::clear(Char from, Char to, Traits const &)
+{
+ this->rr_.clear(range<Char>(from, to));
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void basic_chset<Char>::clear()
+{
+ this->rr_.clear();
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset<Char>::inverse()
+{
+ // BUGBUG is this right? Does this handle icase correctly?
+ basic_chset<Char> inv;
+ inv.set((std::numeric_limits<Char>::min)(), (std::numeric_limits<Char>::max)());
+ inv -= *this;
+ this->swap(inv);
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset<Char>::swap(basic_chset<Char> &that)
+{
+ this->rr_.swap(that.rr_);
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset<Char> &
+basic_chset<Char>::operator |=(basic_chset<Char> const &that)
+{
+ typedef typename range_run<Char>::const_iterator const_iterator;
+ for(const_iterator iter = that.rr_.begin(); iter != that.rr_.end(); ++iter)
+ {
+ this->rr_.set(*iter);
+ }
+ return *this;
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset<Char> &
+basic_chset<Char>::operator &=(basic_chset<Char> const &that)
+{
+ basic_chset<Char> inv;
+ inv.set((std::numeric_limits<Char>::min)(), (std::numeric_limits<Char>::max)());
+ inv -= that;
+ *this -= inv;
+ return *this;
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset<Char> &
+basic_chset<Char>::operator -=(basic_chset<Char> const &that)
+{
+ typedef typename range_run<Char>::const_iterator const_iterator;
+ for(const_iterator iter = that.rr_.begin(); iter != that.rr_.end(); ++iter)
+ {
+ this->rr_.clear(*iter);
+ }
+ return *this;
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset<Char> &
+basic_chset<Char>::operator ^=(basic_chset<Char> const &that)
+{
+ basic_chset bma = that;
+ bma -= *this;
+ *this -= that;
+ *this |= bma;
+ return *this;
+}
+
+#if(CHAR_BIT == 8)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// basic_chset: specializations for 8 bit chars using std::bitset
+//
+///////////////////////////////////////////////////////////////////////////////
+template<typename Char>
+inline basic_chset_8bit<Char>::basic_chset_8bit()
+{
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset_8bit<Char>::basic_chset_8bit(basic_chset_8bit<Char> const &arg)
+ : bset_(arg.bset_)
+{
+}
+
+/////////////////////////////////
+template<typename Char>
+inline bool basic_chset_8bit<Char>::empty() const
+{
+ return !this->bset_.any();
+}
+
+/////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline bool basic_chset_8bit<Char>::test(Char v, Traits const &, mpl::false_) const // case-sensitive
+{
+ return this->bset_.test((unsigned char)v);
+}
+
+/////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline bool basic_chset_8bit<Char>::test(Char v, Traits const &tr, mpl::true_) const // case-insensitive
+{
+ return this->bset_.test((unsigned char)tr.translate_nocase(v));
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset_8bit<Char>::set(Char from, Char to)
+{
+ for(int i = from; i <= to; ++i)
+ {
+ this->bset_.set((unsigned char)i);
+ }
+}
+
+/////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset_8bit<Char>::set(Char from, Char to, Traits const &tr)
+{
+ for(int i = from; i <= to; ++i)
+ {
+ this->bset_.set((unsigned char)tr.translate_nocase((Char)i));
+ }
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset_8bit<Char>::set(Char c)
+{
+ this->bset_.set((unsigned char)c);
+}
+
+/////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset_8bit<Char>::set(Char c, Traits const &tr)
+{
+ this->bset_.set((unsigned char)tr.translate_nocase(c));
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset_8bit<Char>::clear(Char from, Char to)
+{
+ for(int i = from; i <= to; ++i)
+ {
+ this->bset_.reset((unsigned char)i);
+ }
+}
+
+/////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset_8bit<Char>::clear(Char from, Char to, Traits const &tr)
+{
+ for(int i = from; i <= to; ++i)
+ {
+ this->bset_.reset((unsigned char)tr.translate_nocase((Char)i));
+ }
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset_8bit<Char>::clear(Char c)
+{
+ this->bset_.reset((unsigned char)c);
+}
+
+/////////////////////////////////
+template<typename Char>
+template<typename Traits>
+inline void basic_chset_8bit<Char>::clear(Char c, Traits const &tr)
+{
+ this->bset_.reset((unsigned char)tr.tranlsate_nocase(c));
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset_8bit<Char>::clear()
+{
+ this->bset_.reset();
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset_8bit<Char>::inverse()
+{
+ this->bset_.flip();
+}
+
+/////////////////////////////////
+template<typename Char>
+inline void basic_chset_8bit<Char>::swap(basic_chset_8bit<Char> &that)
+{
+ std::swap(this->bset_, that.bset_);
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset_8bit<Char> &
+basic_chset_8bit<Char>::operator |=(basic_chset_8bit<Char> const &that)
+{
+ this->bset_ |= that.bset_;
+ return *this;
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset_8bit<Char> &
+basic_chset_8bit<Char>::operator &=(basic_chset_8bit<Char> const &that)
+{
+ this->bset_ &= that.bset_;
+ return *this;
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset_8bit<Char> &
+basic_chset_8bit<Char>::operator -=(basic_chset_8bit<Char> const &that)
+{
+ this->bset_ &= ~that.bset_;
+ return *this;
+}
+
+/////////////////////////////////
+template<typename Char>
+inline basic_chset_8bit<Char> &
+basic_chset_8bit<Char>::operator ^=(basic_chset_8bit<Char> const &that)
+{
+ this->bset_ ^= that.bset_;
+ return *this;
+}
+
+template<typename Char>
+inline std::bitset<256> const &
+basic_chset_8bit<Char>::base() const
+{
+ return this->bset_;
+}
+
+#endif // if(CHAR_BIT == 8)
+
+
+///////////////////////////////////////////////////////////////////////////////
+// helpers
+template<typename Char, typename Traits>
+inline void set_char(basic_chset<Char> &chset, Char ch, Traits const &tr, bool icase)
+{
+ icase ? chset.set(ch, tr) : chset.set(ch);
+}
+
+template<typename Char, typename Traits>
+inline void set_range(basic_chset<Char> &chset, Char from, Char to, Traits const &tr, bool icase)
+{
+ icase ? chset.set(from, to, tr) : chset.set(from, to);
+}
+
+template<typename Char, typename Traits>
+inline void set_class(basic_chset<Char> &chset, typename Traits::char_class_type char_class, bool no, Traits const &tr)
+{
+ BOOST_MPL_ASSERT_RELATION(1, ==, sizeof(Char));
+ for(std::size_t i = 0; i <= UCHAR_MAX; ++i)
+ {
+ typedef typename std::char_traits<Char>::int_type int_type;
+ Char ch = std::char_traits<Char>::to_char_type(static_cast<int_type>(i));
+ if(no != tr.isctype(ch, char_class))
+ {
+ chset.set(ch);
+ }
+ }
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
+
diff --git a/boost/xpressive/detail/utility/chset/chset.hpp b/boost/xpressive/detail/utility/chset/chset.hpp
new file mode 100644
index 0000000000..c10d466772
--- /dev/null
+++ b/boost/xpressive/detail/utility/chset/chset.hpp
@@ -0,0 +1,165 @@
+///////////////////////////////////////////////////////////////////////////////
+// chset.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_CHSET_CHSET_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_CHSET_CHSET_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <vector>
+#include <boost/call_traits.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+#include <boost/xpressive/detail/utility/chset/basic_chset.ipp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// compound_charset
+//
+template<typename Traits>
+struct compound_charset
+ : private basic_chset<typename Traits::char_type>
+{
+ typedef typename Traits::char_type char_type;
+ typedef basic_chset<char_type> base_type;
+ typedef Traits traits_type;
+ typedef typename Traits::char_class_type char_class_type;
+
+ compound_charset()
+ : base_type()
+ , complement_(false)
+ , has_posix_(false)
+ , posix_yes_()
+ , posix_no_()
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // accessors
+ basic_chset<char_type> const &base() const
+ {
+ return *this;
+ }
+
+ bool is_inverted() const
+ {
+ return this->complement_;
+ }
+
+ char_class_type posix_yes() const
+ {
+ return this->posix_yes_;
+ }
+
+ std::vector<char_class_type> const &posix_no() const
+ {
+ return this->posix_no_;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // complement
+ void inverse()
+ {
+ this->complement_ = !this->complement_;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // set
+ void set_char(char_type ch, Traits const &tr, bool icase)
+ {
+ icase ? this->base_type::set(ch, tr) : this->base_type::set(ch);
+ }
+
+ void set_range(char_type from, char_type to, Traits const &tr, bool icase)
+ {
+ icase ? this->base_type::set(from, to, tr) : this->base_type::set(from, to);
+ }
+
+ void set_class(char_class_type const &m, bool no)
+ {
+ this->has_posix_ = true;
+
+ if(no)
+ {
+ this->posix_no_.push_back(m);
+ }
+ else
+ {
+ this->posix_yes_ |= m;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // test
+ template<typename ICase>
+ bool test(char_type ch, Traits const &tr, ICase) const
+ {
+ return this->complement_ !=
+ (this->base_type::test(ch, tr, ICase()) ||
+ (this->has_posix_ && this->test_posix(ch, tr)));
+ }
+
+private:
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // not_posix_pred
+ struct not_posix_pred
+ {
+ char_type ch_;
+ Traits const *traits_ptr_;
+
+ bool operator ()(typename call_traits<char_class_type>::param_type m) const
+ {
+ return !this->traits_ptr_->isctype(this->ch_, m);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // test_posix
+ bool test_posix(char_type ch, Traits const &tr) const
+ {
+ not_posix_pred const pred = {ch, &tr};
+ return tr.isctype(ch, this->posix_yes_)
+ || any(this->posix_no_.begin(), this->posix_no_.end(), pred);
+ }
+
+ bool complement_;
+ bool has_posix_;
+ char_class_type posix_yes_;
+ std::vector<char_class_type> posix_no_;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// helpers
+template<typename Char, typename Traits>
+inline void set_char(compound_charset<Traits> &chset, Char ch, Traits const &tr, bool icase)
+{
+ chset.set_char(ch, tr, icase);
+}
+
+template<typename Char, typename Traits>
+inline void set_range(compound_charset<Traits> &chset, Char from, Char to, Traits const &tr, bool icase)
+{
+ chset.set_range(from, to, tr, icase);
+}
+
+template<typename Traits>
+inline void set_class(compound_charset<Traits> &chset, typename Traits::char_class_type char_class, bool no, Traits const &)
+{
+ chset.set_class(char_class, no);
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
+
diff --git a/boost/xpressive/detail/utility/chset/range_run.hpp b/boost/xpressive/detail/utility/chset/range_run.hpp
new file mode 100644
index 0000000000..f7d6adde15
--- /dev/null
+++ b/boost/xpressive/detail/utility/chset/range_run.hpp
@@ -0,0 +1,102 @@
+/*=============================================================================
+ Copyright (c) 2001-2003 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+#ifndef BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_HPP_EAN_10_04_2005
+
+///////////////////////////////////////////////////////////////////////////////
+#include <vector>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////
+//
+// range class
+//
+// Implements a closed range of values. This class is used in
+// the implementation of the range_run class.
+//
+// { Low level implementation detail }
+// { Not to be confused with spirit::range }
+//
+///////////////////////////////////////////////////////////////////////////
+template<typename Char>
+struct range
+{
+ range(Char first, Char last);
+
+ bool is_valid() const;
+ bool includes(Char v) const;
+ bool includes(range const &r) const;
+ bool overlaps(range const &r) const;
+ void merge(range const &r);
+
+ Char first_;
+ Char last_;
+};
+
+//////////////////////////////////
+template<typename Char>
+struct range_compare
+{
+ bool operator()(range<Char> const &x, range<Char> const &y) const
+ {
+ return x.first_ < y.first_;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////
+//
+// range_run
+//
+// An implementation of a sparse bit (boolean) set. The set uses
+// a sorted vector of disjoint ranges. This class implements the
+// bare minimum essentials from which the full range of set
+// operators can be implemented. The set is constructed from
+// ranges. Internally, adjacent or overlapping ranges are
+// coalesced.
+//
+// range_runs are very space-economical in situations where there
+// are lots of ranges and a few individual disjoint values.
+// Searching is O(log n) where n is the number of ranges.
+//
+// { Low level implementation detail }
+//
+///////////////////////////////////////////////////////////////////////////
+template<typename Char>
+struct range_run
+{
+ typedef range<Char> range_type;
+ typedef std::vector<range_type> run_type;
+ typedef typename run_type::iterator iterator;
+ typedef typename run_type::const_iterator const_iterator;
+
+ void swap(range_run& rr);
+ bool empty() const;
+ bool test(Char v) const;
+ template<typename Traits>
+ bool test(Char v, Traits const &tr) const;
+ void set(range_type const &r);
+ void clear(range_type const &r);
+ void clear();
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+private:
+ void merge(iterator iter, range_type const &r);
+
+ run_type run_;
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
+
diff --git a/boost/xpressive/detail/utility/chset/range_run.ipp b/boost/xpressive/detail/utility/chset/range_run.ipp
new file mode 100644
index 0000000000..dfd321f786
--- /dev/null
+++ b/boost/xpressive/detail/utility/chset/range_run.ipp
@@ -0,0 +1,235 @@
+/*=============================================================================
+ Copyright (c) 2001-2003 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+#ifndef BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_IPP
+#define BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_IPP
+
+///////////////////////////////////////////////////////////////////////////////
+#include <algorithm> // for std::lower_bound
+#include <boost/limits.hpp>
+#include <boost/assert.hpp>
+#include <boost/xpressive/detail/utility/chset/range_run.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////
+//
+// range class implementation
+//
+///////////////////////////////////////////////////////////////////////
+template<typename Char>
+inline range<Char>::range(Char first, Char last)
+ : first_(first)
+ , last_(last)
+{
+}
+
+//////////////////////////////////
+template<typename Char>
+inline bool range<Char>::is_valid() const
+{
+ return this->first_ <= this->last_;
+}
+
+//////////////////////////////////
+template<typename Char>
+inline bool range<Char>::includes(range<Char> const &r) const
+{
+ return (this->first_ <= r.first_) && (this->last_ >= r.last_);
+}
+
+//////////////////////////////////
+template<typename Char>
+inline bool range<Char>::includes(Char v) const
+{
+ return (this->first_ <= v) && (this->last_ >= v);
+}
+
+//////////////////////////////////
+template<typename Char>
+inline bool range<Char>::overlaps(range<Char> const &r) const
+{
+ Char decr_first = (std::min)(this->first_, Char(this->first_-1));
+ Char incr_last = (std::max)(this->last_, Char(this->last_+1));
+
+ return (decr_first <= r.last_) && (incr_last >= r.first_);
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void range<Char>::merge(range<Char> const &r)
+{
+ this->first_ = (std::min)(this->first_, r.first_);
+ this->last_ = (std::max)(this->last_, r.last_);
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// range_run class implementation
+//
+///////////////////////////////////////////////////////////////////////
+template<typename Char>
+inline bool range_run<Char>::empty() const
+{
+ return this->run_.empty();
+}
+
+template<typename Char>
+inline bool range_run<Char>::test(Char v) const
+{
+ if(this->run_.empty())
+ {
+ return false;
+ }
+
+ const_iterator iter = std::lower_bound(
+ this->run_.begin()
+ , this->run_.end()
+ , range<Char>(v, v)
+ , range_compare<Char>()
+ );
+
+ return (iter != this->run_.end() && iter->includes(v))
+ || (iter != this->run_.begin() && (--iter)->includes(v));
+}
+
+template<typename Char>
+template<typename Traits>
+inline bool range_run<Char>::test(Char v, Traits const &tr) const
+{
+ const_iterator begin = this->run_.begin();
+ const_iterator end = this->run_.end();
+
+ for(; begin != end; ++begin)
+ {
+ if(tr.in_range_nocase(begin->first_, begin->last_, v))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void range_run<Char>::swap(range_run<Char> &rr)
+{
+ this->run_.swap(rr.run_);
+}
+
+//////////////////////////////////
+template<typename Char>
+void range_run<Char>::merge(iterator iter, range<Char> const &r)
+{
+ BOOST_ASSERT(iter != this->run_.end());
+ iter->merge(r);
+
+ iterator i = iter;
+ while(++i != this->run_.end() && iter->overlaps(*i))
+ {
+ iter->merge(*i);
+ }
+
+ this->run_.erase(++iter, i);
+}
+
+//////////////////////////////////
+template<typename Char>
+void range_run<Char>::set(range<Char> const &r)
+{
+ BOOST_ASSERT(r.is_valid());
+ if(!this->run_.empty())
+ {
+ iterator iter = std::lower_bound(this->run_.begin(), this->run_.end(), r, range_compare<Char>());
+
+ if((iter != this->run_.end() && iter->includes(r)) ||
+ (iter != this->run_.begin() && (iter - 1)->includes(r)))
+ {
+ return;
+ }
+ else if(iter != this->run_.begin() && (iter - 1)->overlaps(r))
+ {
+ this->merge(--iter, r);
+ }
+ else if(iter != this->run_.end() && iter->overlaps(r))
+ {
+ this->merge(iter, r);
+ }
+ else
+ {
+ this->run_.insert(iter, r);
+ }
+ }
+ else
+ {
+ this->run_.push_back(r);
+ }
+}
+
+//////////////////////////////////
+template<typename Char>
+void range_run<Char>::clear(range<Char> const &r)
+{
+ BOOST_ASSERT(r.is_valid());
+ if(!this->run_.empty())
+ {
+ iterator iter = std::lower_bound(this->run_.begin(), this->run_.end(), r, range_compare<Char>());
+ iterator left_iter;
+
+ if((iter != this->run_.begin()) &&
+ (left_iter = (iter - 1))->includes(r.first_))
+ {
+ if(left_iter->last_ > r.last_)
+ {
+ Char save_last = left_iter->last_;
+ left_iter->last_ = r.first_-1;
+ this->run_.insert(iter, range<Char>(r.last_+1, save_last));
+ return;
+ }
+ else
+ {
+ left_iter->last_ = r.first_-1;
+ }
+ }
+
+ iterator i = iter;
+ for(; i != this->run_.end() && r.includes(*i); ++i) {}
+ if(i != this->run_.end() && i->includes(r.last_))
+ {
+ i->first_ = r.last_+1;
+ }
+ this->run_.erase(iter, i);
+ }
+}
+
+//////////////////////////////////
+template<typename Char>
+inline void range_run<Char>::clear()
+{
+ this->run_.clear();
+}
+
+//////////////////////////////////
+template<typename Char>
+inline typename range_run<Char>::const_iterator range_run<Char>::begin() const
+{
+ return this->run_.begin();
+}
+
+//////////////////////////////////
+template<typename Char>
+inline typename range_run<Char>::const_iterator range_run<Char>::end() const
+{
+ return this->run_.end();
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/utility/cons.hpp b/boost/xpressive/detail/utility/cons.hpp
new file mode 100644
index 0000000000..50c43838b9
--- /dev/null
+++ b/boost/xpressive/detail/utility/cons.hpp
@@ -0,0 +1,309 @@
+///////////////////////////////////////////////////////////////////////////////
+// cons.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
+
+#include <boost/version.hpp>
+
+#if BOOST_VERSION >= 103300
+
+// In Boost 1.33+, we have a cons list in Fusion, so just include it.
+
+# if BOOST_VERSION >= 103500
+# include <boost/fusion/include/cons.hpp> // Boost 1.35+ has Fusion2
+# else
+# include <boost/spirit/fusion/sequence/cons.hpp> // Fusion1
+# endif
+
+#else
+
+// For earlier versions of Boost, put the definition of cons here
+# include <boost/call_traits.hpp>
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/eval_if.hpp>
+# include <boost/mpl/identity.hpp>
+# include <boost/type_traits/is_const.hpp>
+# include <boost/type_traits/add_const.hpp>
+# include <boost/type_traits/add_reference.hpp>
+# include <boost/spirit/fusion/detail/config.hpp>
+# include <boost/spirit/fusion/detail/access.hpp>
+# include <boost/spirit/fusion/iterator/next.hpp>
+# include <boost/spirit/fusion/iterator/equal_to.hpp>
+# include <boost/spirit/fusion/iterator/as_fusion_iterator.hpp>
+# include <boost/spirit/fusion/iterator/detail/iterator_base.hpp>
+# include <boost/spirit/fusion/sequence/begin.hpp>
+# include <boost/spirit/fusion/sequence/end.hpp>
+# include <boost/spirit/fusion/sequence/as_fusion_sequence.hpp>
+# include <boost/spirit/fusion/sequence/detail/sequence_base.hpp>
+
+namespace boost { namespace fusion
+{
+ struct nil;
+
+ struct cons_tag;
+
+ template <typename Car, typename Cdr>
+ struct cons;
+
+ struct cons_iterator_tag;
+
+ template <typename Cons>
+ struct cons_iterator;
+
+ namespace cons_detail
+ {
+ template <typename Iterator>
+ struct deref_traits_impl
+ {
+ typedef typename Iterator::cons_type cons_type;
+ typedef typename cons_type::car_type value_type;
+
+ typedef typename mpl::eval_if<
+ is_const<cons_type>
+ , add_reference<typename add_const<value_type>::type>
+ , add_reference<value_type> >::type
+ type;
+
+ static type
+ call(Iterator const& i)
+ {
+ return detail::ref(i.cons.car);
+ }
+ };
+
+ template <typename Iterator>
+ struct next_traits_impl
+ {
+ typedef typename Iterator::cons_type cons_type;
+ typedef typename cons_type::cdr_type cdr_type;
+
+ typedef cons_iterator<
+ typename mpl::eval_if<
+ is_const<cons_type>
+ , add_const<cdr_type>
+ , mpl::identity<cdr_type>
+ >::type>
+ type;
+
+ static type
+ call(Iterator const& i)
+ {
+ return type(detail::ref(i.cons.cdr));
+ }
+ };
+
+ template <typename Iterator>
+ struct value_traits_impl
+ {
+ typedef typename Iterator::cons_type cons_type;
+ typedef typename cons_type::car_type type;
+ };
+
+ template <typename Cons>
+ struct begin_traits_impl
+ {
+ typedef cons_iterator<Cons> type;
+
+ static type
+ call(Cons& t)
+ {
+ return type(t);
+ }
+ };
+
+ template <typename Cons>
+ struct end_traits_impl
+ {
+ typedef cons_iterator<
+ typename mpl::if_<is_const<Cons>, nil const, nil>::type>
+ type;
+
+ static type
+ call(Cons& t)
+ {
+ FUSION_RETURN_DEFAULT_CONSTRUCTED;
+ }
+ };
+ } // namespace cons_detail
+
+ namespace meta
+ {
+ template <typename Tag>
+ struct deref_impl;
+
+ template <>
+ struct deref_impl<cons_iterator_tag>
+ {
+ template <typename Iterator>
+ struct apply : cons_detail::deref_traits_impl<Iterator> {};
+ };
+
+ template <typename Tag>
+ struct next_impl;
+
+ template <>
+ struct next_impl<cons_iterator_tag>
+ {
+ template <typename Iterator>
+ struct apply : cons_detail::next_traits_impl<Iterator> {};
+ };
+
+ template <typename Tag>
+ struct value_impl;
+
+ template <>
+ struct value_impl<cons_iterator_tag>
+ {
+ template <typename Iterator>
+ struct apply : cons_detail::value_traits_impl<Iterator> {};
+ };
+
+ template <typename Tag>
+ struct begin_impl;
+
+ template <>
+ struct begin_impl<cons_tag>
+ {
+ template <typename Sequence>
+ struct apply : cons_detail::begin_traits_impl<Sequence>
+ {};
+ };
+
+ template <typename Tag>
+ struct end_impl;
+
+ template <>
+ struct end_impl<cons_tag>
+ {
+ template <typename Sequence>
+ struct apply : cons_detail::end_traits_impl<Sequence>
+ {};
+ };
+ } // namespace meta
+
+ template <typename Cons = nil>
+ struct cons_iterator : iterator_base<cons_iterator<Cons> >
+ {
+ typedef cons_iterator_tag tag;
+ typedef Cons cons_type;
+
+ explicit cons_iterator(cons_type& cons_)
+ : cons(cons_) {}
+
+ cons_type& cons;
+ };
+
+ template <>
+ struct cons_iterator<nil> : iterator_base<cons_iterator<nil> >
+ {
+ typedef cons_iterator_tag tag;
+ typedef nil cons_type;
+ cons_iterator() {}
+ explicit cons_iterator(nil const&) {}
+ };
+
+ template <>
+ struct cons_iterator<nil const> : iterator_base<cons_iterator<nil const> >
+ {
+ typedef cons_iterator_tag tag;
+ typedef nil const cons_type;
+ cons_iterator() {}
+ explicit cons_iterator(nil const&) {}
+ };
+
+ struct nil : sequence_base<nil>
+ {
+ typedef cons_tag tag;
+ typedef void_t car_type;
+ typedef void_t cdr_type;
+ };
+
+ template <typename Car, typename Cdr = nil>
+ struct cons : sequence_base<cons<Car,Cdr> >
+ {
+ typedef cons_tag tag;
+ typedef typename call_traits<Car>::value_type car_type;
+ typedef Cdr cdr_type;
+
+ cons()
+ : car(), cdr() {}
+
+ explicit cons(
+ typename call_traits<Car>::param_type car_
+ , typename call_traits<Cdr>::param_type cdr_ = Cdr())
+ : car(car_), cdr(cdr_) {}
+
+ car_type car;
+ cdr_type cdr;
+ };
+
+ template <typename Car>
+ inline cons<Car>
+ make_cons(Car const& car)
+ {
+ return cons<Car>(car);
+ }
+
+ template <typename Car, typename Cdr>
+ inline cons<Car, Cdr>
+ make_cons(Car const& car, Cdr const& cdr)
+ {
+ return cons<Car, Cdr>(car, cdr);
+ }
+}} // namespace boost::fusion
+
+namespace boost { namespace mpl
+{
+ template <typename Tag>
+ struct begin_impl;
+
+ template <typename Tag>
+ struct end_impl;
+
+ template <>
+ struct begin_impl<fusion::cons_tag>
+ : fusion::meta::begin_impl<fusion::cons_tag>
+ {
+ };
+
+ template <>
+ struct end_impl<fusion::cons_tag>
+ : fusion::meta::end_impl<fusion::cons_tag>
+ {
+ };
+
+}} // namespace boost::mpl
+
+#endif
+
+// Before Boost v1.33.1, Fusion cons lists were not valid MPL sequences.
+#if BOOST_VERSION < 103301
+namespace boost { namespace mpl
+{
+ template<typename Iterator>
+ struct next;
+
+ template<typename Cons>
+ struct next<fusion::cons_iterator<Cons> >
+ : fusion::cons_detail::next_traits_impl<fusion::cons_iterator<Cons> >
+ {
+ };
+
+ template<typename Iterator>
+ struct deref;
+
+ template<typename Cons>
+ struct deref<fusion::cons_iterator<Cons> >
+ : fusion::cons_detail::value_traits_impl<fusion::cons_iterator<Cons> >
+ {
+ };
+
+}} // namespace boost::mpl
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/utility/counted_base.hpp b/boost/xpressive/detail/utility/counted_base.hpp
new file mode 100644
index 0000000000..406c69db17
--- /dev/null
+++ b/boost/xpressive/detail/utility/counted_base.hpp
@@ -0,0 +1,84 @@
+//////////////////////////////////////////////////////////////////////////////
+// (c) Copyright Andreas Huber Doenni 2002-2005, Eric Niebler 2006
+// Distributed under the Boost Software License, Version 1.0. (See accompany-
+// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_COUNTED_BASE_HPP_EAN_04_16_2006
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_COUNTED_BASE_HPP_EAN_04_16_2006
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/detail/atomic_count.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+ template<typename Derived>
+ struct counted_base_access;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // counted_base
+ template<typename Derived>
+ struct counted_base
+ {
+ long use_count() const
+ {
+ return this->count_;
+ }
+
+ protected:
+ counted_base()
+ : count_(0)
+ {
+ }
+
+ counted_base(counted_base<Derived> const &)
+ : count_(0)
+ {
+ }
+
+ counted_base &operator =(counted_base<Derived> const &)
+ {
+ return *this;
+ }
+
+ private:
+ friend struct counted_base_access<Derived>;
+ mutable boost::detail::atomic_count count_;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+ // counted_base_access
+ template<typename Derived>
+ struct counted_base_access
+ {
+ static void add_ref(counted_base<Derived> const *that)
+ {
+ ++that->count_;
+ }
+
+ static void release(counted_base<Derived> const *that)
+ {
+ BOOST_ASSERT(0 < that->count_);
+ if(0 == --that->count_)
+ {
+ boost::checked_delete(static_cast<Derived const *>(that));
+ }
+ }
+ };
+
+ template<typename Derived>
+ inline void intrusive_ptr_add_ref(counted_base<Derived> const *that)
+ {
+ counted_base_access<Derived>::add_ref(that);
+ }
+
+ template<typename Derived>
+ inline void intrusive_ptr_release(counted_base<Derived> const *that)
+ {
+ counted_base_access<Derived>::release(that);
+ }
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/utility/dont_care.hpp b/boost/xpressive/detail/utility/dont_care.hpp
new file mode 100644
index 0000000000..3e7a7a5f91
--- /dev/null
+++ b/boost/xpressive/detail/utility/dont_care.hpp
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// dont_care.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_DONT_CARE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_DONT_CARE_HPP_EAN_10_04_2005
+
+namespace boost { namespace xpressive { namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // for function arguments we don't care about
+ struct dont_care
+ {
+ dont_care() {}
+
+ template<typename T>
+ dont_care(T const &) {}
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/utility/hash_peek_bitset.hpp b/boost/xpressive/detail/utility/hash_peek_bitset.hpp
new file mode 100644
index 0000000000..56b41fc117
--- /dev/null
+++ b/boost/xpressive/detail/utility/hash_peek_bitset.hpp
@@ -0,0 +1,178 @@
+///////////////////////////////////////////////////////////////////////////////
+// hash_peek_bitset.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4100) // unreferenced formal parameter
+# pragma warning(disable : 4127) // conditional expression constant
+#endif
+
+#include <bitset>
+#include <string> // for std::char_traits
+#include <boost/xpressive/detail/utility/chset/basic_chset.ipp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// hash_peek_bitset
+//
+template<typename Char>
+struct hash_peek_bitset
+{
+ typedef Char char_type;
+ typedef typename std::char_traits<char_type>::int_type int_type;
+
+ hash_peek_bitset()
+ : icase_(false)
+ , bset_()
+ {
+ }
+
+ std::size_t count() const
+ {
+ return this->bset_.count();
+ }
+
+ void set_all()
+ {
+ this->icase_ = false;
+ this->bset_.set();
+ }
+
+ template<typename Traits>
+ void set_char(char_type ch, bool icase, Traits const &tr)
+ {
+ if(this->test_icase_(icase))
+ {
+ ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
+ this->bset_.set(tr.hash(ch));
+ }
+ }
+
+ template<typename Traits>
+ void set_range(char_type from, char_type to, bool no, bool icase, Traits const &tr)
+ {
+ int_type ifrom = std::char_traits<char_type>::to_int_type(from);
+ int_type ito = std::char_traits<char_type>::to_int_type(to);
+ BOOST_ASSERT(ifrom <= ito);
+ // bound the computational complexity. BUGBUG could set the inverse range
+ if(no || 256 < (ito - ifrom))
+ {
+ this->set_all();
+ }
+ else if(this->test_icase_(icase))
+ {
+ for(int_type i = ifrom; i <= ito; ++i)
+ {
+ char_type ch = std::char_traits<char_type>::to_char_type(i);
+ ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
+ this->bset_.set(tr.hash(ch));
+ }
+ }
+ }
+
+ template<typename Traits>
+ void set_class(typename Traits::char_class_type char_class, bool no, Traits const &tr)
+ {
+ if(1 != sizeof(char_type))
+ {
+ // wide character set, no efficient way of filling in the bitset, so set them all to 1
+ this->set_all();
+ }
+ else
+ {
+ for(std::size_t i = 0; i <= UCHAR_MAX; ++i)
+ {
+ char_type ch = std::char_traits<char_type>::to_char_type(static_cast<int_type>(i));
+ if(no != tr.isctype(ch, char_class))
+ {
+ this->bset_.set(i);
+ }
+ }
+ }
+ }
+
+ void set_bitset(hash_peek_bitset<Char> const &that)
+ {
+ if(this->test_icase_(that.icase()))
+ {
+ this->bset_ |= that.bset_;
+ }
+ }
+
+ void set_charset(basic_chset_8bit<Char> const &that, bool icase)
+ {
+ if(this->test_icase_(icase))
+ {
+ this->bset_ |= that.base();
+ }
+ }
+
+ bool icase() const
+ {
+ return this->icase_;
+ }
+
+ template<typename Traits>
+ bool test(char_type ch, Traits const &tr) const
+ {
+ ch = this->icase_ ? tr.translate_nocase(ch) : tr.translate(ch);
+ return this->bset_.test(tr.hash(ch));
+ }
+
+ template<typename Traits>
+ bool test(char_type ch, Traits const &tr, mpl::false_) const
+ {
+ BOOST_ASSERT(!this->icase_);
+ return this->bset_.test(tr.hash(tr.translate(ch)));
+ }
+
+ template<typename Traits>
+ bool test(char_type ch, Traits const &tr, mpl::true_) const
+ {
+ BOOST_ASSERT(this->icase_);
+ return this->bset_.test(tr.hash(tr.translate_nocase(ch)));
+ }
+
+private:
+
+ // Make sure all sub-expressions being merged have the same case-sensitivity
+ bool test_icase_(bool icase)
+ {
+ std::size_t count = this->bset_.count();
+
+ if(256 == count)
+ {
+ return false; // all set already, nothing to do
+ }
+ else if(0 != count && this->icase_ != icase)
+ {
+ this->set_all(); // icase mismatch! set all and bail
+ return false;
+ }
+
+ this->icase_ = icase;
+ return true;
+ }
+
+ bool icase_;
+ std::bitset<256> bset_;
+};
+
+}}} // namespace boost::xpressive::detail
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/utility/ignore_unused.hpp b/boost/xpressive/detail/utility/ignore_unused.hpp
new file mode 100644
index 0000000000..e7d3139f8a
--- /dev/null
+++ b/boost/xpressive/detail/utility/ignore_unused.hpp
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// ignore_unused.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_IGNORE_UNUSED_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_IGNORE_UNUSED_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include "boost/proto/detail/ignore_unused.hpp"
+
+namespace boost { namespace xpressive { namespace detail
+{
+ using boost::proto::detail::ignore_unused;
+}}}
+
+#endif
+
diff --git a/boost/xpressive/detail/utility/literals.hpp b/boost/xpressive/detail/utility/literals.hpp
new file mode 100644
index 0000000000..67c9a42807
--- /dev/null
+++ b/boost/xpressive/detail/utility/literals.hpp
@@ -0,0 +1,85 @@
+///////////////////////////////////////////////////////////////////////////////
+// literals.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_LITERALS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_LITERALS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
+#include <boost/cstdint.hpp> // for BOOST_STATIC_CONSTANT
+#include <boost/detail/workaround.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// char_literal
+//
+template<typename Char, boost::intmax_t Ch, boost::intmax_t Wch>
+struct char_literal;
+
+template<typename Char, boost::intmax_t Ch>
+struct char_literal<Char, Ch, Ch>
+{
+ BOOST_STATIC_CONSTANT(boost::intmax_t, value = Ch);
+};
+
+#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+template<typename Char, boost::intmax_t Ch>
+boost::intmax_t const char_literal<Char, Ch, Ch>::value;
+#endif
+
+template<typename Ch>
+struct string_literal;
+
+template<>
+struct string_literal<char>
+{
+ static char const *pick(char const *cstr, wchar_t const *)
+ {
+ return cstr;
+ }
+
+ static char pick(char ch, wchar_t)
+ {
+ return ch;
+ }
+};
+
+template<>
+struct string_literal<wchar_t>
+{
+ static wchar_t const *pick(char const *, wchar_t const *cstr)
+ {
+ return cstr;
+ }
+
+ static wchar_t pick(char, wchar_t ch)
+ {
+ return ch;
+ }
+};
+
+#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
+
+# define BOOST_XPR_CHAR_(Char, ch) ch
+# define BOOST_XPR_CSTR_(Char, st) boost::xpressive::detail::string_literal<Char>::pick(st, L##st)
+
+#else
+
+# define BOOST_XPR_CHAR_(Char, ch) boost::xpressive::detail::char_literal<Char, ch, L##ch>::value
+# define BOOST_XPR_CSTR_(Char, st) boost::xpressive::detail::string_literal<Char>::pick(st, L##st)
+
+#endif
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/utility/never_true.hpp b/boost/xpressive/detail/utility/never_true.hpp
new file mode 100644
index 0000000000..8c15ee4ff0
--- /dev/null
+++ b/boost/xpressive/detail/utility/never_true.hpp
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// never_true.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_NEVER_TRUE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_NEVER_TRUE_HPP_EAN_10_04_2005
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ // for use in static asserts
+ template<typename T>
+ struct never_true
+ : mpl::false_
+ {
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/utility/save_restore.hpp b/boost/xpressive/detail/utility/save_restore.hpp
new file mode 100644
index 0000000000..a9c2a2407e
--- /dev/null
+++ b/boost/xpressive/detail/utility/save_restore.hpp
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////////////////////
+// save_restore.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_SAVE_RESTORE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_SAVE_RESTORE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/noncopyable.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ template<typename T>
+ struct save_restore
+ : private noncopyable
+ {
+ explicit save_restore(T &t)
+ : ref(t)
+ , val(t)
+ {
+ }
+
+ save_restore(T &t, T const &n)
+ : ref(t)
+ , val(t)
+ {
+ this->ref = n;
+ }
+
+ ~save_restore()
+ {
+ this->ref = this->val;
+ }
+
+ void restore()
+ {
+ this->ref = this->val;
+ }
+
+ private:
+ T &ref;
+ T const val;
+ };
+
+}}}
+
+#endif
diff --git a/boost/xpressive/detail/utility/sequence_stack.hpp b/boost/xpressive/detail/utility/sequence_stack.hpp
new file mode 100644
index 0000000000..aa251b64a8
--- /dev/null
+++ b/boost/xpressive/detail/utility/sequence_stack.hpp
@@ -0,0 +1,259 @@
+///////////////////////////////////////////////////////////////////////////////
+// sequence_stack.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_SEQUENCE_STACK_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_SEQUENCE_STACK_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4127) // conditional expression constant
+#endif
+
+#include <algorithm>
+#include <functional>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+struct fill_t {} const fill = {};
+
+//////////////////////////////////////////////////////////////////////////
+// sequence_stack
+//
+// For storing a stack of sequences of type T, where each sequence
+// is guaranteed to be stored in contiguous memory.
+template<typename T>
+struct sequence_stack
+{
+private:
+ static T *allocate(std::size_t size, T const &t)
+ {
+ std::size_t i = 0;
+ T *p = (T *)::operator new(size * sizeof(T));
+ try
+ {
+ for(; i < size; ++i)
+ ::new((void *)(p+i)) T(t);
+ }
+ catch(...)
+ {
+ deallocate(p, i);
+ throw;
+ }
+ return p;
+ }
+
+ static void deallocate(T *p, std::size_t i)
+ {
+ while(i-- > 0)
+ (p+i)->~T();
+ ::operator delete(p);
+ }
+
+ struct chunk
+ {
+ chunk(std::size_t size, T const &t, std::size_t count, chunk *back, chunk *next)
+ : begin_(allocate(size, t))
+ , curr_(begin_ + count)
+ , end_(begin_ + size)
+ , back_(back)
+ , next_(next)
+ {
+ if(this->back_)
+ this->back_->next_ = this;
+ if(this->next_)
+ this->next_->back_ = this;
+ }
+
+ ~chunk()
+ {
+ deallocate(this->begin_, this->size());
+ }
+
+ std::size_t size() const
+ {
+ return static_cast<std::size_t>(this->end_ - this->begin_);
+ }
+
+ T *const begin_, *curr_, *const end_;
+ chunk *back_, *next_;
+
+ private:
+ chunk &operator =(chunk const &);
+ };
+
+ chunk *current_chunk_;
+
+ // Cache these for faster access
+ T *begin_;
+ T *curr_;
+ T *end_;
+
+ T *grow_(std::size_t count, T const &t)
+ {
+ if(this->current_chunk_)
+ {
+ // write the cached value of current into the expr.
+ // OK to do this even if later statements throw.
+ this->current_chunk_->curr_ = this->curr_;
+
+ // Do we have a expr with enough available memory already?
+ if(this->current_chunk_->next_ && count <= this->current_chunk_->next_->size())
+ {
+ this->current_chunk_ = this->current_chunk_->next_;
+ this->curr_ = this->current_chunk_->curr_ = this->current_chunk_->begin_ + count;
+ this->end_ = this->current_chunk_->end_;
+ this->begin_ = this->current_chunk_->begin_;
+ std::fill_n(this->begin_, count, t);
+ return this->begin_;
+ }
+
+ // grow exponentially
+ std::size_t new_size = (std::max)(count, static_cast<std::size_t>(this->current_chunk_->size() * 1.5));
+
+ // Create a new expr and insert it into the list
+ this->current_chunk_ = new chunk(new_size, t, count, this->current_chunk_, this->current_chunk_->next_);
+ }
+ else
+ {
+ // first chunk is 256
+ std::size_t new_size = (std::max)(count, static_cast<std::size_t>(256U));
+
+ // Create a new expr and insert it into the list
+ this->current_chunk_ = new chunk(new_size, t, count, 0, 0);
+ }
+
+ this->begin_ = this->current_chunk_->begin_;
+ this->curr_ = this->current_chunk_->curr_;
+ this->end_ = this->current_chunk_->end_;
+ return this->begin_;
+ }
+
+ void unwind_chunk_()
+ {
+ // write the cached value of curr_ into current_chunk_
+ this->current_chunk_->curr_ = this->begin_;
+ // make the previous chunk the current
+ this->current_chunk_ = this->current_chunk_->back_;
+
+ // update the cache
+ this->begin_ = this->current_chunk_->begin_;
+ this->curr_ = this->current_chunk_->curr_;
+ this->end_ = this->current_chunk_->end_;
+ }
+
+ bool in_current_chunk(T *ptr) const
+ {
+ return !std::less<void*>()(ptr, this->begin_) && std::less<void*>()(ptr, this->end_);
+ }
+
+public:
+ sequence_stack()
+ : current_chunk_(0)
+ , begin_(0)
+ , curr_(0)
+ , end_(0)
+ {
+ }
+
+ ~sequence_stack()
+ {
+ this->clear();
+ }
+
+ // walk to the front of the linked list
+ void unwind()
+ {
+ if(this->current_chunk_)
+ {
+ while(this->current_chunk_->back_)
+ {
+ this->current_chunk_->curr_ = this->current_chunk_->begin_;
+ this->current_chunk_ = this->current_chunk_->back_;
+ }
+
+ this->begin_ = this->curr_ = this->current_chunk_->curr_ = this->current_chunk_->begin_;
+ this->end_ = this->current_chunk_->end_;
+ }
+ }
+
+ void clear()
+ {
+ // walk to the front of the list
+ this->unwind();
+
+ // delete the list
+ for(chunk *next; this->current_chunk_; this->current_chunk_ = next)
+ {
+ next = this->current_chunk_->next_;
+ delete this->current_chunk_;
+ }
+
+ this->begin_ = this->curr_ = this->end_ = 0;
+ }
+
+ T *push_sequence(std::size_t count, T const &t)
+ {
+ // This is the ptr to return
+ T *ptr = this->curr_;
+
+ // Advance the high-water mark
+ this->curr_ += count;
+
+ // Check to see if we have overflowed this buffer
+ if(std::less<void*>()(this->end_, this->curr_))
+ {
+ // oops, back this out.
+ this->curr_ = ptr;
+
+ // allocate a new block and return a ptr to the new memory
+ return this->grow_(count, t);
+ }
+
+ return ptr;
+ }
+
+ T *push_sequence(std::size_t count, T const &t, fill_t)
+ {
+ T *ptr = this->push_sequence(count, t);
+ std::fill_n(ptr, count, t);
+ return ptr;
+ }
+
+ void unwind_to(T *ptr)
+ {
+ while(!this->in_current_chunk(ptr))
+ {
+ // completely unwind the current chunk, move to the previous chunk
+ this->unwind_chunk_();
+ }
+ this->current_chunk_->curr_ = this->curr_ = ptr;
+ }
+
+ // shrink-to-fit: remove any unused nodes in the chain
+ void conserve()
+ {
+ if(this->current_chunk_)
+ {
+ for(chunk *next; this->current_chunk_->next_; this->current_chunk_->next_ = next)
+ {
+ next = this->current_chunk_->next_->next_;
+ delete this->current_chunk_->next_;
+ }
+ }
+ }
+};
+
+}}} // namespace boost::xpressive::detail
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/utility/symbols.hpp b/boost/xpressive/detail/utility/symbols.hpp
new file mode 100644
index 0000000000..b1c4213a6c
--- /dev/null
+++ b/boost/xpressive/detail/utility/symbols.hpp
@@ -0,0 +1,278 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file symbols.hpp
+/// Contains the Ternary Search Trie implementation.
+/// Based on the following papers:
+/// J. Bentley and R. Sedgewick. (1998) Ternary search trees. Dr. Dobbs Journal
+/// G. Badr and B.J. Oommen. (2005) Self-Adjusting of Ternary Search Tries Using
+/// Conditional Rotations and Randomized Heuristics
+//
+// Copyright 2007 David Jenkins.
+// Copyright 2007 Eric Niebler.
+//
+// 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_SYMBOLS_HPP_DRJ_06_11_2007
+#define BOOST_XPRESSIVE_DETAIL_SYMBOLS_HPP_DRJ_06_11_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/value_type.hpp>
+#include <boost/range/const_iterator.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // symbols (using a ternary search trie)
+ //
+ template<typename Map>
+ struct symbols
+ {
+ typedef typename range_value<Map>::type::first_type key_type;
+ typedef typename range_value<Map>::type::second_type value_type;
+ typedef typename range_value<key_type>::type char_type;
+ typedef typename range_const_iterator<Map>::type iterator;
+ typedef typename range_const_iterator<key_type>::type key_iterator;
+ typedef value_type const *result_type;
+
+ // copies of this symbol table share the TST
+
+ template<typename Trans>
+ void load(Map const &map, Trans trans)
+ {
+ iterator begin = boost::begin(map);
+ iterator end = boost::end(map);
+ node* root_p = this->root.get();
+ for(; begin != end; ++begin)
+ {
+ key_iterator kbegin = boost::begin(begin->first);
+ key_iterator kend = boost::end(begin->first);
+ root_p = this->insert(root_p, kbegin, kend, &begin->second, trans);
+ }
+ this->root.reset(root_p);
+ }
+
+ template<typename BidiIter, typename Trans>
+ result_type operator ()(BidiIter &begin, BidiIter end, Trans trans) const
+ {
+ return this->search(begin, end, trans, this->root.get());
+ }
+
+ template<typename Sink>
+ void peek(Sink const &sink) const
+ {
+ this->peek_(this->root.get(), sink);
+ }
+
+ private:
+ ///////////////////////////////////////////////////////////////////////////////
+ // struct node : a node in the TST.
+ // The "eq" field stores the result pointer when ch is zero.
+ //
+ struct node
+ : boost::noncopyable
+ {
+ node(char_type c)
+ : ch(c)
+ , lo(0)
+ , eq(0)
+ , hi(0)
+ #ifdef BOOST_DISABLE_THREADS
+ , tau(0)
+ #endif
+ {}
+
+ ~node()
+ {
+ delete lo;
+ if (ch)
+ delete eq;
+ delete hi;
+ }
+
+ void swap(node& that)
+ {
+ std::swap(ch, that.ch);
+ std::swap(lo, that.lo);
+ std::swap(eq, that.eq);
+ std::swap(hi, that.hi);
+ #ifdef BOOST_DISABLE_THREADS
+ std::swap(tau, that.tau);
+ #endif
+ }
+
+ char_type ch;
+ node* lo;
+ union
+ {
+ node* eq;
+ result_type result;
+ };
+ node* hi;
+ #ifdef BOOST_DISABLE_THREADS
+ long tau;
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // insert : insert a string into the TST
+ //
+ template<typename Trans>
+ node* insert(node* p, key_iterator &begin, key_iterator end, result_type r, Trans trans) const
+ {
+ char_type c1 = 0;
+
+ if(begin != end)
+ {
+ c1 = trans(*begin);
+ }
+
+ if(!p)
+ {
+ p = new node(c1);
+ }
+
+ if(c1 < p->ch)
+ {
+ p->lo = this->insert(p->lo, begin, end, r, trans);
+ }
+ else if(c1 == p->ch)
+ {
+ if(0 == c1)
+ {
+ p->result = r;
+ }
+ else
+ {
+ p->eq = this->insert(p->eq, ++begin, end, r, trans);
+ }
+ }
+ else
+ {
+ p->hi = this->insert(p->hi, begin, end, r, trans);
+ }
+
+ return p;
+ }
+
+ #ifdef BOOST_DISABLE_THREADS
+ ///////////////////////////////////////////////////////////////////////////////
+ // conditional rotation : the goal is to minimize the overall
+ // weighted path length of each binary search tree
+ //
+ bool cond_rotation(bool left, node* const i, node* const j) const
+ {
+ // don't rotate top node in binary search tree
+ if (i == j)
+ return false;
+ // calculate psi (the rotation condition)
+ node* const k = (left ? i->hi : i->lo);
+ long psi = 2*i->tau - j->tau - (k ? k->tau : 0);
+ if (psi <= 0)
+ return false;
+
+ // recalculate the tau values
+ j->tau += -i->tau + (k ? k->tau : 0);
+ i->tau += j->tau - (k ? k->tau : 0);
+ // fixup links and swap nodes
+ if (left)
+ {
+ j->lo = k;
+ i->hi = i;
+ }
+ else
+ {
+ j->hi = k;
+ i->lo = i;
+ }
+ (*i).swap(*j);
+ return true;
+ }
+ #endif
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // search : find a string in the TST
+ //
+ template<typename BidiIter, typename Trans>
+ result_type search(BidiIter &begin, BidiIter end, Trans trans, node* p) const
+ {
+ result_type r = 0;
+ node* p2 = p;
+ bool left = false;
+ char_type c1 = (begin != end ? trans(*begin) : 0);
+ while(p)
+ {
+ #ifdef BOOST_DISABLE_THREADS
+ ++p->tau;
+ #endif
+ if(c1 == p->ch)
+ {
+ // conditional rotation test
+ #ifdef BOOST_DISABLE_THREADS
+ if (this->cond_rotation(left, p, p2))
+ p = p2;
+ #endif
+ if (0 == p->ch)
+ {
+ // it's a match!
+ r = p->result;
+ }
+ if(begin == end)
+ break;
+ ++begin;
+ p = p->eq;
+ // search for the longest match first
+ r = search(begin,end,trans,p);
+ if (0 == r)
+ {
+ // search for a match ending here
+ r = search(end,end,trans,p);
+ if (0 == r)
+ {
+ --begin;
+ }
+ }
+ break;
+ }
+ else if(c1 < p->ch)
+ {
+ left = true;
+ p2 = p;
+ p = p->lo;
+ }
+ else // (c1 > p->ch)
+ {
+ left = false;
+ p2 = p;
+ p = p->hi;
+ }
+ }
+ return r;
+ }
+
+ template<typename Sink>
+ void peek_(node const *const &p, Sink const &sink) const
+ {
+ if(p)
+ {
+ sink(p->ch);
+ this->peek_(p->lo, sink);
+ this->peek_(p->hi, sink);
+ }
+ }
+
+ boost::shared_ptr<node> root;
+ };
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/utility/tracking_ptr.hpp b/boost/xpressive/detail/utility/tracking_ptr.hpp
new file mode 100644
index 0000000000..7f29ba155d
--- /dev/null
+++ b/boost/xpressive/detail/utility/tracking_ptr.hpp
@@ -0,0 +1,494 @@
+///////////////////////////////////////////////////////////////////////////////
+// tracking_ptr.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_TRACKING_PTR_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_TRACKING_PTR_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
+# include <iostream>
+#endif
+#include <set>
+#include <functional>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator/filter_iterator.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+template<typename Type>
+struct tracking_ptr;
+
+template<typename Derived>
+struct enable_reference_tracking;
+
+///////////////////////////////////////////////////////////////////////////////
+// weak_iterator
+// steps through a set of weak_ptr, converts to shared_ptrs on the fly and
+// removes from the set the weak_ptrs that have expired.
+template<typename Derived>
+struct weak_iterator
+ : iterator_facade
+ <
+ weak_iterator<Derived>
+ , shared_ptr<Derived> const
+ , std::forward_iterator_tag
+ >
+{
+ typedef std::set<weak_ptr<Derived> > set_type;
+ typedef typename set_type::iterator base_iterator;
+
+ weak_iterator()
+ : cur_()
+ , iter_()
+ , set_(0)
+ {
+ }
+
+ weak_iterator(base_iterator iter, set_type *set)
+ : cur_()
+ , iter_(iter)
+ , set_(set)
+ {
+ this->satisfy_();
+ }
+
+private:
+ friend class boost::iterator_core_access;
+
+ shared_ptr<Derived> const &dereference() const
+ {
+ return this->cur_;
+ }
+
+ void increment()
+ {
+ ++this->iter_;
+ this->satisfy_();
+ }
+
+ bool equal(weak_iterator<Derived> const &that) const
+ {
+ return this->iter_ == that.iter_;
+ }
+
+ void satisfy_()
+ {
+ while(this->iter_ != this->set_->end())
+ {
+ this->cur_ = this->iter_->lock();
+ if(this->cur_)
+ return;
+ base_iterator tmp = this->iter_++;
+ this->set_->erase(tmp);
+ }
+ this->cur_.reset();
+ }
+
+ shared_ptr<Derived> cur_;
+ base_iterator iter_;
+ set_type *set_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// filter_self
+// for use with a filter_iterator to filter a node out of a list of dependencies
+template<typename Derived>
+struct filter_self
+ : std::unary_function<shared_ptr<Derived>, bool>
+{
+ filter_self(enable_reference_tracking<Derived> *self)
+ : self_(self)
+ {
+ }
+
+ bool operator ()(shared_ptr<Derived> const &that) const
+ {
+ return this->self_ != that.get();
+ }
+
+private:
+ enable_reference_tracking<Derived> *self_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// swap without bringing in std::swap -- must be found by ADL.
+template<typename T>
+void adl_swap(T &t1, T &t2)
+{
+ swap(t1, t2);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// enable_reference_tracking
+// inherit from this type to enable reference tracking for a type. You can
+// then use tracking_ptr (below) as a holder for derived objects.
+//
+template<typename Derived>
+struct enable_reference_tracking
+{
+ typedef std::set<shared_ptr<Derived> > references_type;
+ typedef std::set<weak_ptr<Derived> > dependents_type;
+
+ void tracking_copy(Derived const &that)
+ {
+ if(&this->derived_() != &that)
+ {
+ this->raw_copy_(that);
+ this->tracking_update();
+ }
+ }
+
+ void tracking_clear()
+ {
+ this->raw_copy_(Derived());
+ }
+
+ // called automatically as a result of a tracking_copy(). Must be called explicitly
+ // if you change the references without calling tracking_copy().
+ void tracking_update()
+ {
+ // add "this" as a dependency to all the references
+ this->update_references_();
+ // notify our dependencies that we have new references
+ this->update_dependents_();
+ }
+
+ void track_reference(enable_reference_tracking<Derived> &that)
+ {
+ // avoid some unbounded memory growth in certain circumstances by
+ // opportunistically removing stale dependencies from "that"
+ that.purge_stale_deps_();
+ // add "that" as a reference
+ this->refs_.insert(that.self_);
+ // also inherit that's references
+ this->refs_.insert(that.refs_.begin(), that.refs_.end());
+ }
+
+ long use_count() const
+ {
+ return this->cnt_;
+ }
+
+ void add_ref()
+ {
+ ++this->cnt_;
+ }
+
+ void release()
+ {
+ BOOST_ASSERT(0 < this->cnt_);
+ if(0 == --this->cnt_)
+ {
+ this->refs_.clear();
+ this->self_.reset();
+ }
+ }
+
+ //{{AFX_DEBUG
+ #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
+ friend std::ostream &operator <<(std::ostream &sout, enable_reference_tracking<Derived> const &that)
+ {
+ that.dump_(sout);
+ return sout;
+ }
+ #endif
+ //}}AFX_DEBUG
+
+protected:
+
+ enable_reference_tracking()
+ : refs_()
+ , deps_()
+ , self_()
+ , cnt_(0)
+ {
+ }
+
+ enable_reference_tracking(enable_reference_tracking<Derived> const &that)
+ : refs_()
+ , deps_()
+ , self_()
+ , cnt_(0)
+ {
+ this->operator =(that);
+ }
+
+ enable_reference_tracking<Derived> &operator =(enable_reference_tracking<Derived> const &that)
+ {
+ references_type(that.refs_).swap(this->refs_);
+ return *this;
+ }
+
+ void swap(enable_reference_tracking<Derived> &that)
+ {
+ this->refs_.swap(that.refs_);
+ }
+
+private:
+ friend struct tracking_ptr<Derived>;
+
+ Derived &derived_()
+ {
+ return *static_cast<Derived *>(this);
+ }
+
+ void raw_copy_(Derived that)
+ {
+ detail::adl_swap(this->derived_(), that);
+ }
+
+ bool has_deps_() const
+ {
+ return !this->deps_.empty();
+ }
+
+ void update_references_()
+ {
+ typename references_type::iterator cur = this->refs_.begin();
+ typename references_type::iterator end = this->refs_.end();
+ for(; cur != end; ++cur)
+ {
+ // for each reference, add this as a dependency
+ (*cur)->track_dependency_(*this);
+ }
+ }
+
+ void update_dependents_()
+ {
+ // called whenever this regex object changes (i.e., is assigned to). it walks
+ // the list of dependent regexes and updates *their* lists of references,
+ // thereby spreading out the reference counting responsibility evenly.
+ weak_iterator<Derived> cur(this->deps_.begin(), &this->deps_);
+ weak_iterator<Derived> end(this->deps_.end(), &this->deps_);
+
+ for(; cur != end; ++cur)
+ {
+ (*cur)->track_reference(*this);
+ }
+ }
+
+ void track_dependency_(enable_reference_tracking<Derived> &dep)
+ {
+ if(this == &dep) // never add ourself as a dependency
+ return;
+
+ // add dep as a dependency
+ this->deps_.insert(dep.self_);
+
+ filter_self<Derived> not_self(this);
+ weak_iterator<Derived> begin(dep.deps_.begin(), &dep.deps_);
+ weak_iterator<Derived> end(dep.deps_.end(), &dep.deps_);
+
+ // also inherit dep's dependencies
+ this->deps_.insert(
+ make_filter_iterator(not_self, begin, end)
+ , make_filter_iterator(not_self, end, end)
+ );
+ }
+
+ void purge_stale_deps_()
+ {
+ weak_iterator<Derived> cur(this->deps_.begin(), &this->deps_);
+ weak_iterator<Derived> end(this->deps_.end(), &this->deps_);
+
+ for(; cur != end; ++cur)
+ ;
+ }
+
+ //{{AFX_DEBUG
+ #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
+ void dump_(std::ostream &sout) const;
+ #endif
+ //}}AFX_DEBUG
+
+ references_type refs_;
+ dependents_type deps_;
+ shared_ptr<Derived> self_;
+ boost::detail::atomic_count cnt_;
+};
+
+template<typename Derived>
+inline void intrusive_ptr_add_ref(enable_reference_tracking<Derived> *p)
+{
+ p->add_ref();
+}
+
+template<typename Derived>
+inline void intrusive_ptr_release(enable_reference_tracking<Derived> *p)
+{
+ p->release();
+}
+
+//{{AFX_DEBUG
+#ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
+///////////////////////////////////////////////////////////////////////////////
+// dump_
+//
+template<typename Derived>
+inline void enable_reference_tracking<Derived>::dump_(std::ostream &sout) const
+{
+ shared_ptr<Derived> this_ = this->self_;
+ sout << "0x" << (void*)this << " cnt=" << this_.use_count()-1 << " refs={";
+ typename references_type::const_iterator cur1 = this->refs_.begin();
+ typename references_type::const_iterator end1 = this->refs_.end();
+ for(; cur1 != end1; ++cur1)
+ {
+ sout << "0x" << (void*)&**cur1 << ',';
+ }
+ sout << "} deps={";
+ typename dependents_type::const_iterator cur2 = this->deps_.begin();
+ typename dependents_type::const_iterator end2 = this->deps_.end();
+ for(; cur2 != end2; ++cur2)
+ {
+ // ericne, 27/nov/05: CW9_4 doesn't like if(shared_ptr x = y)
+ shared_ptr<Derived> dep = cur2->lock();
+ if(dep.get())
+ {
+ sout << "0x" << (void*)&*dep << ',';
+ }
+ }
+ sout << '}';
+}
+#endif
+//}}AFX_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////
+// tracking_ptr
+// holder for a reference-tracked type. Does cycle-breaking, lazy initialization
+// and copy-on-write. TODO: implement move semantics.
+//
+template<typename Type>
+struct tracking_ptr
+{
+ BOOST_MPL_ASSERT((is_base_and_derived<enable_reference_tracking<Type>, Type>));
+ typedef Type element_type;
+
+ tracking_ptr()
+ : impl_()
+ {
+ }
+
+ tracking_ptr(tracking_ptr<element_type> const &that)
+ : impl_()
+ {
+ this->operator =(that);
+ }
+
+ tracking_ptr<element_type> &operator =(tracking_ptr<element_type> const &that)
+ {
+ // Note: the copy-and-swap idiom doesn't work here if has_deps_()==true
+ // because it invalidates references to the element_type object.
+ if(this != &that)
+ {
+ if(that)
+ {
+ if(that.has_deps_() || this->has_deps_())
+ {
+ this->fork_(); // deep copy, forks data if necessary
+ this->impl_->tracking_copy(*that);
+ }
+ else
+ {
+ this->impl_ = that.impl_; // shallow, copy-on-write
+ }
+ }
+ else if(*this)
+ {
+ this->impl_->tracking_clear();
+ }
+ }
+ return *this;
+ }
+
+ // NOTE: this does *not* do tracking. Can't provide a non-throwing swap that tracks references
+ void swap(tracking_ptr<element_type> &that) // throw()
+ {
+ this->impl_.swap(that.impl_);
+ }
+
+ // calling this forces this->impl_ to fork.
+ shared_ptr<element_type> const &get() const
+ {
+ if(intrusive_ptr<element_type> impl = this->fork_())
+ {
+ this->impl_->tracking_copy(*impl);
+ }
+ return this->impl_->self_;
+ }
+
+ #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
+ typedef bool unspecified_bool_type;
+ #else
+ typedef typename intrusive_ptr<element_type>::unspecified_bool_type unspecified_bool_type;
+ #endif
+
+ // smart-pointer operators
+ operator unspecified_bool_type() const
+ {
+ return this->impl_;
+ }
+
+ bool operator !() const
+ {
+ return !this->impl_;
+ }
+
+ // Since this does not un-share the data, it returns a ptr-to-const
+ element_type const *operator ->() const
+ {
+ return get_pointer(this->impl_);
+ }
+
+ // Since this does not un-share the data, it returns a ref-to-const
+ element_type const &operator *() const
+ {
+ return *this->impl_;
+ }
+
+private:
+
+ // calling this forces impl_ to fork.
+ intrusive_ptr<element_type> fork_() const
+ {
+ intrusive_ptr<element_type> impl;
+ if(!this->impl_ || 1 != this->impl_->use_count())
+ {
+ impl = this->impl_;
+ BOOST_ASSERT(!this->has_deps_());
+ shared_ptr<element_type> simpl(new element_type);
+ this->impl_ = get_pointer(simpl->self_ = simpl);
+ }
+ return impl;
+ }
+
+ // does anybody have a dependency on us?
+ bool has_deps_() const
+ {
+ return this->impl_ && this->impl_->has_deps_();
+ }
+
+ // mutable to allow lazy initialization
+ mutable intrusive_ptr<element_type> impl_;
+};
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/detail/utility/traits_utils.hpp b/boost/xpressive/detail/utility/traits_utils.hpp
new file mode 100644
index 0000000000..18e3e609ff
--- /dev/null
+++ b/boost/xpressive/detail/utility/traits_utils.hpp
@@ -0,0 +1,145 @@
+///////////////////////////////////////////////////////////////////////////////
+// traits_utils.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_TRAITS_UTILS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_TRAITS_UTILS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning(push)
+# pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+
+#include <string>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // char_cast
+ //
+ template<typename ToChar, typename FromChar, typename Traits>
+ inline ToChar
+ char_cast(FromChar from, Traits const &, typename enable_if<is_same<ToChar, FromChar> >::type * = 0)
+ {
+ return from;
+ }
+
+ template<typename ToChar, typename FromChar, typename Traits>
+ inline ToChar
+ char_cast(FromChar from, Traits const &tr, typename disable_if<is_same<ToChar, FromChar> >::type * = 0)
+ {
+ BOOST_MPL_ASSERT((is_same<FromChar, char>));
+ return tr.widen(from);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // widen_fun
+ //
+ template<typename Traits>
+ struct widen_fun
+ {
+ typedef typename Traits::char_type result_type;
+ explicit widen_fun(Traits const &tr)
+ : traits_(tr)
+ {}
+
+ result_type operator()(char ch) const
+ {
+ return this->traits_.widen(ch);
+ }
+
+ Traits const &traits_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // string_cast_
+ //
+ template<
+ typename To
+ , typename From
+ , typename ToChar = typename detail::range_data<To>::type
+ , typename FromChar = typename detail::range_data<From>::type
+ >
+ struct string_cast_
+ {
+ BOOST_MPL_ASSERT((is_same<FromChar, char>));
+ typedef To const result_type;
+ template<typename Traits>
+ result_type operator()(From const &from, Traits const &tr) const
+ {
+ widen_fun<Traits> widen(tr);
+ To to(
+ boost::make_transform_iterator(detail::data_begin(from), widen)
+ , boost::make_transform_iterator(detail::data_end(from), widen)
+ );
+ return to;
+ }
+ };
+
+ template<typename To, typename From, typename Char>
+ struct string_cast_<To, From, Char, Char>
+ {
+ typedef To const result_type;
+ template<typename Traits>
+ result_type operator()(From const &from, Traits const &) const
+ {
+ To to(detail::data_begin(from), detail::data_end(from));
+ return to;
+ }
+ };
+
+ template<typename From, typename Char>
+ struct string_cast_<From, From, Char, Char>
+ {
+ typedef From const &result_type;
+ template<typename Traits>
+ result_type operator()(From const &from, Traits const &) const
+ {
+ return from;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // string_cast
+ //
+ template<typename To, typename From, typename Traits>
+ typename string_cast_<To, From>::result_type
+ string_cast(From const &from, Traits const &tr)
+ {
+ return string_cast_<To, From>()(from, tr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // translate
+ //
+ template<typename Char, typename Traits>
+ inline Char translate(Char ch, Traits const &tr, mpl::false_) // case-sensitive
+ {
+ return tr.translate(ch);
+ }
+
+ template<typename Char, typename Traits>
+ inline Char translate(Char ch, Traits const &tr, mpl::true_) // case-insensitive
+ {
+ return tr.translate_nocase(ch);
+ }
+
+}}} // namespace boost::xpressive::detail
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/boost/xpressive/detail/utility/width.hpp b/boost/xpressive/detail/utility/width.hpp
new file mode 100644
index 0000000000..3fc10c76a5
--- /dev/null
+++ b/boost/xpressive/detail/utility/width.hpp
@@ -0,0 +1,94 @@
+///////////////////////////////////////////////////////////////////////////////
+// width.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_WIDTH_HPP_EAN_04_07_2006
+#define BOOST_XPRESSIVE_DETAIL_UTILITY_WIDTH_HPP_EAN_04_07_2006
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <climits> // for INT_MAX
+#include <boost/mpl/size_t.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+typedef mpl::size_t<INT_MAX / 2 - 1> unknown_width;
+struct width;
+bool is_unknown(width const &that);
+
+///////////////////////////////////////////////////////////////////////////////
+// width
+struct width
+{
+ width(std::size_t val = 0)
+ : value_(val)
+ {
+ }
+
+ bool operator !() const
+ {
+ return !this->value_;
+ }
+
+ width &operator +=(width const &that)
+ {
+ this->value_ =
+ !is_unknown(*this) && !is_unknown(that)
+ ? this->value_ + that.value_
+ : unknown_width();
+ return *this;
+ }
+
+ width &operator |=(width const &that)
+ {
+ this->value_ =
+ this->value_ == that.value_
+ ? this->value_
+ : unknown_width();
+ return *this;
+ }
+
+ std::size_t value() const
+ {
+ return this->value_;
+ }
+
+private:
+ std::size_t value_;
+};
+
+inline bool is_unknown(width const &that)
+{
+ return unknown_width::value == that.value();
+}
+
+inline bool operator ==(width const &left, width const &right)
+{
+ return left.value() == right.value();
+}
+
+inline bool operator !=(width const &left, width const &right)
+{
+ return left.value() != right.value();
+}
+
+inline width operator +(width left, width const &right)
+{
+ return left += right;
+}
+
+inline width operator |(width left, width const &right)
+{
+ return left |= right;
+}
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/match_results.hpp b/boost/xpressive/match_results.hpp
new file mode 100644
index 0000000000..6e9516d1f9
--- /dev/null
+++ b/boost/xpressive/match_results.hpp
@@ -0,0 +1,1395 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file match_results.hpp
+/// Contains the definition of the match_results type and associated helpers.
+/// The match_results type holds the results of a regex_match() or
+/// regex_search() operation.
+//
+// Copyright 2008 Eric Niebler. 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)
+//
+// Acknowledgements: Thanks to Markus Schoepflin for helping to track down
+// a tricky formatting bug on HP Tru64, and to Steven Watanabe for suggesting
+// the fix.
+
+#ifndef BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <map>
+#include <string>
+#include <vector>
+#include <utility>
+#include <iterator>
+#include <typeinfo>
+#include <algorithm>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/integer.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/size_t.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/iterator_adaptors.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/numeric/conversion/converter.hpp>
+#include <boost/optional.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/as_literal.hpp>
+#include <boost/range/const_iterator.hpp>
+#include <boost/type_traits/is_function.hpp>
+#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
+# include <boost/iterator/filter_iterator.hpp>
+#endif
+#include <boost/xpressive/regex_constants.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/regex_impl.hpp>
+#include <boost/xpressive/detail/core/sub_match_vector.hpp>
+#include <boost/xpressive/detail/utility/sequence_stack.hpp>
+#include <boost/xpressive/detail/core/results_cache.hpp>
+#include <boost/xpressive/detail/utility/literals.hpp>
+#include <boost/xpressive/detail/utility/algorithm.hpp>
+#include <boost/xpressive/detail/utility/counted_base.hpp>
+// Doxygen can't handle proto :-(
+#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+# include <boost/proto/proto_fwd.hpp>
+# include <boost/proto/traits.hpp>
+#endif
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// type_info_less
+//
+struct type_info_less
+{
+ bool operator()(std::type_info const *left, std::type_info const *right) const
+ {
+ return 0 != left->before(*right);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ActionArgBinding
+//
+struct ActionArgBinding
+ : proto::assign<proto::terminal<action_arg<proto::_, proto::_> >, proto::terminal<proto::_> >
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// results_extras
+//
+template<typename BidiIter>
+struct results_extras
+ : counted_base<results_extras<BidiIter> >
+{
+ sequence_stack<sub_match_impl<BidiIter> > sub_match_stack_;
+ results_cache<BidiIter> results_cache_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// char_overflow_handler_
+//
+struct char_overflow_handler_
+{
+ void operator ()(numeric::range_check_result result) const // throw(regex_error)
+ {
+ if(numeric::cInRange != result)
+ {
+ BOOST_THROW_EXCEPTION(
+ regex_error(
+ regex_constants::error_escape
+ , "character escape too large to fit in target character type"
+ )
+ );
+ }
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// transform_op enum
+//
+enum transform_op { None = 0, Upper = 1, Lower = 2 };
+enum transform_scope { Next = 0, Rest = 1 };
+
+///////////////////////////////////////////////////////////////////////////////
+// case_converting_iterator
+//
+template<typename OutputIterator, typename Char>
+struct case_converting_iterator
+ : std::iterator<std::output_iterator_tag, Char, void, void, case_converting_iterator<OutputIterator, Char> >
+{
+ case_converting_iterator(OutputIterator const &out, traits<Char> const *tr)
+ : out_(out)
+ , traits_(tr)
+ , next_(None)
+ , rest_(None)
+ {}
+
+ OutputIterator base() const
+ {
+ return this->out_;
+ }
+
+ case_converting_iterator &operator ++()
+ {
+ ++this->out_;
+ this->next_ = None;
+ return *this;
+ }
+
+ case_converting_iterator operator ++(int)
+ {
+ case_converting_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+ case_converting_iterator &operator *()
+ {
+ return *this;
+ }
+
+ friend bool set_transform(case_converting_iterator &iter, transform_op trans, transform_scope scope)
+ {
+ BOOST_ASSERT(scope == Next || scope == Rest);
+ if(scope == Next)
+ iter.next_ = trans;
+ else
+ iter.rest_ = trans;
+ return true;
+ }
+
+ case_converting_iterator &operator =(Char ch)
+ {
+ switch(this->next_ ? this->next_ : this->rest_)
+ {
+ case Lower:
+ ch = this->traits_->tolower(ch);
+ break;
+
+ case Upper:
+ ch = this->traits_->toupper(ch);
+ break;
+
+ default:;
+ }
+
+ *this->out_ = ch;
+ return *this;
+ }
+
+private:
+ OutputIterator out_;
+ traits<Char> const *traits_;
+ transform_op next_, rest_;
+};
+
+template<typename Iterator>
+inline bool set_transform(Iterator &, transform_op, transform_scope)
+{
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// noop_output_iterator
+//
+template<typename Char>
+struct noop_output_iterator
+ : std::iterator<std::output_iterator_tag, Char, void, void, noop_output_iterator<Char> >
+{
+ noop_output_iterator &operator ++()
+ {
+ return *this;
+ }
+
+ noop_output_iterator &operator ++(int)
+ {
+ return *this;
+ }
+
+ noop_output_iterator &operator *()
+ {
+ return *this;
+ }
+
+ noop_output_iterator &operator =(Char const &)
+ {
+ return *this;
+ }
+};
+
+struct any_type { any_type(...); };
+typedef char no_type;
+typedef char (&unary_type)[2];
+typedef char (&binary_type)[3];
+typedef char (&ternary_type)[4];
+
+no_type check_is_formatter(unary_type, binary_type, ternary_type);
+
+template<typename T>
+unary_type check_is_formatter(T const &, binary_type, ternary_type);
+
+template<typename T>
+binary_type check_is_formatter(unary_type, T const &, ternary_type);
+
+template<typename T, typename U>
+binary_type check_is_formatter(T const &, U const &, ternary_type);
+
+template<typename T>
+ternary_type check_is_formatter(unary_type, binary_type, T const &);
+
+template<typename T, typename U>
+ternary_type check_is_formatter(T const &, binary_type, U const &);
+
+template<typename T, typename U>
+ternary_type check_is_formatter(unary_type, T const &, U const &);
+
+template<typename T, typename U, typename V>
+ternary_type check_is_formatter(T const &, U const &, V const &);
+
+struct unary_binary_ternary
+{
+ typedef unary_type (*unary_fun)(any_type);
+ typedef binary_type (*binary_fun)(any_type, any_type);
+ typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
+ operator unary_fun();
+ operator binary_fun();
+ operator ternary_fun();
+};
+
+template<typename Formatter, bool IsFunction = is_function<Formatter>::value>
+struct formatter_wrapper
+ : Formatter
+ , unary_binary_ternary
+{
+ formatter_wrapper();
+};
+
+template<typename Formatter>
+struct formatter_wrapper<Formatter, true>
+ : unary_binary_ternary
+{
+ operator Formatter *();
+};
+
+template<typename Formatter>
+struct formatter_wrapper<Formatter *, false>
+ : unary_binary_ternary
+{
+ operator Formatter *();
+};
+
+template<typename Formatter, typename What, typename Out, typename Void = void>
+struct formatter_arity
+{
+ static formatter_wrapper<Formatter> &formatter;
+ static What &what;
+ static Out &out;
+ BOOST_STATIC_CONSTANT(
+ std::size_t
+ , value = sizeof(
+ check_is_formatter(
+ formatter(what)
+ , formatter(what, out)
+ , formatter(what, out, regex_constants::format_default)
+ )
+ ) - 1
+ );
+ typedef mpl::size_t<value> type;
+};
+
+template<typename Formatter, typename What, typename Out>
+struct formatter_arity<Formatter, What, Out, typename Formatter::proto_is_expr_>
+ : mpl::size_t<4>
+{};
+
+template<typename T>
+struct is_char_ptr
+ : mpl::false_
+{};
+
+template<typename T>
+struct is_char_ptr<T *>
+ : mpl::not_<is_function<T> >
+{};
+
+#if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
+// work around gcc-4.0.1 compiler bug wrt function references
+template<typename T>
+typename mpl::if_<is_function<T>, T *, T const &>::type
+as_callable(T const &t)
+{
+ return t;
+}
+#endif
+
+} // detail
+
+///////////////////////////////////////////////////////////////////////////////
+// match_results
+/// \brief Class template match_results\<\> holds the results of a regex_match() or a
+/// regex_search() as a collection of sub_match objects.
+///
+/// Class template match_results\<\> denotes a collection of sequences representing the result of
+/// a regular expression match. Storage for the collection is allocated and freed as necessary by
+/// the member functions of class match_results\<\>.
+///
+/// The class template match_results\<\> conforms to the requirements of a Sequence, as specified
+/// in (lib.sequence.reqmts), except that only operations defined for const-qualified Sequences are
+/// supported.
+template<typename BidiIter>
+struct match_results
+{
+private:
+ /// INTERNAL ONLY
+ ///
+ struct dummy { int i_; };
+ typedef int dummy::*bool_type;
+
+public:
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef typename detail::string_type<char_type>::type string_type;
+ typedef std::size_t size_type;
+ typedef sub_match<BidiIter> value_type;
+ typedef typename iterator_difference<BidiIter>::type difference_type;
+ typedef value_type const &reference;
+ typedef value_type const &const_reference;
+
+ typedef typename detail::sub_match_vector<BidiIter>::iterator iterator;
+ typedef typename detail::sub_match_vector<BidiIter>::const_iterator const_iterator;
+ typedef typename detail::nested_results<BidiIter> nested_results_type;
+
+ /// \post regex_id() == 0
+ /// \post size() == 0
+ /// \post empty() == true
+ /// \post str() == string_type()
+ match_results()
+ : regex_id_(0)
+ , sub_matches_()
+ , base_()
+ , prefix_()
+ , suffix_()
+ , nested_results_()
+ , extras_ptr_()
+ , traits_()
+ , args_()
+ , named_marks_()
+ {
+ }
+
+ /// \param that The match_results object to copy
+ /// \post regex_id() == that.regex_id().
+ /// \post size() == that.size().
+ /// \post empty() == that.empty().
+ /// \post str(n) == that.str(n) for all positive integers n \< that.size().
+ /// \post prefix() == that.prefix().
+ /// \post suffix() == that.suffix().
+ /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
+ /// \post length(n) == that.length(n) for all positive integers n \< that.size().
+ /// \post position(n) == that.position(n) for all positive integers n \< that.size().
+ match_results(match_results<BidiIter> const &that)
+ : regex_id_(that.regex_id_)
+ , sub_matches_()
+ , base_()
+ , prefix_()
+ , suffix_()
+ , nested_results_()
+ , extras_ptr_()
+ , traits_()
+ , args_(that.args_)
+ , named_marks_(that.named_marks_)
+ {
+ if(that)
+ {
+ extras_type &extras = this->get_extras_();
+ std::size_t size = that.sub_matches_.size();
+ detail::sub_match_impl<BidiIter> *sub_matches = extras.sub_match_stack_.push_sequence(size, detail::sub_match_impl<BidiIter>(*that.base_), detail::fill);
+ detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size, that.sub_matches_);
+
+ this->base_ = that.base_;
+ this->prefix_ = that.prefix_;
+ this->suffix_ = that.suffix_;
+ // BUGBUG this doesn't share the extras::sequence_stack
+ this->nested_results_ = that.nested_results_;
+ this->traits_ = that.traits_;
+ }
+ }
+
+ ~match_results()
+ {
+ }
+
+ /// \param that The match_results object to copy.
+ /// \post regex_id() == that.regex_id().
+ /// \post size() == that.size().
+ /// \post empty() == that.empty().
+ /// \post str(n) == that.str(n) for all positive integers n \< that.size().
+ /// \post prefix() == that.prefix().
+ /// \post suffix() == that.suffix().
+ /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
+ /// \post length(n) == that.length(n) for all positive integers n \< that.size().
+ /// \post position(n) == that.position(n) for all positive integers n \< that.size().
+ match_results<BidiIter> &operator =(match_results<BidiIter> const &that)
+ {
+ match_results<BidiIter>(that).swap(*this);
+ return *this;
+ }
+
+ /// Returns one plus the number of marked sub-expressions in the regular
+ /// expression that was matched if *this represents the result of a
+ /// successful match. Otherwise returns 0.
+ size_type size() const
+ {
+ return this->sub_matches_.size();
+ }
+
+ /// Returns size() == 0.
+ ///
+ bool empty() const
+ {
+ return 0 == this->size();
+ }
+
+ /// Returns (*this)[sub].length().
+ ///
+ difference_type length(size_type sub = 0) const
+ {
+ return this->sub_matches_[ sub ].length();
+ }
+
+ /// If !(*this)[sub].matched then returns -1. Otherwise returns std::distance(base, (*this)[sub].first),
+ /// where base is the start iterator of the sequence that was searched. [Note - unless this is part
+ /// of a repeated search with a regex_iterator then base is the same as prefix().first - end note]
+ difference_type position(size_type sub = 0) const
+ {
+ return this->sub_matches_[ sub ].matched ? std::distance(*this->base_, this->sub_matches_[ sub ].first) : -1;
+ }
+
+ /// Returns (*this)[sub].str().
+ ///
+ string_type str(size_type sub = 0) const
+ {
+ return this->sub_matches_[ sub ].str();
+ }
+
+ /// Returns a reference to the sub_match object representing the sequence that
+ /// matched marked sub-expression sub. If sub == 0 then returns a reference to
+ /// a sub_match object representing the sequence that matched the whole regular
+ /// expression. If sub >= size() then returns a sub_match object representing an
+ /// unmatched sub-expression.
+ template<typename Sub>
+ const_reference operator [](Sub const &sub) const
+ {
+ return this->at_(sub);
+ }
+
+ /// Returns a reference to the sub_match object representing the character sequence from
+ /// the start of the string being matched/searched, to the start of the match found.
+ ///
+ /// \pre (*this)[0].matched is true
+ const_reference prefix() const
+ {
+ return this->prefix_ ? *this->prefix_ : this->sub_matches_[this->sub_matches_.size()];
+ }
+
+ /// Returns a reference to the sub_match object representing the character sequence from
+ /// the end of the match found to the end of the string being matched/searched.
+ ///
+ /// \pre (*this)[0].matched is true
+ const_reference suffix() const
+ {
+ return this->suffix_ ? *this->suffix_ : this->sub_matches_[this->sub_matches_.size()];
+ }
+
+ /// Returns a starting iterator that enumerates over all the marked sub-expression matches
+ /// stored in *this.
+ ///
+ const_iterator begin() const
+ {
+ return this->sub_matches_.begin();
+ }
+
+ /// Returns a terminating iterator that enumerates over all the marked sub-expression
+ /// matches stored in *this.
+ ///
+ const_iterator end() const
+ {
+ return this->sub_matches_.end();
+ }
+
+ /// Returns a true value if (*this)[0].matched, else returns a false value.
+ ///
+ operator bool_type() const
+ {
+ return (!this->empty() && this->sub_matches_[ 0 ].matched) ? &dummy::i_ : 0;
+ }
+
+ /// Returns true if empty() || !(*this)[0].matched, else returns false.
+ ///
+ bool operator !() const
+ {
+ return this->empty() || !this->sub_matches_[ 0 ].matched;
+ }
+
+ /// Returns the id of the basic_regex object most recently used with this match_results object.
+ ///
+ regex_id_type regex_id() const
+ {
+ return this->regex_id_;
+ }
+
+ /// Returns a Sequence of nested match_results elements.
+ ///
+ nested_results_type const &nested_results() const
+ {
+ return this->nested_results_;
+ }
+
+ /// If \c Format models \c ForwardRange or is a null-terminated string, this function
+ /// copies the character sequence in \c fmt to \c OutputIterator \c out. For each format
+ /// specifier or escape sequence in \c fmt, replace that sequence with either the character(s) it
+ /// represents, or the sequence within <tt>*this</tt> to which it refers. The bitmasks specified in flags
+ /// determines what format specifiers or escape sequences are recognized. By default, this is the
+ /// format used by ECMA-262, ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
+ /// this function returns <tt>fmt(*this, out, flags)</tt>.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
+ /// returns <tt>fmt(*this, out)</tt>.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
+ /// returns <tt>std::copy(x.begin(), x.end(), out)</tt>, where \c x is the result of
+ /// calling <tt>fmt(*this)</tt>.
+ template<typename Format, typename OutputIterator>
+ OutputIterator format
+ (
+ OutputIterator out
+ , Format const &fmt
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
+ ) const
+ {
+ // Is this a formatter object, or a format string?
+ typedef
+ typename detail::formatter_arity<
+ Format
+ , match_results<BidiIter>
+ , OutputIterator
+ >::type
+ arity;
+
+ return this->format_(out, fmt, flags, arity());
+ }
+
+ /// \overload
+ ///
+ template<typename OutputIterator>
+ OutputIterator format
+ (
+ OutputIterator out
+ , char_type const *fmt
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ ) const
+ {
+ return this->format_(out, boost::as_literal(fmt), flags, mpl::size_t<0>());
+ }
+
+ /// If \c Format models \c ForwardRange or is a null-terminated string, this function
+ /// returns a copy of the character sequence \c fmt. For each format specifier or escape sequence in \c fmt,
+ /// replace that sequence with either the character(s) it represents, or the sequence within
+ /// <tt>*this</tt> to which it refers. The bitmasks specified in \c flags determines what format specifiers
+ /// or escape sequences are recognized. By default this is the format used by ECMA-262,
+ /// ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
+ /// this function returns a \c string_type object \c x populated by calling <tt>fmt(*this, out, flags)</tt>,
+ /// where \c out is a \c back_insert_iterator into \c x.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
+ /// returns a \c string_type object \c x populated by calling <tt>fmt(*this, out)</tt>,
+ /// where \c out is a \c back_insert_iterator into \c x.
+ ///
+ /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
+ /// returns <tt>fmt(*this)</tt>.
+ template<typename Format, typename OutputIterator>
+ string_type format
+ (
+ Format const &fmt
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
+ ) const
+ {
+ string_type result;
+ this->format(std::back_inserter(result), fmt, flags);
+ return result;
+ }
+
+ /// \overload
+ ///
+ string_type format
+ (
+ char_type const *fmt
+ , regex_constants::match_flag_type flags = regex_constants::format_default
+ ) const
+ {
+ string_type result;
+ this->format(std::back_inserter(result), fmt, flags);
+ return result;
+ }
+
+ /// Swaps the contents of two match_results objects. Guaranteed not to throw.
+ /// \param that The match_results object to swap with.
+ /// \post *this contains the sequence of matched sub-expressions that were in that,
+ /// that contains the sequence of matched sub-expressions that were in *this.
+ /// \throw nothrow
+ void swap(match_results<BidiIter> &that) // throw()
+ {
+ using std::swap;
+ swap(this->regex_id_, that.regex_id_);
+ this->sub_matches_.swap(that.sub_matches_);
+ this->base_.swap(that.base_);
+ this->prefix_.swap(that.prefix_);
+ this->suffix_.swap(that.suffix_);
+ this->nested_results_.swap(that.nested_results_);
+ this->extras_ptr_.swap(that.extras_ptr_);
+ this->traits_.swap(that.traits_);
+ this->args_.swap(that.args_);
+ }
+
+ /// TODO document me
+ ///
+ template<typename Arg>
+ match_results<BidiIter> &let(Arg const &arg)
+ {
+ typedef typename proto::result_of::left<Arg>::type left_type;
+ typedef typename proto::result_of::right<Arg>::type right_type;
+ typedef typename proto::result_of::value<left_type>::type arg_left_type;
+ typedef typename proto::result_of::value<right_type>::type arg_right_type;
+ BOOST_MPL_ASSERT((proto::matches<Arg, detail::ActionArgBinding>));
+ BOOST_MPL_ASSERT((is_same<typename arg_left_type::type, arg_right_type>));
+ this->args_[&typeid(proto::value(proto::left(arg)))] = &proto::value(proto::right(arg));
+ return *this;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ match_results<BidiIter> const &operator ()(regex_id_type regex_id, size_type index = 0) const
+ {
+ // BUGBUG this is linear, make it O(1)
+ static match_results<BidiIter> const s_null;
+
+ regex_id_filter_predicate<BidiIter> pred(regex_id);
+ typename nested_results_type::const_iterator
+ begin = this->nested_results_.begin()
+ , end = this->nested_results_.end()
+ , cur = detail::find_nth_if(begin, end, index, pred);
+
+ return (cur == end) ? s_null : *cur;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ match_results<BidiIter> const &operator ()(basic_regex<BidiIter> const &rex, std::size_t index = 0) const
+ {
+ return (*this)(rex.regex_id(), index);
+ }
+
+private:
+
+ friend struct detail::core_access<BidiIter>;
+ typedef detail::results_extras<BidiIter> extras_type;
+
+ /// INTERNAL ONLY
+ ///
+ void init_
+ (
+ regex_id_type regex_id
+ , intrusive_ptr<detail::traits<char_type> const> const &tr
+ , detail::sub_match_impl<BidiIter> *sub_matches
+ , size_type size
+ , std::vector<detail::named_mark<char_type> > const &named_marks
+ )
+ {
+ this->traits_ = tr;
+ this->regex_id_ = regex_id;
+ this->named_marks_ = named_marks;
+ detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ extras_type &get_extras_()
+ {
+ if(!this->extras_ptr_)
+ {
+ this->extras_ptr_ = new extras_type;
+ }
+
+ return *this->extras_ptr_;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ void set_prefix_suffix_(BidiIter begin, BidiIter end)
+ {
+ this->base_ = begin;
+ this->prefix_ = sub_match<BidiIter>(begin, this->sub_matches_[ 0 ].first, begin != this->sub_matches_[ 0 ].first);
+ this->suffix_ = sub_match<BidiIter>(this->sub_matches_[ 0 ].second, end, this->sub_matches_[ 0 ].second != end);
+
+ typename nested_results_type::iterator ibegin = this->nested_results_.begin();
+ typename nested_results_type::iterator iend = this->nested_results_.end();
+ for( ; ibegin != iend; ++ibegin )
+ {
+ ibegin->set_prefix_suffix_(begin, end);
+ }
+ }
+
+ /// INTERNAL ONLY
+ ///
+ void reset_()
+ {
+ detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, 0, 0);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ void set_base_(BidiIter base)
+ {
+ this->base_ = base;
+
+ typename nested_results_type::iterator ibegin = this->nested_results_.begin();
+ typename nested_results_type::iterator iend = this->nested_results_.end();
+ for( ; ibegin != iend; ++ibegin )
+ {
+ ibegin->set_base_(base);
+ }
+ }
+
+ /// INTERNAL ONLY
+ ///
+ const_reference at_(size_type sub) const
+ {
+ return this->sub_matches_[ sub ];
+ }
+
+ /// INTERNAL ONLY
+ ///
+ const_reference at_(detail::basic_mark_tag const &mark) const
+ {
+ return this->sub_matches_[ detail::get_mark_number(mark) ];
+ }
+
+ /// INTERNAL ONLY
+ ///
+ const_reference at_(char_type const *name) const
+ {
+ for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
+ {
+ if(this->named_marks_[i].name_ == name)
+ {
+ return this->sub_matches_[ this->named_marks_[i].mark_nbr_ ];
+ }
+ }
+ BOOST_THROW_EXCEPTION(
+ regex_error(regex_constants::error_badmark, "invalid named back-reference")
+ );
+ // Should never execute, but if it does, this returns
+ // a "null" sub_match.
+ return this->sub_matches_[this->sub_matches_.size()];
+ }
+
+ /// INTERNAL ONLY
+ ///
+ const_reference at_(string_type const &name) const
+ {
+ return (*this)[name.c_str()];
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename ForwardRange>
+ OutputIterator format2_(OutputIterator out, ForwardRange const &result) const
+ {
+ return std::copy(boost::begin(result), boost::end(result), out);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename Char>
+ OutputIterator format2_(OutputIterator out, Char const *const &result) const
+ {
+ Char const *tmp = result;
+ BOOST_ASSERT(0 != tmp);
+ for(; 0 != *tmp; ++tmp, ++out)
+ {
+ *out = *tmp;
+ }
+ return out;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename ForwardRange>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , ForwardRange const &format
+ , regex_constants::match_flag_type flags
+ , mpl::size_t<0>
+ ) const
+ {
+ typedef typename range_const_iterator<ForwardRange>::type iterator;
+ iterator cur = boost::begin(format), end = boost::end(format);
+
+ if(0 != (regex_constants::format_literal & flags))
+ {
+ return std::copy(cur, end, out);
+ }
+ else if(0 != (regex_constants::format_perl & flags))
+ {
+ return this->format_perl_(cur, end, out);
+ }
+ else if(0 != (regex_constants::format_sed & flags))
+ {
+ return this->format_sed_(cur, end, out);
+ }
+ else if(0 != (regex_constants::format_all & flags))
+ {
+ return this->format_all_(cur, end, out);
+ }
+
+ return this->format_ecma_262_(cur, end, out);
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename Callable1>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , Callable1 const &format
+ , regex_constants::match_flag_type
+ , mpl::size_t<1>
+ ) const
+ {
+ #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
+ return this->format2_(out, detail::as_callable(format)(*this));
+ #else
+ return this->format2_(out, format(*this));
+ #endif
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename Callable2>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , Callable2 const &format
+ , regex_constants::match_flag_type
+ , mpl::size_t<2>
+ ) const
+ {
+ #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
+ return detail::as_callable(format)(*this, out);
+ #else
+ return format(*this, out);
+ #endif
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename Callable3>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , Callable3 const &format
+ , regex_constants::match_flag_type flags
+ , mpl::size_t<3>
+ ) const
+ {
+ #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
+ return detail::as_callable(format)(*this, out, flags);
+ #else
+ return format(*this, out, flags);
+ #endif
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename OutputIterator, typename Expr>
+ OutputIterator format_
+ (
+ OutputIterator out
+ , Expr const &format
+ , regex_constants::match_flag_type flags
+ , mpl::size_t<4>
+ ) const
+ {
+ // detail::ReplaceAlgo may be an incomplete type at this point, so
+ // we can't construct it directly.
+ typedef typename mpl::if_c<true, detail::ReplaceAlgo, OutputIterator>::type ReplaceAlgo;
+ return this->format2_(out, ReplaceAlgo()(format, 0, *this));
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_ecma_262_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ {
+ while(cur != end)
+ {
+ switch(*cur)
+ {
+ case BOOST_XPR_CHAR_(char_type, '$'):
+ out = this->format_backref_(++cur, end, out);
+ break;
+
+ default:
+ *out++ = *cur++;
+ break;
+ }
+ }
+
+ return out;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_sed_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ {
+ while(cur != end)
+ {
+ switch(*cur)
+ {
+ case BOOST_XPR_CHAR_(char_type, '&'):
+ ++cur;
+ out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '\\'):
+ out = this->format_escape_(++cur, end, out);
+ break;
+
+ default:
+ *out++ = *cur++;
+ break;
+ }
+ }
+
+ return out;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_perl_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ {
+ detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
+
+ while(cur != end)
+ {
+ switch(*cur)
+ {
+ case BOOST_XPR_CHAR_(char_type, '$'):
+ iout = this->format_backref_(++cur, end, iout);
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '\\'):
+ if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
+ {
+ iout = this->format_named_backref_(++cur, end, iout);
+ }
+ else
+ {
+ iout = this->format_escape_(cur, end, iout);
+ }
+ break;
+
+ default:
+ *iout++ = *cur++;
+ break;
+ }
+ }
+
+ return iout.base();
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_all_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
+ {
+ detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
+ iout = this->format_all_impl_(cur, end, iout);
+ BOOST_XPR_ENSURE_(cur == end
+ , regex_constants::error_paren, "unbalanced parentheses in format string");
+ return iout.base();
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_all_impl_(ForwardIterator &cur, ForwardIterator end, OutputIterator out, bool metacolon = false) const
+ {
+ int max = 0, sub = 0;
+ detail::noop_output_iterator<char_type> noop;
+
+ while(cur != end)
+ {
+ switch(*cur)
+ {
+ case BOOST_XPR_CHAR_(char_type, '$'):
+ out = this->format_backref_(++cur, end, out);
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '\\'):
+ if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
+ {
+ out = this->format_named_backref_(++cur, end, out);
+ }
+ else
+ {
+ out = this->format_escape_(cur, end, out);
+ }
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '('):
+ out = this->format_all_impl_(++cur, end, out);
+ BOOST_XPR_ENSURE_(BOOST_XPR_CHAR_(char_type, ')') == *(cur-1)
+ , regex_constants::error_paren, "unbalanced parentheses in format string");
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, '?'):
+ BOOST_XPR_ENSURE_(++cur != end
+ , regex_constants::error_subreg, "malformed conditional in format string");
+ max = static_cast<int>(this->size() - 1);
+ sub = detail::toi(cur, end, *this->traits_, 10, max);
+ BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
+ if(this->sub_matches_[ sub ].matched)
+ {
+ out = this->format_all_impl_(cur, end, out, true);
+ if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
+ this->format_all_impl_(cur, end, noop);
+ }
+ else
+ {
+ this->format_all_impl_(cur, end, noop, true);
+ if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
+ out = this->format_all_impl_(cur, end, out);
+ }
+ return out;
+
+ case BOOST_XPR_CHAR_(char_type, ':'):
+ if(metacolon)
+ {
+ case BOOST_XPR_CHAR_(char_type, ')'):
+ ++cur;
+ return out;
+ }
+ // else fall-through
+
+ default:
+ *out++ = *cur++;
+ break;
+ }
+ }
+
+ return out;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_backref_
+ (
+ ForwardIterator &cur
+ , ForwardIterator end
+ , OutputIterator out
+ ) const
+ {
+ if(cur == end)
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, '$');
+ }
+ else if(BOOST_XPR_CHAR_(char_type, '$') == *cur)
+ {
+ *out++ = *cur++;
+ }
+ else if(BOOST_XPR_CHAR_(char_type, '&') == *cur) // whole match
+ {
+ ++cur;
+ out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
+ }
+ else if(BOOST_XPR_CHAR_(char_type, '`') == *cur) // prefix
+ {
+ ++cur;
+ out = std::copy(this->prefix().first, this->prefix().second, out);
+ }
+ else if(BOOST_XPR_CHAR_(char_type, '\'') == *cur) // suffix
+ {
+ ++cur;
+ out = std::copy(this->suffix().first, this->suffix().second, out);
+ }
+ else if(-1 != this->traits_->value(*cur, 10)) // a sub-match
+ {
+ int max = static_cast<int>(this->size() - 1);
+ int sub = detail::toi(cur, end, *this->traits_, 10, max);
+ BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
+ if(this->sub_matches_[ sub ].matched)
+ out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
+ }
+ else
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, '$');
+ *out++ = *cur++;
+ }
+
+ return out;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_escape_
+ (
+ ForwardIterator &cur
+ , ForwardIterator end
+ , OutputIterator out
+ ) const
+ {
+ using namespace regex_constants;
+ ForwardIterator tmp;
+ // define an unsigned type the same size as char_type
+ typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
+ BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
+ typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
+ numeric::converter<int, uchar_t, converstion_traits, detail::char_overflow_handler_> converter;
+
+ if(cur == end)
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, '\\');
+ return out;
+ }
+
+ char_type ch = *cur++;
+ switch(ch)
+ {
+ case BOOST_XPR_CHAR_(char_type, 'a'):
+ *out++ = BOOST_XPR_CHAR_(char_type, '\a');
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'e'):
+ *out++ = converter(27);
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'f'):
+ *out++ = BOOST_XPR_CHAR_(char_type, '\f');
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'n'):
+ *out++ = BOOST_XPR_CHAR_(char_type, '\n');
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'r'):
+ *out++ = BOOST_XPR_CHAR_(char_type, '\r');
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 't'):
+ *out++ = BOOST_XPR_CHAR_(char_type, '\t');
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'v'):
+ *out++ = BOOST_XPR_CHAR_(char_type, '\v');
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'x'):
+ BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
+ if(BOOST_XPR_CHAR_(char_type, '{') == *cur)
+ {
+ BOOST_XPR_ENSURE_(++cur != end, error_escape, "unexpected end of format found");
+ tmp = cur;
+ *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xffff));
+ BOOST_XPR_ENSURE_(4 == std::distance(tmp, cur) && cur != end && BOOST_XPR_CHAR_(char_type, '}') == *cur++
+ , error_escape, "invalid hex escape : must be \\x { HexDigit HexDigit HexDigit HexDigit }");
+ }
+ else
+ {
+ tmp = cur;
+ *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xff));
+ BOOST_XPR_ENSURE_(2 == std::distance(tmp, cur), error_escape
+ , "invalid hex escape : must be \\x HexDigit HexDigit");
+ }
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'c'):
+ BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
+ BOOST_XPR_ENSURE_
+ (
+ this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *cur)
+ || this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *cur)
+ , error_escape
+ , "invalid escape control letter; must be one of a-z or A-Z"
+ );
+ // Convert to character according to ECMA-262, section 15.10.2.10:
+ *out++ = converter(*cur % 32);
+ ++cur;
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'l'):
+ if(!set_transform(out, detail::Lower, detail::Next))
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, 'l');
+ }
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'L'):
+ if(!set_transform(out, detail::Lower, detail::Rest))
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, 'L');
+ }
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'u'):
+ if(!set_transform(out, detail::Upper, detail::Next))
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, 'u');
+ }
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'U'):
+ if(!set_transform(out, detail::Upper, detail::Rest))
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, 'U');
+ }
+ break;
+
+ case BOOST_XPR_CHAR_(char_type, 'E'):
+ if(!set_transform(out, detail::None, detail::Rest))
+ {
+ *out++ = BOOST_XPR_CHAR_(char_type, 'E');
+ }
+ break;
+
+ default:
+ // BUGBUG what about backreferences like \12 ?
+ if(0 < this->traits_->value(ch, 10))
+ {
+ int sub = this->traits_->value(ch, 10);
+ if(this->sub_matches_[ sub ].matched)
+ out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
+ }
+ else
+ {
+ *out++ = ch;
+ }
+ break;
+ }
+
+ return out;
+ }
+
+ /// INTERNAL ONLY
+ ///
+ template<typename ForwardIterator, typename OutputIterator>
+ OutputIterator format_named_backref_
+ (
+ ForwardIterator &cur
+ , ForwardIterator end
+ , OutputIterator out
+ ) const
+ {
+ using namespace regex_constants;
+ BOOST_XPR_ENSURE_(cur != end && BOOST_XPR_CHAR_(char_type, '<') == *cur++
+ , error_badmark, "invalid named back-reference");
+ ForwardIterator begin = cur;
+ for(; cur != end && BOOST_XPR_CHAR_(char_type, '>') != *cur; ++cur)
+ {}
+ BOOST_XPR_ENSURE_(cur != begin && cur != end && BOOST_XPR_CHAR_(char_type, '>') == *cur
+ , error_badmark, "invalid named back-reference");
+
+ string_type name(begin, cur++);
+ for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
+ {
+ if(this->named_marks_[i].name_ == name)
+ {
+ std::size_t sub = this->named_marks_[i].mark_nbr_;
+ return std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
+ }
+ }
+
+ BOOST_THROW_EXCEPTION(regex_error(error_badmark, "invalid named back-reference"));
+ // Should never get here
+ return out;
+ }
+
+ regex_id_type regex_id_;
+ detail::sub_match_vector<BidiIter> sub_matches_;
+ boost::optional<BidiIter> base_;
+ boost::optional<sub_match<BidiIter> > prefix_;
+ boost::optional<sub_match<BidiIter> > suffix_;
+ nested_results_type nested_results_;
+ intrusive_ptr<extras_type> extras_ptr_;
+ intrusive_ptr<detail::traits<char_type> const> traits_;
+ detail::action_args_type args_;
+ std::vector<detail::named_mark<char_type> > named_marks_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_id_filter_predicate
+//
+template<typename BidiIter>
+struct regex_id_filter_predicate
+ : std::unary_function<match_results<BidiIter>, bool>
+{
+ regex_id_filter_predicate(regex_id_type regex_id)
+ : regex_id_(regex_id)
+ {
+ }
+
+ bool operator ()(match_results<BidiIter> const &res) const
+ {
+ return this->regex_id_ == res.regex_id();
+ }
+
+private:
+
+ regex_id_type regex_id_;
+};
+
+}} // namespace boost::xpressive
+
+#ifdef BOOST_HAS_CONCEPTS
+// Better living through concepts. :-P
+namespace std
+{
+ template<typename Iter_, typename Char_>
+ concept_map OutputIterator<
+ boost::xpressive::detail::case_converting_iterator<Iter_, Char_>
+ , Char_
+ >
+ {};
+
+ template<typename Char_>
+ concept_map OutputIterator<
+ boost::xpressive::detail::noop_output_iterator<Char_>
+ , Char_
+ >
+ {};
+}
+#endif
+
+#endif
diff --git a/boost/xpressive/regex_actions.hpp b/boost/xpressive/regex_actions.hpp
new file mode 100644
index 0000000000..e22b164a88
--- /dev/null
+++ b/boost/xpressive/regex_actions.hpp
@@ -0,0 +1,973 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_actions.hpp
+/// Defines the syntax elements of xpressive's action expressions.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_ACTIONS_HPP_EAN_03_22_2007
+#define BOOST_XPRESSIVE_ACTIONS_HPP_EAN_03_22_2007
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/ref.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/core/matcher/attr_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/attr_end_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/attr_begin_matcher.hpp>
+#include <boost/xpressive/detail/core/matcher/predicate_matcher.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+// These are very often needed by client code.
+#include <boost/typeof/std/map.hpp>
+#include <boost/typeof/std/string.hpp>
+
+// Doxygen can't handle proto :-(
+#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+# include <boost/proto/core.hpp>
+# include <boost/proto/transform.hpp>
+# include <boost/xpressive/detail/core/matcher/action_matcher.hpp>
+#endif
+
+/// INTERNAL ONLY
+///
+#define UNREF(x) typename remove_reference<x>::type
+
+/// INTERNAL ONLY
+///
+#define UNCVREF(x) typename remove_cv<typename remove_reference<x>::type>::type
+
+#if BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4510) // default constructor could not be generated
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
+#endif
+
+namespace boost
+{
+ namespace detail
+ {
+ // Bit of a hack to make lexical_cast work with wide sub_match
+ template<typename T>
+ struct stream_char;
+
+ template<typename BidiIter>
+ struct stream_char<xpressive::sub_match<BidiIter> >
+ : boost::iterator_value<BidiIter>
+ {};
+ }
+}
+
+namespace boost { namespace xpressive
+{
+
+ namespace detail
+ {
+ template<typename T, typename U>
+ struct action_arg
+ {
+ typedef T type;
+ typedef typename add_reference<T>::type reference;
+
+ reference cast(void *pv) const
+ {
+ return *static_cast<UNREF(T) *>(pv);
+ }
+ };
+
+ template<typename T>
+ struct value_wrapper
+ : private noncopyable
+ {
+ value_wrapper()
+ : value()
+ {}
+
+ value_wrapper(T const &t)
+ : value(t)
+ {}
+
+ T value;
+ };
+
+ struct check_tag
+ {};
+
+ struct BindArg
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename MatchResults, typename Expr>
+ struct result<This(MatchResults, Expr)>
+ {
+ typedef Expr type;
+ };
+
+ template<typename MatchResults, typename Expr>
+ Expr const & operator ()(MatchResults &what, Expr const &expr) const
+ {
+ what.let(expr);
+ return expr;
+ }
+ };
+
+ struct let_tag
+ {};
+
+ // let(_a = b, _c = d)
+ struct BindArgs
+ : proto::function<
+ proto::terminal<let_tag>
+ , proto::vararg<
+ proto::when<
+ proto::assign<proto::_, proto::_>
+ , proto::call<BindArg(proto::_data, proto::_)>
+ >
+ >
+ >
+ {};
+
+ struct let_domain
+ : boost::proto::domain<boost::proto::pod_generator<let_> >
+ {};
+
+ template<typename Expr>
+ struct let_
+ {
+ BOOST_PROTO_BASIC_EXTENDS(Expr, let_<Expr>, let_domain)
+ BOOST_PROTO_EXTENDS_FUNCTION()
+ };
+
+ template<typename Args, typename BidiIter>
+ void bind_args(let_<Args> const &args, match_results<BidiIter> &what)
+ {
+ BindArgs()(args, 0, what);
+ }
+
+ typedef boost::proto::functional::make_expr<proto::tag::function, proto::default_domain> make_function;
+ }
+
+ namespace op
+ {
+ struct at
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Cont, typename Idx>
+ struct result<This(Cont, Idx)>
+ : result<This(Cont const &, Idx)>
+ {
+ };
+
+ template<typename This, typename Cont, typename Idx>
+ struct result<This(Cont &, Idx)>
+ {
+ typedef typename Cont::reference type;
+ };
+
+ template<typename This, typename Cont, typename Idx>
+ struct result<This(Cont const &, Idx)>
+ {
+ typedef typename Cont::const_reference type;
+ };
+
+ template<typename Cont, typename Idx>
+ typename Cont::reference operator()(Cont &c, Idx idx BOOST_PROTO_DISABLE_IF_IS_CONST(Cont)) const
+ {
+ return c[idx];
+ }
+
+ template<typename Cont, typename Idx>
+ typename Cont::const_reference operator()(Cont const &c, Idx idx) const
+ {
+ return c[idx];
+ }
+ };
+
+ struct push
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+
+ template<typename Sequence, typename Value>
+ void operator()(Sequence &seq, Value const &val) const
+ {
+ seq.push(val);
+ }
+ };
+
+ struct push_back
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+
+ template<typename Sequence, typename Value>
+ void operator()(Sequence &seq, Value const &val) const
+ {
+ seq.push_back(val);
+ }
+ };
+
+ struct push_front
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+
+ template<typename Sequence, typename Value>
+ void operator()(Sequence &seq, Value const &val) const
+ {
+ seq.push_front(val);
+ }
+ };
+
+ struct pop
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+
+ template<typename Sequence>
+ void operator()(Sequence &seq) const
+ {
+ seq.pop();
+ }
+ };
+
+ struct pop_back
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+
+ template<typename Sequence>
+ void operator()(Sequence &seq) const
+ {
+ seq.pop_back();
+ }
+ };
+
+ struct pop_front
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+
+ template<typename Sequence>
+ void operator()(Sequence &seq) const
+ {
+ seq.pop_front();
+ }
+ };
+
+ struct front
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Sequence>
+ struct result<This(Sequence)>
+ {
+ typedef UNREF(Sequence) sequence_type;
+ typedef
+ typename mpl::if_c<
+ is_const<sequence_type>::value
+ , typename sequence_type::const_reference
+ , typename sequence_type::reference
+ >::type
+ type;
+ };
+
+ template<typename Sequence>
+ typename result<front(Sequence &)>::type operator()(Sequence &seq) const
+ {
+ return seq.front();
+ }
+ };
+
+ struct back
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Sequence>
+ struct result<This(Sequence)>
+ {
+ typedef UNREF(Sequence) sequence_type;
+ typedef
+ typename mpl::if_c<
+ is_const<sequence_type>::value
+ , typename sequence_type::const_reference
+ , typename sequence_type::reference
+ >::type
+ type;
+ };
+
+ template<typename Sequence>
+ typename result<back(Sequence &)>::type operator()(Sequence &seq) const
+ {
+ return seq.back();
+ }
+ };
+
+ struct top
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Sequence>
+ struct result<This(Sequence)>
+ {
+ typedef UNREF(Sequence) sequence_type;
+ typedef
+ typename mpl::if_c<
+ is_const<sequence_type>::value
+ , typename sequence_type::value_type const &
+ , typename sequence_type::value_type &
+ >::type
+ type;
+ };
+
+ template<typename Sequence>
+ typename result<top(Sequence &)>::type operator()(Sequence &seq) const
+ {
+ return seq.top();
+ }
+ };
+
+ struct first
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Pair>
+ struct result<This(Pair)>
+ {
+ typedef UNREF(Pair)::first_type type;
+ };
+
+ template<typename Pair>
+ typename Pair::first_type operator()(Pair const &p) const
+ {
+ return p.first;
+ }
+ };
+
+ struct second
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Pair>
+ struct result<This(Pair)>
+ {
+ typedef UNREF(Pair)::second_type type;
+ };
+
+ template<typename Pair>
+ typename Pair::second_type operator()(Pair const &p) const
+ {
+ return p.second;
+ }
+ };
+
+ struct matched
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef bool result_type;
+
+ template<typename Sub>
+ bool operator()(Sub const &sub) const
+ {
+ return sub.matched;
+ }
+ };
+
+ struct length
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Sub>
+ struct result<This(Sub)>
+ {
+ typedef UNREF(Sub)::difference_type type;
+ };
+
+ template<typename Sub>
+ typename Sub::difference_type operator()(Sub const &sub) const
+ {
+ return sub.length();
+ }
+ };
+
+ struct str
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Sub>
+ struct result<This(Sub)>
+ {
+ typedef UNREF(Sub)::string_type type;
+ };
+
+ template<typename Sub>
+ typename Sub::string_type operator()(Sub const &sub) const
+ {
+ return sub.str();
+ }
+ };
+
+ // This codifies the return types of the various insert member
+ // functions found in sequence containers, the 2 flavors of
+ // associative containers, and strings.
+ struct insert
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig, typename EnableIf = void>
+ struct result
+ {};
+
+ // assoc containers
+ template<typename This, typename Cont, typename Value>
+ struct result<This(Cont, Value), void>
+ {
+ typedef UNREF(Cont) cont_type;
+ typedef UNREF(Value) value_type;
+ static cont_type &scont_;
+ static value_type &svalue_;
+ typedef char yes_type;
+ typedef char (&no_type)[2];
+ static yes_type check_insert_return(typename cont_type::iterator);
+ static no_type check_insert_return(std::pair<typename cont_type::iterator, bool>);
+ BOOST_STATIC_CONSTANT(bool, is_iterator = (sizeof(yes_type) == sizeof(check_insert_return(scont_.insert(svalue_)))));
+ typedef
+ typename mpl::if_c<
+ is_iterator
+ , typename cont_type::iterator
+ , std::pair<typename cont_type::iterator, bool>
+ >::type
+ type;
+ };
+
+ // sequence containers, assoc containers, strings
+ template<typename This, typename Cont, typename It, typename Value>
+ struct result<This(Cont, It, Value),
+ typename disable_if<mpl::or_<is_integral<UNCVREF(It)>, is_same<UNCVREF(It), UNCVREF(Value)> > >::type>
+ {
+ typedef UNREF(Cont)::iterator type;
+ };
+
+ // strings
+ template<typename This, typename Cont, typename Size, typename T>
+ struct result<This(Cont, Size, T),
+ typename enable_if<is_integral<UNCVREF(Size)> >::type>
+ {
+ typedef UNREF(Cont) &type;
+ };
+
+ // assoc containers
+ template<typename This, typename Cont, typename It>
+ struct result<This(Cont, It, It), void>
+ {
+ typedef void type;
+ };
+
+ // sequence containers, strings
+ template<typename This, typename Cont, typename It, typename Size, typename Value>
+ struct result<This(Cont, It, Size, Value),
+ typename disable_if<is_integral<UNCVREF(It)> >::type>
+ {
+ typedef void type;
+ };
+
+ // strings
+ template<typename This, typename Cont, typename Size, typename A0, typename A1>
+ struct result<This(Cont, Size, A0, A1),
+ typename enable_if<is_integral<UNCVREF(Size)> >::type>
+ {
+ typedef UNREF(Cont) &type;
+ };
+
+ /// operator()
+ ///
+ template<typename Cont, typename A0>
+ typename result<insert(Cont &, A0 const &)>::type
+ operator()(Cont &cont, A0 const &a0) const
+ {
+ return cont.insert(a0);
+ }
+
+ /// \overload
+ ///
+ template<typename Cont, typename A0, typename A1>
+ typename result<insert(Cont &, A0 const &, A1 const &)>::type
+ operator()(Cont &cont, A0 const &a0, A1 const &a1) const
+ {
+ return cont.insert(a0, a1);
+ }
+
+ /// \overload
+ ///
+ template<typename Cont, typename A0, typename A1, typename A2>
+ typename result<insert(Cont &, A0 const &, A1 const &, A2 const &)>::type
+ operator()(Cont &cont, A0 const &a0, A1 const &a1, A2 const &a2) const
+ {
+ return cont.insert(a0, a1, a2);
+ }
+ };
+
+ struct make_pair
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename First, typename Second>
+ struct result<This(First, Second)>
+ {
+ typedef std::pair<UNCVREF(First), UNCVREF(Second)> type;
+ };
+
+ template<typename First, typename Second>
+ std::pair<First, Second> operator()(First const &first, Second const &second) const
+ {
+ return std::make_pair(first, second);
+ }
+ };
+
+ template<typename T>
+ struct as
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef T result_type;
+
+ template<typename Value>
+ T operator()(Value const &val) const
+ {
+ return lexical_cast<T>(val);
+ }
+ };
+
+ template<typename T>
+ struct static_cast_
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef T result_type;
+
+ template<typename Value>
+ T operator()(Value const &val) const
+ {
+ return static_cast<T>(val);
+ }
+ };
+
+ template<typename T>
+ struct dynamic_cast_
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef T result_type;
+
+ template<typename Value>
+ T operator()(Value const &val) const
+ {
+ return dynamic_cast<T>(val);
+ }
+ };
+
+ template<typename T>
+ struct const_cast_
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef T result_type;
+
+ template<typename Value>
+ T operator()(Value const &val) const
+ {
+ return const_cast<T>(val);
+ }
+ };
+
+ template<typename T>
+ struct construct
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef T result_type;
+
+ T operator()() const
+ {
+ return T();
+ }
+
+ template<typename A0>
+ T operator()(A0 const &a0) const
+ {
+ return T(a0);
+ }
+
+ template<typename A0, typename A1>
+ T operator()(A0 const &a0, A1 const &a1) const
+ {
+ return T(a0, a1);
+ }
+
+ template<typename A0, typename A1, typename A2>
+ T operator()(A0 const &a0, A1 const &a1, A2 const &a2) const
+ {
+ return T(a0, a1, a2);
+ }
+ };
+
+ template<typename Except>
+ struct throw_
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+
+ void operator()() const
+ {
+ BOOST_THROW_EXCEPTION(Except());
+ }
+
+ template<typename A0>
+ void operator()(A0 const &a0) const
+ {
+ BOOST_THROW_EXCEPTION(Except(a0));
+ }
+
+ template<typename A0, typename A1>
+ void operator()(A0 const &a0, A1 const &a1) const
+ {
+ BOOST_THROW_EXCEPTION(Except(a0, a1));
+ }
+
+ template<typename A0, typename A1, typename A2>
+ void operator()(A0 const &a0, A1 const &a1, A2 const &a2) const
+ {
+ BOOST_THROW_EXCEPTION(Except(a0, a1, a2));
+ }
+ };
+
+ struct unwrap_reference
+ {
+ BOOST_PROTO_CALLABLE()
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Ref>
+ struct result<This(Ref)>
+ {
+ typedef typename boost::unwrap_reference<Ref>::type &type;
+ };
+
+ template<typename This, typename Ref>
+ struct result<This(Ref &)>
+ {
+ typedef typename boost::unwrap_reference<Ref>::type &type;
+ };
+
+ template<typename T>
+ T &operator()(boost::reference_wrapper<T> r) const
+ {
+ return static_cast<T &>(r);
+ }
+ };
+ }
+
+ template<typename Fun>
+ struct function
+ {
+ typedef typename proto::terminal<Fun>::type type;
+ };
+
+ function<op::at>::type const at = {{}};
+ function<op::push>::type const push = {{}};
+ function<op::push_back>::type const push_back = {{}};
+ function<op::push_front>::type const push_front = {{}};
+ function<op::pop>::type const pop = {{}};
+ function<op::pop_back>::type const pop_back = {{}};
+ function<op::pop_front>::type const pop_front = {{}};
+ function<op::top>::type const top = {{}};
+ function<op::back>::type const back = {{}};
+ function<op::front>::type const front = {{}};
+ function<op::first>::type const first = {{}};
+ function<op::second>::type const second = {{}};
+ function<op::matched>::type const matched = {{}};
+ function<op::length>::type const length = {{}};
+ function<op::str>::type const str = {{}};
+ function<op::insert>::type const insert = {{}};
+ function<op::make_pair>::type const make_pair = {{}};
+ function<op::unwrap_reference>::type const unwrap_reference = {{}};
+
+ template<typename T>
+ struct value
+ : proto::extends<typename proto::terminal<T>::type, value<T> >
+ {
+ typedef proto::extends<typename proto::terminal<T>::type, value<T> > base_type;
+
+ value()
+ : base_type()
+ {}
+
+ explicit value(T const &t)
+ : base_type(base_type::proto_base_expr::make(t))
+ {}
+
+ using base_type::operator =;
+
+ T &get()
+ {
+ return proto::value(*this);
+ }
+
+ T const &get() const
+ {
+ return proto::value(*this);
+ }
+ };
+
+ template<typename T>
+ struct reference
+ : proto::extends<typename proto::terminal<reference_wrapper<T> >::type, reference<T> >
+ {
+ typedef proto::extends<typename proto::terminal<reference_wrapper<T> >::type, reference<T> > base_type;
+
+ explicit reference(T &t)
+ : base_type(base_type::proto_base_expr::make(boost::ref(t)))
+ {}
+
+ using base_type::operator =;
+
+ T &get() const
+ {
+ return proto::value(*this).get();
+ }
+ };
+
+ template<typename T>
+ struct local
+ : detail::value_wrapper<T>
+ , proto::terminal<reference_wrapper<T> >::type
+ {
+ typedef typename proto::terminal<reference_wrapper<T> >::type base_type;
+
+ local()
+ : detail::value_wrapper<T>()
+ , base_type(base_type::make(boost::ref(detail::value_wrapper<T>::value)))
+ {}
+
+ explicit local(T const &t)
+ : detail::value_wrapper<T>(t)
+ , base_type(base_type::make(boost::ref(detail::value_wrapper<T>::value)))
+ {}
+
+ using base_type::operator =;
+
+ T &get()
+ {
+ return proto::value(*this);
+ }
+
+ T const &get() const
+ {
+ return proto::value(*this);
+ }
+ };
+
+ /// as (a.k.a., lexical_cast)
+ ///
+ template<typename X2_0, typename A0>
+ typename detail::make_function::impl<op::as<X2_0> const, A0 const &>::result_type const
+ as(A0 const &a0)
+ {
+ return detail::make_function::impl<op::as<X2_0> const, A0 const &>()((op::as<X2_0>()), a0);
+ }
+
+ /// static_cast_
+ ///
+ template<typename X2_0, typename A0>
+ typename detail::make_function::impl<op::static_cast_<X2_0> const, A0 const &>::result_type const
+ static_cast_(A0 const &a0)
+ {
+ return detail::make_function::impl<op::static_cast_<X2_0> const, A0 const &>()((op::static_cast_<X2_0>()), a0);
+ }
+
+ /// dynamic_cast_
+ ///
+ template<typename X2_0, typename A0>
+ typename detail::make_function::impl<op::dynamic_cast_<X2_0> const, A0 const &>::result_type const
+ dynamic_cast_(A0 const &a0)
+ {
+ return detail::make_function::impl<op::dynamic_cast_<X2_0> const, A0 const &>()((op::dynamic_cast_<X2_0>()), a0);
+ }
+
+ /// const_cast_
+ ///
+ template<typename X2_0, typename A0>
+ typename detail::make_function::impl<op::const_cast_<X2_0> const, A0 const &>::result_type const
+ const_cast_(A0 const &a0)
+ {
+ return detail::make_function::impl<op::const_cast_<X2_0> const, A0 const &>()((op::const_cast_<X2_0>()), a0);
+ }
+
+ /// val()
+ ///
+ template<typename T>
+ value<T> const val(T const &t)
+ {
+ return value<T>(t);
+ }
+
+ /// ref()
+ ///
+ template<typename T>
+ reference<T> const ref(T &t)
+ {
+ return reference<T>(t);
+ }
+
+ /// cref()
+ ///
+ template<typename T>
+ reference<T const> const cref(T const &t)
+ {
+ return reference<T const>(t);
+ }
+
+ /// check(), for testing custom assertions
+ ///
+ proto::terminal<detail::check_tag>::type const check = {{}};
+
+ /// let(), for binding references to non-local variables
+ ///
+ detail::let_<proto::terminal<detail::let_tag>::type> const let = {{{}}};
+
+ /// placeholder<T>, for defining a placeholder to stand in fo
+ /// a variable of type T in a semantic action.
+ ///
+ template<typename T, int I, typename Dummy>
+ struct placeholder
+ {
+ typedef placeholder<T, I, Dummy> this_type;
+ typedef typename proto::terminal<detail::action_arg<T, mpl::int_<I> > >::type action_arg_type;
+
+ BOOST_PROTO_EXTENDS(action_arg_type, this_type, proto::default_domain)
+ };
+
+ /// Usage: construct\<Type\>(arg1, arg2)
+ ///
+ /// Usage: throw_\<Exception\>(arg1, arg2)
+ ///
+ #define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, A_const_ref_a, a)\
+ \
+ template<typename X2_0 BOOST_PP_COMMA_IF(N) typename_A(N)>\
+ typename detail::make_function::impl<op::construct<X2_0> const BOOST_PP_COMMA_IF(N) A_const_ref(N)>::result_type const\
+ construct(A_const_ref_a(N))\
+ {\
+ return detail::make_function::impl<op::construct<X2_0> const BOOST_PP_COMMA_IF(N) A_const_ref(N)>()((op::construct<X2_0>()) BOOST_PP_COMMA_IF(N) a(N));\
+ }\
+ \
+ template<typename X2_0 BOOST_PP_COMMA_IF(N) typename_A(N)>\
+ typename detail::make_function::impl<op::throw_<X2_0> const BOOST_PP_COMMA_IF(N) A_const_ref(N)>::result_type const\
+ throw_(A_const_ref_a(N))\
+ {\
+ return detail::make_function::impl<op::throw_<X2_0> const BOOST_PP_COMMA_IF(N) A_const_ref(N)>()((op::throw_<X2_0>()) BOOST_PP_COMMA_IF(N) a(N));\
+ }\
+ /**/
+
+ #define BOOST_PROTO_LOCAL_a BOOST_PROTO_a
+ #define BOOST_PROTO_LOCAL_LIMITS (0, BOOST_PP_DEC(BOOST_PROTO_MAX_ARITY))
+ #include BOOST_PROTO_LOCAL_ITERATE()
+
+ namespace detail
+ {
+ inline void ignore_unused_regex_actions()
+ {
+ detail::ignore_unused(xpressive::at);
+ detail::ignore_unused(xpressive::push);
+ detail::ignore_unused(xpressive::push_back);
+ detail::ignore_unused(xpressive::push_front);
+ detail::ignore_unused(xpressive::pop);
+ detail::ignore_unused(xpressive::pop_back);
+ detail::ignore_unused(xpressive::pop_front);
+ detail::ignore_unused(xpressive::top);
+ detail::ignore_unused(xpressive::back);
+ detail::ignore_unused(xpressive::front);
+ detail::ignore_unused(xpressive::first);
+ detail::ignore_unused(xpressive::second);
+ detail::ignore_unused(xpressive::matched);
+ detail::ignore_unused(xpressive::length);
+ detail::ignore_unused(xpressive::str);
+ detail::ignore_unused(xpressive::insert);
+ detail::ignore_unused(xpressive::make_pair);
+ detail::ignore_unused(xpressive::unwrap_reference);
+ detail::ignore_unused(xpressive::check);
+ detail::ignore_unused(xpressive::let);
+ }
+
+ struct mark_nbr
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef int result_type;
+
+ int operator()(mark_placeholder m) const
+ {
+ return m.mark_number_;
+ }
+ };
+
+ struct ReplaceAlgo
+ : proto::or_<
+ proto::when<
+ proto::terminal<mark_placeholder>
+ , op::at(proto::_data, proto::call<mark_nbr(proto::_value)>)
+ >
+ , proto::when<
+ proto::terminal<any_matcher>
+ , op::at(proto::_data, proto::size_t<0>)
+ >
+ , proto::when<
+ proto::terminal<reference_wrapper<proto::_> >
+ , op::unwrap_reference(proto::_value)
+ >
+ , proto::_default<ReplaceAlgo>
+ >
+ {};
+ }
+}}
+
+#undef UNREF
+#undef UNCVREF
+
+#if BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_XPRESSIVE_ACTIONS_HPP_EAN_03_22_2007
diff --git a/boost/xpressive/regex_algorithms.hpp b/boost/xpressive/regex_algorithms.hpp
new file mode 100644
index 0000000000..9e934c495e
--- /dev/null
+++ b/boost/xpressive/regex_algorithms.hpp
@@ -0,0 +1,994 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_algorithms.hpp
+/// Contains the regex_match(), regex_search() and regex_replace() algorithms.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_ALGORITHMS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_ALGORITHMS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <string>
+#include <iterator>
+#include <boost/mpl/or.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/xpressive/match_results.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/state.hpp>
+#include <boost/xpressive/detail/utility/save_restore.hpp>
+
+/// INTERNAL ONLY
+///
+#define BOOST_XPR_NONDEDUCED_TYPE_(x) typename mpl::identity<x>::type
+
+namespace boost { namespace xpressive
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_match
+///////////////////////////////////////////////////////////////////////////////
+
+namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // regex_match_impl
+ template<typename BidiIter>
+ inline bool regex_match_impl
+ (
+ BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end
+ , match_results<BidiIter> &what
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ )
+ {
+ typedef detail::core_access<BidiIter> access;
+ BOOST_ASSERT(0 != re.regex_id());
+
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ state.flags_.match_all_ = true;
+ state.sub_match(0).begin_ = begin;
+
+ if(access::match(re, state))
+ {
+ access::set_prefix_suffix(what, begin, end);
+ return true;
+ }
+
+ // handle partial matches
+ else if(state.found_partial_match_ && 0 != (flags & regex_constants::match_partial))
+ {
+ state.set_partial_match();
+ return true;
+ }
+
+ access::reset(what);
+ return false;
+ }
+} // namespace detail
+
+/// \brief See if a regex matches a sequence from beginning to end.
+///
+/// Determines whether there is an exact match between the regular expression \c re,
+/// and all of the sequence <tt>[begin, end)</tt>.
+///
+/// \pre Type \c BidiIter meets the requirements of a Bidirectional Iterator (24.1.4).
+/// \pre <tt>[begin,end)</tt> denotes a valid iterator range.
+/// \param begin The beginning of the sequence.
+/// \param end The end of the sequence.
+/// \param what The \c match_results struct into which the sub_matches will be written
+/// \param re The regular expression object to use
+/// \param flags Optional match flags, used to control how the expression is matched
+/// against the sequence. (See \c match_flag_type.)
+/// \return \c true if a match is found, \c false otherwise
+/// \throw regex_error on stack exhaustion
+template<typename BidiIter>
+inline bool regex_match
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end
+ , match_results<BidiIter> &what
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+/// \overload
+///
+template<typename BidiIter>
+inline bool regex_match
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<BidiIter> what;
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+/// \overload
+///
+template<typename Char>
+inline bool regex_match
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin
+ , match_results<Char *> &what
+ , basic_regex<Char *> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ typedef detail::core_access<Char *> access;
+
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ typedef typename remove_const<Char>::type char_type;
+ Char *end = begin + std::char_traits<char_type>::length(begin);
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_match
+(
+ BidiRange &rng
+ , match_results<BidiIter> &what
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_match
+(
+ BidiRange const &rng
+ , match_results<BidiIter> &what
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+/// \overload
+///
+template<typename Char>
+inline bool regex_match
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin
+ , basic_regex<Char *> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<Char *> what;
+ typedef typename remove_const<Char>::type char_type;
+ Char *end = begin + std::char_traits<char_type>::length(begin);
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_match
+(
+ BidiRange &rng
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<BidiIter> what;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_match
+(
+ BidiRange const &rng
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<BidiIter> what;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ return detail::regex_match_impl(begin, end, what, re, flags);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_search
+///////////////////////////////////////////////////////////////////////////////
+
+namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // regex_search_impl
+ template<typename BidiIter>
+ inline bool regex_search_impl
+ (
+ match_state<BidiIter> &state
+ , basic_regex<BidiIter> const &re
+ , bool not_initial_null = false
+ )
+ {
+ typedef core_access<BidiIter> access;
+ typedef typename iterator_value<BidiIter>::type char_type;
+ match_results<BidiIter> &what = *state.context_.results_ptr_;
+ BOOST_ASSERT(0 != re.regex_id());
+
+ bool const partial_ok = state.flags_.match_partial_;
+ save_restore<bool> not_null(state.flags_.match_not_null_, state.flags_.match_not_null_ || not_initial_null);
+ state.flags_.match_prev_avail_ = state.flags_.match_prev_avail_ || !state.bos();
+
+ regex_impl<BidiIter> const &impl = *access::get_regex_impl(re);
+ BidiIter const begin = state.cur_, end = state.end_;
+ BidiIter &sub0begin = state.sub_match(0).begin_;
+ sub0begin = state.cur_;
+
+ // If match_continuous is set, we only need to check for a match at the current position
+ if(state.flags_.match_continuous_)
+ {
+ if(access::match(re, state))
+ {
+ access::set_prefix_suffix(what, begin, end);
+ return true;
+ }
+
+ // handle partial matches
+ else if(partial_ok && state.found_partial_match_)
+ {
+ state.set_partial_match();
+ return true;
+ }
+ }
+
+ // If we have a finder, use it to find where a potential match can start
+ else if(impl.finder_ && (!partial_ok || impl.finder_->ok_for_partial_matches()))
+ {
+ finder<BidiIter> const &find = *impl.finder_;
+ if(find(state))
+ {
+ if(state.cur_ != begin)
+ {
+ not_null.restore();
+ }
+
+ do
+ {
+ sub0begin = state.cur_;
+ if(access::match(re, state))
+ {
+ access::set_prefix_suffix(what, begin, end);
+ return true;
+ }
+
+ // handle partial matches
+ else if(partial_ok && state.found_partial_match_)
+ {
+ state.set_partial_match();
+ return true;
+ }
+
+ BOOST_ASSERT(state.cur_ == sub0begin);
+ not_null.restore();
+ }
+ while(state.cur_ != state.end_ && (++state.cur_, find(state)));
+ }
+ }
+
+ // Otherwise, use brute force search at every position.
+ else
+ {
+ for(;;)
+ {
+ if(access::match(re, state))
+ {
+ access::set_prefix_suffix(what, begin, end);
+ return true;
+ }
+
+ // handle partial matches
+ else if(partial_ok && state.found_partial_match_)
+ {
+ state.set_partial_match();
+ return true;
+ }
+
+ else if(end == sub0begin)
+ {
+ break;
+ }
+
+ BOOST_ASSERT(state.cur_ == sub0begin);
+ state.cur_ = ++sub0begin;
+ not_null.restore();
+ }
+ }
+
+ access::reset(what);
+ return false;
+ }
+} // namespace detail
+
+
+/// \brief Determines whether there is some sub-sequence within <tt>[begin,end)</tt>
+/// that matches the regular expression \c re.
+///
+/// Determines whether there is some sub-sequence within <tt>[begin,end)</tt> that matches
+/// the regular expression \c re.
+///
+/// \pre Type \c BidiIter meets the requirements of a Bidirectional Iterator (24.1.4).
+/// \pre <tt>[begin,end)</tt> denotes a valid iterator range.
+/// \param begin The beginning of the sequence
+/// \param end The end of the sequence
+/// \param what The \c match_results struct into which the sub_matches will be written
+/// \param re The regular expression object to use
+/// \param flags Optional match flags, used to control how the expression is matched against
+/// the sequence. (See \c match_flag_type.)
+/// \return \c true if a match is found, \c false otherwise
+/// \throw regex_error on stack exhaustion
+template<typename BidiIter>
+inline bool regex_search
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end
+ , match_results<BidiIter> &what
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+/// \overload
+///
+template<typename BidiIter>
+inline bool regex_search
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<BidiIter> what;
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+/// \overload
+///
+template<typename Char>
+inline bool regex_search
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin
+ , match_results<Char *> &what
+ , basic_regex<Char *> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ typedef detail::core_access<Char *> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ typedef typename remove_const<Char>::type char_type;
+ Char *end = begin + std::char_traits<char_type>::length(begin);
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<Char *> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_search
+(
+ BidiRange &rng
+ , match_results<BidiIter> &what
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_search
+(
+ BidiRange const &rng
+ , match_results<BidiIter> &what
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ access::reset(what);
+ return false;
+ }
+
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+/// \overload
+///
+template<typename Char>
+inline bool regex_search
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin
+ , basic_regex<Char *> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ typedef detail::core_access<Char *> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<Char *> what;
+ // BUGBUG this is inefficient
+ typedef typename remove_const<Char>::type char_type;
+ Char *end = begin + std::char_traits<char_type>::length(begin);
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<Char *> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_search
+(
+ BidiRange &rng
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<BidiIter> what;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+/// \overload
+///
+template<typename BidiRange, typename BidiIter>
+inline bool regex_search
+(
+ BidiRange const &rng
+ , basic_regex<BidiIter> const &re
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0
+)
+{
+ typedef detail::core_access<BidiIter> access;
+
+ // a default-constructed regex matches nothing
+ if(0 == re.regex_id())
+ {
+ return false;
+ }
+
+ // BUGBUG this is inefficient
+ match_results<BidiIter> what;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(rng), end = boost::end(rng);
+ // the state object holds matching state and
+ // is passed by reference to all the matchers
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ return detail::regex_search_impl(state, re);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_replace
+///////////////////////////////////////////////////////////////////////////////
+
+namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // regex_replace_impl
+ template<typename OutIter, typename BidiIter, typename Formatter>
+ inline OutIter regex_replace_impl
+ (
+ OutIter out
+ , BidiIter begin
+ , BidiIter end
+ , basic_regex<BidiIter> const &re
+ , Formatter const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ )
+ {
+ using namespace regex_constants;
+ typedef detail::core_access<BidiIter> access;
+ BOOST_ASSERT(0 != re.regex_id());
+
+ BidiIter cur = begin;
+ match_results<BidiIter> what;
+ detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
+ bool const yes_copy = (0 == (flags & format_no_copy));
+
+ if(detail::regex_search_impl(state, re))
+ {
+ if(yes_copy)
+ {
+ out = std::copy(cur, what[0].first, out);
+ }
+
+ out = what.format(out, format, flags);
+ cur = state.cur_ = state.next_search_ = what[0].second;
+
+ if(0 == (flags & format_first_only))
+ {
+ bool not_null = (0 == what.length());
+ state.reset(what, *access::get_regex_impl(re));
+ while(detail::regex_search_impl(state, re, not_null))
+ {
+ if(yes_copy)
+ {
+ out = std::copy(cur, what[0].first, out);
+ }
+
+ access::set_prefix_suffix(what, begin, end);
+ out = what.format(out, format, flags);
+ cur = state.cur_ = state.next_search_ = what[0].second;
+ not_null = (0 == what.length());
+ state.reset(what, *access::get_regex_impl(re));
+ }
+ }
+ }
+
+ if(yes_copy)
+ {
+ out = std::copy(cur, end, out);
+ }
+
+ return out;
+ }
+} // namespace detail
+
+/// \brief Build an output sequence given an input sequence, a regex, and a format string or
+/// a formatter object, function, or expression.
+///
+/// Constructs a \c regex_iterator object: <tt>regex_iterator\< BidiIter \> i(begin, end, re, flags)</tt>,
+/// and uses \c i to enumerate through all of the matches m of type <tt>match_results\< BidiIter \></tt> that
+/// occur within the sequence <tt>[begin, end)</tt>. If no such matches are found and <tt>!(flags \& format_no_copy)</tt>
+/// then calls <tt>std::copy(begin, end, out)</tt>. Otherwise, for each match found, if <tt>!(flags \& format_no_copy)</tt>
+/// calls <tt>std::copy(m.prefix().first, m.prefix().second, out)</tt>, and then calls <tt>m.format(out, format, flags)</tt>.
+/// Finally if <tt>!(flags \& format_no_copy)</tt> calls <tt>std::copy(last_m.suffix().first, last_m.suffix().second, out)</tt>
+/// where \c last_m is a copy of the last match found.
+///
+/// If <tt>flags \& format_first_only</tt> is non-zero then only the first match found is replaced.
+///
+/// \pre Type \c BidiIter meets the requirements of a Bidirectional Iterator (24.1.4).
+/// \pre Type \c OutIter meets the requirements of an Output Iterator (24.1.2).
+/// \pre Type \c Formatter models \c ForwardRange, <tt>Callable\<match_results\<BidiIter\> \></tt>,
+/// <tt>Callable\<match_results\<BidiIter\>, OutIter\></tt>, or
+/// <tt>Callable\<match_results\<BidiIter\>, OutIter, regex_constants::match_flag_type\></tt>;
+/// or else it is a null-terminated format string, or an expression template
+/// representing a formatter lambda expression.
+/// \pre <tt>[begin,end)</tt> denotes a valid iterator range.
+/// \param out An output iterator into which the output sequence is written.
+/// \param begin The beginning of the input sequence.
+/// \param end The end of the input sequence.
+/// \param re The regular expression object to use.
+/// \param format The format string used to format the replacement sequence,
+/// or a formatter function, function object, or expression.
+/// \param flags Optional match flags, used to control how the expression is matched against
+/// the sequence. (See \c match_flag_type.)
+/// \return The value of the output iterator after the output sequence has been written to it.
+/// \throw regex_error on stack exhaustion or invalid format string.
+template<typename OutIter, typename BidiIter, typename Formatter>
+inline OutIter regex_replace
+(
+ OutIter out
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end
+ , basic_regex<BidiIter> const &re
+ , Formatter const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<Formatter> >::type * = 0
+)
+{
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ out = std::copy(begin, end, out);
+ }
+
+ return out;
+ }
+
+ return detail::regex_replace_impl(out, begin, end, re, format, flags);
+}
+
+/// \overload
+///
+template<typename OutIter, typename BidiIter>
+inline OutIter regex_replace
+(
+ OutIter out
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin
+ , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end
+ , basic_regex<BidiIter> const &re
+ , typename iterator_value<BidiIter>::type const *format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ out = std::copy(begin, end, out);
+ }
+
+ return out;
+ }
+
+ return detail::regex_replace_impl(out, begin, end, re, format, flags);
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter, typename Formatter>
+inline BidiContainer regex_replace
+(
+ BidiContainer &str
+ , basic_regex<BidiIter> const &re
+ , Formatter const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<mpl::or_<detail::is_char_ptr<BidiContainer>, detail::is_char_ptr<Formatter> > >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ std::copy(begin, end, std::back_inserter(result));
+ }
+
+ return result;
+ }
+
+ detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter, typename Formatter>
+inline BidiContainer regex_replace
+(
+ BidiContainer const &str
+ , basic_regex<BidiIter> const &re
+ , Formatter const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<mpl::or_<detail::is_char_ptr<BidiContainer>, detail::is_char_ptr<Formatter> > >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ std::copy(begin, end, std::back_inserter(result));
+ }
+
+ return result;
+ }
+
+ detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename Char, typename Formatter>
+inline std::basic_string<typename remove_const<Char>::type> regex_replace
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *str
+ , basic_regex<Char *> const &re
+ , Formatter const &format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<Formatter> >::type * = 0
+)
+{
+ typedef typename remove_const<Char>::type char_type;
+ std::basic_string<char_type> result;
+
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ result = str;
+ }
+
+ return result;
+ }
+
+ Char *end = str + std::char_traits<char_type>::length(str);
+ detail::regex_replace_impl(std::back_inserter(result), str, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter>
+inline BidiContainer regex_replace
+(
+ BidiContainer &str
+ , basic_regex<BidiIter> const &re
+ , typename iterator_value<BidiIter>::type const *format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiContainer> >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ std::copy(begin, end, std::back_inserter(result));
+ }
+
+ return result;
+ }
+
+ detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename BidiContainer, typename BidiIter>
+inline BidiContainer regex_replace
+(
+ BidiContainer const &str
+ , basic_regex<BidiIter> const &re
+ , typename iterator_value<BidiIter>::type const *format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , typename disable_if<detail::is_char_ptr<BidiContainer> >::type * = 0
+)
+{
+ BidiContainer result;
+ // Note that the result iterator of the range must be convertible
+ // to BidiIter here.
+ BidiIter begin = boost::begin(str), end = boost::end(str);
+
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ std::copy(begin, end, std::back_inserter(result));
+ }
+
+ return result;
+ }
+
+ detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags);
+ return result;
+}
+
+/// \overload
+///
+template<typename Char>
+inline std::basic_string<typename remove_const<Char>::type> regex_replace
+(
+ BOOST_XPR_NONDEDUCED_TYPE_(Char) *str
+ , basic_regex<Char *> const &re
+ , typename add_const<Char>::type *format
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+)
+{
+ typedef typename remove_const<Char>::type char_type;
+ std::basic_string<char_type> result;
+
+ // Default-constructed regexes match nothing
+ if(0 == re.regex_id())
+ {
+ if((0 == (flags & regex_constants::format_no_copy)))
+ {
+ result = str;
+ }
+
+ return result;
+ }
+
+ Char *end = str + std::char_traits<char_type>::length(str);
+ detail::regex_replace_impl(std::back_inserter(result), str, end, re, format, flags);
+ return result;
+}
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/regex_compiler.hpp b/boost/xpressive/regex_compiler.hpp
new file mode 100644
index 0000000000..4a2a9d7436
--- /dev/null
+++ b/boost/xpressive/regex_compiler.hpp
@@ -0,0 +1,744 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_compiler.hpp
+/// Contains the definition of regex_compiler, a factory for building regex objects
+/// from strings.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_REGEX_COMPILER_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_REGEX_COMPILER_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <map>
+#include <boost/assert.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/xpressive/basic_regex.hpp>
+#include <boost/xpressive/detail/dynamic/parser.hpp>
+#include <boost/xpressive/detail/dynamic/parse_charset.hpp>
+#include <boost/xpressive/detail/dynamic/parser_enum.hpp>
+#include <boost/xpressive/detail/dynamic/parser_traits.hpp>
+#include <boost/xpressive/detail/core/linker.hpp>
+#include <boost/xpressive/detail/core/optimize.hpp>
+
+namespace boost { namespace xpressive
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_compiler
+//
+/// \brief Class template regex_compiler is a factory for building basic_regex objects from a string.
+///
+/// Class template regex_compiler is used to construct a basic_regex object from a string. The string
+/// should contain a valid regular expression. You can imbue a regex_compiler object with a locale,
+/// after which all basic_regex objects created with that regex_compiler object will use that locale.
+/// After creating a regex_compiler object, and optionally imbueing it with a locale, you can call the
+/// compile() method to construct a basic_regex object, passing it the string representing the regular
+/// expression. You can call compile() multiple times on the same regex_compiler object. Two basic_regex
+/// objects compiled from the same string will have different regex_id's.
+template<typename BidiIter, typename RegexTraits, typename CompilerTraits>
+struct regex_compiler
+{
+ typedef BidiIter iterator_type;
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef regex_constants::syntax_option_type flag_type;
+ typedef RegexTraits traits_type;
+ typedef typename traits_type::string_type string_type;
+ typedef typename traits_type::locale_type locale_type;
+ typedef typename traits_type::char_class_type char_class_type;
+
+ explicit regex_compiler(RegexTraits const &traits = RegexTraits())
+ : mark_count_(0)
+ , hidden_mark_count_(0)
+ , traits_(traits)
+ , upper_(0)
+ , self_()
+ , rules_()
+ {
+ this->upper_ = lookup_classname(this->rxtraits(), "upper");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // imbue
+ /// Specify the locale to be used by a regex_compiler.
+ ///
+ /// \param loc The locale that this regex_compiler should use.
+ /// \return The previous locale.
+ locale_type imbue(locale_type loc)
+ {
+ locale_type oldloc = this->traits_.imbue(loc);
+ this->upper_ = lookup_classname(this->rxtraits(), "upper");
+ return oldloc;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // getloc
+ /// Get the locale used by a regex_compiler.
+ ///
+ /// \return The locale used by this regex_compiler.
+ locale_type getloc() const
+ {
+ return this->traits_.getloc();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // compile
+ /// Builds a basic_regex object from a range of characters.
+ ///
+ /// \param begin The beginning of a range of characters representing the
+ /// regular expression to compile.
+ /// \param end The end of a range of characters representing the
+ /// regular expression to compile.
+ /// \param flags Optional bitmask that determines how the pat string is
+ /// interpreted. (See syntax_option_type.)
+ /// \return A basic_regex object corresponding to the regular expression
+ /// represented by the character range.
+ /// \pre InputIter is a model of the InputIterator concept.
+ /// \pre [begin,end) is a valid range.
+ /// \pre The range of characters specified by [begin,end) contains a
+ /// valid string-based representation of a regular expression.
+ /// \throw regex_error when the range of characters has invalid regular
+ /// expression syntax.
+ template<typename InputIter>
+ basic_regex<BidiIter>
+ compile(InputIter begin, InputIter end, flag_type flags = regex_constants::ECMAScript)
+ {
+ typedef typename iterator_category<InputIter>::type category;
+ return this->compile_(begin, end, flags, category());
+ }
+
+ /// \overload
+ ///
+ template<typename InputRange>
+ typename disable_if<is_pointer<InputRange>, basic_regex<BidiIter> >::type
+ compile(InputRange const &pat, flag_type flags = regex_constants::ECMAScript)
+ {
+ return this->compile(boost::begin(pat), boost::end(pat), flags);
+ }
+
+ /// \overload
+ ///
+ basic_regex<BidiIter>
+ compile(char_type const *begin, flag_type flags = regex_constants::ECMAScript)
+ {
+ BOOST_ASSERT(0 != begin);
+ char_type const *end = begin + std::char_traits<char_type>::length(begin);
+ return this->compile(begin, end, flags);
+ }
+
+ /// \overload
+ ///
+ basic_regex<BidiIter> compile(char_type const *begin, std::size_t size, flag_type flags)
+ {
+ BOOST_ASSERT(0 != begin);
+ char_type const *end = begin + size;
+ return this->compile(begin, end, flags);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // operator[]
+ /// Return a reference to the named regular expression. If no such named
+ /// regular expression exists, create a new regular expression and return
+ /// a reference to it.
+ ///
+ /// \param name A std::string containing the name of the regular expression.
+ /// \pre The string is not empty.
+ /// \throw bad_alloc on allocation failure.
+ basic_regex<BidiIter> &operator [](string_type const &name)
+ {
+ BOOST_ASSERT(!name.empty());
+ return this->rules_[name];
+ }
+
+ /// \overload
+ ///
+ basic_regex<BidiIter> const &operator [](string_type const &name) const
+ {
+ BOOST_ASSERT(!name.empty());
+ return this->rules_[name];
+ }
+
+private:
+
+ typedef detail::escape_value<char_type, char_class_type> escape_value;
+ typedef detail::alternate_matcher<detail::alternates_vector<BidiIter>, RegexTraits> alternate_matcher;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // compile_
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ basic_regex<BidiIter> compile_(FwdIter begin, FwdIter end, flag_type flags, std::forward_iterator_tag)
+ {
+ BOOST_MPL_ASSERT((is_same<char_type, typename iterator_value<FwdIter>::type>));
+ using namespace regex_constants;
+ this->reset();
+ this->traits_.flags(flags);
+
+ basic_regex<BidiIter> rextmp, *prex = &rextmp;
+ FwdIter tmp = begin;
+
+ // Check if this regex is a named rule:
+ string_type name;
+ if(token_group_begin == this->traits_.get_token(tmp, end) &&
+ BOOST_XPR_ENSURE_(tmp != end, error_paren, "mismatched parenthesis") &&
+ token_rule_assign == this->traits_.get_group_type(tmp, end, name))
+ {
+ begin = tmp;
+ BOOST_XPR_ENSURE_
+ (
+ begin != end && token_group_end == this->traits_.get_token(begin, end)
+ , error_paren
+ , "mismatched parenthesis"
+ );
+ prex = &this->rules_[name];
+ }
+
+ this->self_ = detail::core_access<BidiIter>::get_regex_impl(*prex);
+
+ // at the top level, a regex is a sequence of alternates
+ detail::sequence<BidiIter> seq = this->parse_alternates(begin, end);
+ BOOST_XPR_ENSURE_(begin == end, error_paren, "mismatched parenthesis");
+
+ // terminate the sequence
+ seq += detail::make_dynamic<BidiIter>(detail::end_matcher());
+
+ // bundle the regex information into a regex_impl object
+ detail::common_compile(seq.xpr().matchable(), *this->self_, this->rxtraits());
+
+ this->self_->traits_ = new detail::traits_holder<RegexTraits>(this->rxtraits());
+ this->self_->mark_count_ = this->mark_count_;
+ this->self_->hidden_mark_count_ = this->hidden_mark_count_;
+
+ // References changed, update dependencies.
+ this->self_->tracking_update();
+ this->self_.reset();
+ return *prex;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // compile_
+ /// INTERNAL ONLY
+ template<typename InputIter>
+ basic_regex<BidiIter> compile_(InputIter begin, InputIter end, flag_type flags, std::input_iterator_tag)
+ {
+ string_type pat(begin, end);
+ return this->compile_(boost::begin(pat), boost::end(pat), flags, std::forward_iterator_tag());
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // reset
+ /// INTERNAL ONLY
+ void reset()
+ {
+ this->mark_count_ = 0;
+ this->hidden_mark_count_ = 0;
+ this->traits_.flags(regex_constants::ECMAScript);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // regex_traits
+ /// INTERNAL ONLY
+ traits_type &rxtraits()
+ {
+ return this->traits_.traits();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // regex_traits
+ /// INTERNAL ONLY
+ traits_type const &rxtraits() const
+ {
+ return this->traits_.traits();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_alternates
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ detail::sequence<BidiIter> parse_alternates(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ int count = 0;
+ FwdIter tmp = begin;
+ detail::sequence<BidiIter> seq;
+
+ do switch(++count)
+ {
+ case 1:
+ seq = this->parse_sequence(tmp, end);
+ break;
+ case 2:
+ seq = detail::make_dynamic<BidiIter>(alternate_matcher()) | seq;
+ // fall-through
+ default:
+ seq |= this->parse_sequence(tmp, end);
+ }
+ while((begin = tmp) != end && token_alternate == this->traits_.get_token(tmp, end));
+
+ return seq;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_group
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ detail::sequence<BidiIter> parse_group(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ int mark_nbr = 0;
+ bool keeper = false;
+ bool lookahead = false;
+ bool lookbehind = false;
+ bool negative = false;
+ string_type name;
+
+ detail::sequence<BidiIter> seq, seq_end;
+ FwdIter tmp = FwdIter();
+
+ syntax_option_type old_flags = this->traits_.flags();
+
+ switch(this->traits_.get_group_type(begin, end, name))
+ {
+ case token_no_mark:
+ // Don't process empty groups like (?:) or (?i)
+ // BUGBUG this doesn't handle the degenerate (?:)+ correctly
+ if(token_group_end == this->traits_.get_token(tmp = begin, end))
+ {
+ return this->parse_atom(begin = tmp, end);
+ }
+ break;
+
+ case token_negative_lookahead:
+ negative = true; // fall-through
+ case token_positive_lookahead:
+ lookahead = true;
+ break;
+
+ case token_negative_lookbehind:
+ negative = true; // fall-through
+ case token_positive_lookbehind:
+ lookbehind = true;
+ break;
+
+ case token_independent_sub_expression:
+ keeper = true;
+ break;
+
+ case token_comment:
+ while(BOOST_XPR_ENSURE_(begin != end, error_paren, "mismatched parenthesis"))
+ {
+ switch(this->traits_.get_token(begin, end))
+ {
+ case token_group_end: return this->parse_atom(begin, end);
+ case token_escape: BOOST_XPR_ENSURE_(begin != end, error_escape, "incomplete escape sequence");
+ case token_literal: ++begin;
+ default:;
+ }
+ }
+ break;
+
+ case token_recurse:
+ BOOST_XPR_ENSURE_
+ (
+ begin != end && token_group_end == this->traits_.get_token(begin, end)
+ , error_paren
+ , "mismatched parenthesis"
+ );
+ return detail::make_dynamic<BidiIter>(detail::regex_byref_matcher<BidiIter>(this->self_));
+
+ case token_rule_assign:
+ BOOST_THROW_EXCEPTION(
+ regex_error(error_badrule, "rule assignments must be at the front of the regex")
+ );
+ break;
+
+ case token_rule_ref:
+ {
+ typedef detail::core_access<BidiIter> access;
+ BOOST_XPR_ENSURE_
+ (
+ begin != end && token_group_end == this->traits_.get_token(begin, end)
+ , error_paren
+ , "mismatched parenthesis"
+ );
+ basic_regex<BidiIter> &rex = this->rules_[name];
+ shared_ptr<detail::regex_impl<BidiIter> > impl = access::get_regex_impl(rex);
+ this->self_->track_reference(*impl);
+ return detail::make_dynamic<BidiIter>(detail::regex_byref_matcher<BidiIter>(impl));
+ }
+
+ case token_named_mark:
+ mark_nbr = static_cast<int>(++this->mark_count_);
+ for(std::size_t i = 0; i < this->self_->named_marks_.size(); ++i)
+ {
+ BOOST_XPR_ENSURE_(this->self_->named_marks_[i].name_ != name, error_badmark, "named mark already exists");
+ }
+ this->self_->named_marks_.push_back(detail::named_mark<char_type>(name, this->mark_count_));
+ seq = detail::make_dynamic<BidiIter>(detail::mark_begin_matcher(mark_nbr));
+ seq_end = detail::make_dynamic<BidiIter>(detail::mark_end_matcher(mark_nbr));
+ break;
+
+ case token_named_mark_ref:
+ BOOST_XPR_ENSURE_
+ (
+ begin != end && token_group_end == this->traits_.get_token(begin, end)
+ , error_paren
+ , "mismatched parenthesis"
+ );
+ for(std::size_t i = 0; i < this->self_->named_marks_.size(); ++i)
+ {
+ if(this->self_->named_marks_[i].name_ == name)
+ {
+ mark_nbr = static_cast<int>(this->self_->named_marks_[i].mark_nbr_);
+ return detail::make_backref_xpression<BidiIter>
+ (
+ mark_nbr, this->traits_.flags(), this->rxtraits()
+ );
+ }
+ }
+ BOOST_THROW_EXCEPTION(regex_error(error_badmark, "invalid named back-reference"));
+ break;
+
+ default:
+ mark_nbr = static_cast<int>(++this->mark_count_);
+ seq = detail::make_dynamic<BidiIter>(detail::mark_begin_matcher(mark_nbr));
+ seq_end = detail::make_dynamic<BidiIter>(detail::mark_end_matcher(mark_nbr));
+ break;
+ }
+
+ // alternates
+ seq += this->parse_alternates(begin, end);
+ seq += seq_end;
+ BOOST_XPR_ENSURE_
+ (
+ begin != end && token_group_end == this->traits_.get_token(begin, end)
+ , error_paren
+ , "mismatched parenthesis"
+ );
+
+ typedef detail::shared_matchable<BidiIter> xpr_type;
+ if(lookahead)
+ {
+ seq += detail::make_independent_end_xpression<BidiIter>(seq.pure());
+ detail::lookahead_matcher<xpr_type> lookahead(seq.xpr(), negative, seq.pure());
+ seq = detail::make_dynamic<BidiIter>(lookahead);
+ }
+ else if(lookbehind)
+ {
+ seq += detail::make_independent_end_xpression<BidiIter>(seq.pure());
+ detail::lookbehind_matcher<xpr_type> lookbehind(seq.xpr(), seq.width().value(), negative, seq.pure());
+ seq = detail::make_dynamic<BidiIter>(lookbehind);
+ }
+ else if(keeper) // independent sub-expression
+ {
+ seq += detail::make_independent_end_xpression<BidiIter>(seq.pure());
+ detail::keeper_matcher<xpr_type> keeper(seq.xpr(), seq.pure());
+ seq = detail::make_dynamic<BidiIter>(keeper);
+ }
+
+ // restore the modifiers
+ this->traits_.flags(old_flags);
+ return seq;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_charset
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ detail::sequence<BidiIter> parse_charset(FwdIter &begin, FwdIter end)
+ {
+ detail::compound_charset<traits_type> chset;
+
+ // call out to a helper to actually parse the character set
+ detail::parse_charset(begin, end, chset, this->traits_);
+
+ return detail::make_charset_xpression<BidiIter>
+ (
+ chset
+ , this->rxtraits()
+ , this->traits_.flags()
+ );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_atom
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ detail::sequence<BidiIter> parse_atom(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ escape_value esc = { 0, 0, 0, detail::escape_char };
+ FwdIter old_begin = begin;
+
+ switch(this->traits_.get_token(begin, end))
+ {
+ case token_literal:
+ return detail::make_literal_xpression<BidiIter>
+ (
+ this->parse_literal(begin, end), this->traits_.flags(), this->rxtraits()
+ );
+
+ case token_any:
+ return detail::make_any_xpression<BidiIter>(this->traits_.flags(), this->rxtraits());
+
+ case token_assert_begin_sequence:
+ return detail::make_dynamic<BidiIter>(detail::assert_bos_matcher());
+
+ case token_assert_end_sequence:
+ return detail::make_dynamic<BidiIter>(detail::assert_eos_matcher());
+
+ case token_assert_begin_line:
+ return detail::make_assert_begin_line<BidiIter>(this->traits_.flags(), this->rxtraits());
+
+ case token_assert_end_line:
+ return detail::make_assert_end_line<BidiIter>(this->traits_.flags(), this->rxtraits());
+
+ case token_assert_word_boundary:
+ return detail::make_assert_word<BidiIter>(detail::word_boundary<mpl::true_>(), this->rxtraits());
+
+ case token_assert_not_word_boundary:
+ return detail::make_assert_word<BidiIter>(detail::word_boundary<mpl::false_>(), this->rxtraits());
+
+ case token_assert_word_begin:
+ return detail::make_assert_word<BidiIter>(detail::word_begin(), this->rxtraits());
+
+ case token_assert_word_end:
+ return detail::make_assert_word<BidiIter>(detail::word_end(), this->rxtraits());
+
+ case token_escape:
+ esc = this->parse_escape(begin, end);
+ switch(esc.type_)
+ {
+ case detail::escape_mark:
+ return detail::make_backref_xpression<BidiIter>
+ (
+ esc.mark_nbr_, this->traits_.flags(), this->rxtraits()
+ );
+ case detail::escape_char:
+ return detail::make_char_xpression<BidiIter>
+ (
+ esc.ch_, this->traits_.flags(), this->rxtraits()
+ );
+ case detail::escape_class:
+ return detail::make_posix_charset_xpression<BidiIter>
+ (
+ esc.class_
+ , this->is_upper_(*begin++)
+ , this->traits_.flags()
+ , this->rxtraits()
+ );
+ }
+
+ case token_group_begin:
+ return this->parse_group(begin, end);
+
+ case token_charset_begin:
+ return this->parse_charset(begin, end);
+
+ case token_invalid_quantifier:
+ BOOST_THROW_EXCEPTION(regex_error(error_badrepeat, "quantifier not expected"));
+ break;
+
+ case token_quote_meta_begin:
+ return detail::make_literal_xpression<BidiIter>
+ (
+ this->parse_quote_meta(begin, end), this->traits_.flags(), this->rxtraits()
+ );
+
+ case token_quote_meta_end:
+ BOOST_THROW_EXCEPTION(
+ regex_error(
+ error_escape
+ , "found quote-meta end without corresponding quote-meta begin"
+ )
+ );
+ break;
+
+ case token_end_of_pattern:
+ break;
+
+ default:
+ begin = old_begin;
+ break;
+ }
+
+ return detail::sequence<BidiIter>();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_quant
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ detail::sequence<BidiIter> parse_quant(FwdIter &begin, FwdIter end)
+ {
+ BOOST_ASSERT(begin != end);
+ detail::quant_spec spec = { 0, 0, false, &this->hidden_mark_count_ };
+ detail::sequence<BidiIter> seq = this->parse_atom(begin, end);
+
+ // BUGBUG this doesn't handle the degenerate (?:)+ correctly
+ if(!seq.empty() && begin != end && detail::quant_none != seq.quant())
+ {
+ if(this->traits_.get_quant_spec(begin, end, spec))
+ {
+ BOOST_ASSERT(spec.min_ <= spec.max_);
+
+ if(0 == spec.max_) // quant {0,0} is degenerate -- matches nothing.
+ {
+ seq = this->parse_quant(begin, end);
+ }
+ else
+ {
+ seq.repeat(spec);
+ }
+ }
+ }
+
+ return seq;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_sequence
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ detail::sequence<BidiIter> parse_sequence(FwdIter &begin, FwdIter end)
+ {
+ detail::sequence<BidiIter> seq;
+
+ while(begin != end)
+ {
+ detail::sequence<BidiIter> seq_quant = this->parse_quant(begin, end);
+
+ // did we find a quantified atom?
+ if(seq_quant.empty())
+ break;
+
+ // chain it to the end of the xpression sequence
+ seq += seq_quant;
+ }
+
+ return seq;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_literal
+ // scan ahead looking for char literals to be globbed together into a string literal
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ string_type parse_literal(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ BOOST_ASSERT(begin != end);
+ BOOST_ASSERT(token_literal == this->traits_.get_token(begin, end));
+ escape_value esc = { 0, 0, 0, detail::escape_char };
+ string_type literal(1, *begin);
+
+ for(FwdIter prev = begin, tmp = ++begin; begin != end; prev = begin, begin = tmp)
+ {
+ detail::quant_spec spec = { 0, 0, false, &this->hidden_mark_count_ };
+ if(this->traits_.get_quant_spec(tmp, end, spec))
+ {
+ if(literal.size() != 1)
+ {
+ begin = prev;
+ literal.erase(boost::prior(literal.end()));
+ }
+ return literal;
+ }
+ else switch(this->traits_.get_token(tmp, end))
+ {
+ case token_escape:
+ esc = this->parse_escape(tmp, end);
+ if(detail::escape_char != esc.type_) return literal;
+ literal.insert(literal.end(), esc.ch_);
+ break;
+ case token_literal:
+ literal.insert(literal.end(), *tmp++);
+ break;
+ default:
+ return literal;
+ }
+ }
+
+ return literal;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse_quote_meta
+ // scan ahead looking for char literals to be globbed together into a string literal
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ string_type parse_quote_meta(FwdIter &begin, FwdIter end)
+ {
+ using namespace regex_constants;
+ FwdIter old_begin = begin, old_end;
+ while(end != (old_end = begin))
+ {
+ switch(this->traits_.get_token(begin, end))
+ {
+ case token_quote_meta_end: return string_type(old_begin, old_end);
+ case token_escape: BOOST_XPR_ENSURE_(begin != end, error_escape, "incomplete escape sequence");
+ case token_invalid_quantifier:
+ case token_literal: ++begin;
+ default:;
+ }
+ }
+ return string_type(old_begin, begin);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // parse_escape
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ escape_value parse_escape(FwdIter &begin, FwdIter end)
+ {
+ BOOST_XPR_ENSURE_(begin != end, regex_constants::error_escape, "incomplete escape sequence");
+
+ // first, check to see if this can be a backreference
+ if(0 < this->rxtraits().value(*begin, 10))
+ {
+ // Parse at most 3 decimal digits.
+ FwdIter tmp = begin;
+ int mark_nbr = detail::toi(tmp, end, this->rxtraits(), 10, 999);
+
+ // If the resulting number could conceivably be a backref, then it is.
+ if(10 > mark_nbr || mark_nbr <= static_cast<int>(this->mark_count_))
+ {
+ begin = tmp;
+ escape_value esc = {0, mark_nbr, 0, detail::escape_mark};
+ return esc;
+ }
+ }
+
+ // Not a backreference, defer to the parse_escape helper
+ return detail::parse_escape(begin, end, this->traits_);
+ }
+
+ bool is_upper_(char_type ch) const
+ {
+ return 0 != this->upper_ && this->rxtraits().isctype(ch, this->upper_);
+ }
+
+ std::size_t mark_count_;
+ std::size_t hidden_mark_count_;
+ CompilerTraits traits_;
+ typename RegexTraits::char_class_type upper_;
+ shared_ptr<detail::regex_impl<BidiIter> > self_;
+ std::map<string_type, basic_regex<BidiIter> > rules_;
+};
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/regex_constants.hpp b/boost/xpressive/regex_constants.hpp
new file mode 100644
index 0000000000..49be39bc88
--- /dev/null
+++ b/boost/xpressive/regex_constants.hpp
@@ -0,0 +1,294 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_constants.hpp
+/// Contains definitions for the syntax_option_type, match_flag_type and
+/// error_type enumerations.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_REGEX_CONSTANTS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_REGEX_CONSTANTS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/identity.hpp>
+
+#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+# define icase icase_
+#endif
+
+namespace boost { namespace xpressive { namespace regex_constants
+{
+
+/// Flags used to customize the regex syntax
+///
+enum syntax_option_type
+{
+ // these flags are required:
+
+ ECMAScript = 0, ///< Specifies that the grammar recognized by the regular expression
+ ///< engine uses its normal semantics: that is the same as that given
+ ///< in the ECMA-262, ECMAScript Language Specification, Chapter 15
+ ///< part 10, RegExp (Regular Expression) Objects (FWD.1).
+ ///<
+ icase = 1 << 1, ///< Specifies that matching of regular expressions against a character
+ ///< container sequence shall be performed without regard to case.
+ ///<
+ nosubs = 1 << 2, ///< Specifies that when a regular expression is matched against a
+ ///< character container sequence, then no sub-expression matches are to
+ ///< be stored in the supplied match_results structure.
+ ///<
+ optimize = 1 << 3, ///< Specifies that the regular expression engine should pay more
+ ///< attention to the speed with which regular expressions are matched,
+ ///< and less to the speed with which regular expression objects are
+ ///< constructed. Otherwise it has no detectable effect on the program
+ ///< output.
+ ///<
+ collate = 1 << 4, ///< Specifies that character ranges of the form "[a-b]" should be
+ ///< locale sensitive.
+ ///<
+
+ // These flags are optional. If the functionality is supported
+ // then the flags shall take these names.
+
+ //basic = 1 << 5, ///< Specifies that the grammar recognized by the regular expression
+ // ///< engine is the same as that used by POSIX basic regular expressions
+ // ///< in IEEE Std 1003.1-2001, Portable Operating System Interface
+ // ///< (POSIX), Base Definitions and Headers, Section 9, Regular
+ // ///< Expressions (FWD.1).
+ // ///<
+ //extended = 1 << 6, ///< Specifies that the grammar recognized by the regular expression
+ // ///< engine is the same as that used by POSIX extended regular
+ // ///< expressions in IEEE Std 1003.1-2001, Portable Operating System
+ // ///< Interface (POSIX), Base Definitions and Headers, Section 9,
+ // ///< Regular Expressions (FWD.1).
+ // ///<
+ //awk = 1 << 7, ///< Specifies that the grammar recognized by the regular expression
+ // ///< engine is the same as that used by POSIX utility awk in IEEE Std
+ // ///< 1003.1-2001, Portable Operating System Interface (POSIX), Shells
+ // ///< and Utilities, Section 4, awk (FWD.1).
+ // ///<
+ //grep = 1 << 8, ///< Specifies that the grammar recognized by the regular expression
+ // ///< engine is the same as that used by POSIX utility grep in IEEE Std
+ // ///< 1003.1-2001, Portable Operating System Interface (POSIX),
+ // ///< Shells and Utilities, Section 4, Utilities, grep (FWD.1).
+ // ///<
+ //egrep = 1 << 9, ///< Specifies that the grammar recognized by the regular expression
+ // ///< engine is the same as that used by POSIX utility grep when given
+ // ///< the -E option in IEEE Std 1003.1-2001, Portable Operating System
+ // ///< Interface (POSIX), Shells and Utilities, Section 4, Utilities,
+ // ///< grep (FWD.1).
+ // ///<
+
+ // these flags are specific to xpressive, and they help with perl compliance.
+
+ single_line = 1 << 10, ///< Specifies that the ^ and \$ metacharacters DO NOT match at
+ ///< internal line breaks. Note that this is the opposite of the
+ ///< perl default. It is the inverse of perl's /m (multi-line)
+ ///< modifier.
+ ///<
+ not_dot_null = 1 << 11, ///< Specifies that the . metacharacter does not match the null
+ ///< character \\0.
+ ///<
+ not_dot_newline = 1 << 12, ///< Specifies that the . metacharacter does not match the
+ ///< newline character \\n.
+ ///<
+ ignore_white_space = 1 << 13 ///< Specifies that non-escaped white-space is not significant.
+ ///<
+};
+
+/// Flags used to customize the behavior of the regex algorithms
+///
+enum match_flag_type
+{
+ match_default = 0, ///< Specifies that matching of regular expressions proceeds
+ ///< without any modification of the normal rules used in
+ ///< ECMA-262, ECMAScript Language Specification, Chapter 15
+ ///< part 10, RegExp (Regular Expression) Objects (FWD.1)
+ ///<
+ match_not_bol = 1 << 1, ///< Specifies that the expression "^" should not be matched
+ ///< against the sub-sequence [first,first).
+ ///<
+ match_not_eol = 1 << 2, ///< Specifies that the expression "\$" should not be
+ ///< matched against the sub-sequence [last,last).
+ ///<
+ match_not_bow = 1 << 3, ///< Specifies that the expression "\\b" should not be
+ ///< matched against the sub-sequence [first,first).
+ ///<
+ match_not_eow = 1 << 4, ///< Specifies that the expression "\\b" should not be
+ ///< matched against the sub-sequence [last,last).
+ ///<
+ match_any = 1 << 7, ///< Specifies that if more than one match is possible then
+ ///< any match is an acceptable result.
+ ///<
+ match_not_null = 1 << 8, ///< Specifies that the expression can not be matched
+ ///< against an empty sequence.
+ ///<
+ match_continuous = 1 << 10, ///< Specifies that the expression must match a sub-sequence
+ ///< that begins at first.
+ ///<
+ match_partial = 1 << 11, ///< Specifies that if no match can be found, then it is
+ ///< acceptable to return a match [from, last) where
+ ///< from != last, if there exists some sequence of characters
+ ///< [from,to) of which [from,last) is a prefix, and which
+ ///< would result in a full match.
+ ///<
+ match_prev_avail = 1 << 12, ///< Specifies that --first is a valid iterator position,
+ ///< when this flag is set then the flags match_not_bol
+ ///< and match_not_bow are ignored by the regular expression
+ ///< algorithms (RE.7) and iterators (RE.8).
+ ///<
+ format_default = 0, ///< Specifies that when a regular expression match is to be
+ ///< replaced by a new string, that the new string is
+ ///< constructed using the rules used by the ECMAScript
+ ///< replace function in ECMA-262, ECMAScript Language
+ ///< Specification, Chapter 15 part 5.4.11
+ ///< String.prototype.replace. (FWD.1). In addition during
+ ///< search and replace operations then all non-overlapping
+ ///< occurrences of the regular expression are located and
+ ///< replaced, and sections of the input that did not match
+ ///< the expression, are copied unchanged to the output
+ ///< string.
+ ///<
+ format_sed = 1 << 13, ///< Specifies that when a regular expression match is to be
+ ///< replaced by a new string, that the new string is
+ ///< constructed using the rules used by the Unix sed
+ ///< utility in IEEE Std 1003.1-2001, Portable Operating
+ ///< SystemInterface (POSIX), Shells and Utilities.
+ ///<
+ format_perl = 1 << 14, ///< Specifies that when a regular expression match is to be
+ ///< replaced by a new string, that the new string is
+ ///< constructed using an implementation defined superset
+ ///< of the rules used by the ECMAScript replace function in
+ ///< ECMA-262, ECMAScript Language Specification, Chapter 15
+ ///< part 5.4.11 String.prototype.replace (FWD.1).
+ ///<
+ format_no_copy = 1 << 15, ///< When specified during a search and replace operation,
+ ///< then sections of the character container sequence being
+ ///< searched that do match the regular expression, are not
+ ///< copied to the output string.
+ ///<
+ format_first_only = 1 << 16, ///< When specified during a search and replace operation,
+ ///< then only the first occurrence of the regular
+ ///< expression is replaced.
+ ///<
+ format_literal = 1 << 17, ///< Treat the format string as a literal.
+ ///<
+ format_all = 1 << 18 ///< Specifies that all syntax extensions are enabled,
+ ///< including conditional (?ddexpression1:expression2)
+ ///< replacements.
+ ///<
+};
+
+/// Error codes used by the regex_error type
+///
+enum error_type
+{
+ error_collate, ///< The expression contained an invalid collating element name.
+ ///<
+ error_ctype, ///< The expression contained an invalid character class name.
+ ///<
+ error_escape, ///< The expression contained an invalid escaped character,
+ ///< or a trailing escape.
+ ///<
+ error_subreg, ///< The expression contained an invalid back-reference.
+ ///<
+ error_brack, ///< The expression contained mismatched [ and ].
+ ///<
+ error_paren, ///< The expression contained mismatched ( and ).
+ ///<
+ error_brace, ///< The expression contained mismatched { and }.
+ ///<
+ error_badbrace, ///< The expression contained an invalid range in a {} expression.
+ ///<
+ error_range, ///< The expression contained an invalid character range, for
+ ///< example [b-a].
+ ///<
+ error_space, ///< There was insufficient memory to convert the expression into a
+ ///< finite state machine.
+ ///<
+ error_badrepeat, ///< One of *?+{ was not preceded by a valid regular expression.
+ ///<
+ error_complexity, ///< The complexity of an attempted match against a regular
+ ///< expression exceeded a pre-set level.
+ ///<
+ error_stack, ///< There was insufficient memory to determine whether the regular
+ ///< expression could match the specified character sequence.
+ ///<
+ error_badref, ///< An nested regex is uninitialized.
+ ///<
+ error_badmark, ///< An invalid use of a named capture.
+ ///<
+ error_badlookbehind, ///< An attempt to create a variable-width look-behind assertion
+ ///< was detected.
+ ///<
+ error_badrule, ///< An invalid use of a rule was detected.
+ ///<
+ error_badarg, ///< An argument to an action was unbound.
+ ///<
+ error_badattr, ///< Tried to read from an uninitialized attribute.
+ ///<
+ error_internal ///< An internal error has occurred.
+ ///<
+};
+
+/// INTERNAL ONLY
+inline syntax_option_type operator &(syntax_option_type b1, syntax_option_type b2)
+{
+ return static_cast<syntax_option_type>(
+ static_cast<int>(b1) & static_cast<int>(b2));
+}
+
+/// INTERNAL ONLY
+inline syntax_option_type operator |(syntax_option_type b1, syntax_option_type b2)
+{
+ return static_cast<syntax_option_type>(static_cast<int>(b1) | static_cast<int>(b2));
+}
+
+/// INTERNAL ONLY
+inline syntax_option_type operator ^(syntax_option_type b1, syntax_option_type b2)
+{
+ return static_cast<syntax_option_type>(static_cast<int>(b1) ^ static_cast<int>(b2));
+}
+
+/// INTERNAL ONLY
+inline syntax_option_type operator ~(syntax_option_type b)
+{
+ return static_cast<syntax_option_type>(~static_cast<int>(b));
+}
+
+/// INTERNAL ONLY
+inline match_flag_type operator &(match_flag_type b1, match_flag_type b2)
+{
+ return static_cast<match_flag_type>(static_cast<int>(b1) & static_cast<int>(b2));
+}
+
+/// INTERNAL ONLY
+inline match_flag_type operator |(match_flag_type b1, match_flag_type b2)
+{
+ return static_cast<match_flag_type>(static_cast<int>(b1) | static_cast<int>(b2));
+}
+
+/// INTERNAL ONLY
+inline match_flag_type operator ^(match_flag_type b1, match_flag_type b2)
+{
+ return static_cast<match_flag_type>(static_cast<int>(b1) ^ static_cast<int>(b2));
+}
+
+/// INTERNAL ONLY
+inline match_flag_type operator ~(match_flag_type b)
+{
+ return static_cast<match_flag_type>(~static_cast<int>(b));
+}
+
+}}} // namespace boost::xpressive::regex_constants
+
+#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+# undef icase
+#endif
+
+#endif
diff --git a/boost/xpressive/regex_error.hpp b/boost/xpressive/regex_error.hpp
new file mode 100644
index 0000000000..77fd8cb872
--- /dev/null
+++ b/boost/xpressive/regex_error.hpp
@@ -0,0 +1,114 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_error.hpp
+/// Contains the definition of the regex_error exception class.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_REGEX_ERROR_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_REGEX_ERROR_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <string>
+#include <stdexcept>
+#include <boost/throw_exception.hpp>
+#include <boost/current_function.hpp>
+#include <boost/exception/exception.hpp>
+#include <boost/exception/info.hpp>
+#include <boost/xpressive/regex_constants.hpp>
+
+//{{AFX_DOC_COMMENT
+///////////////////////////////////////////////////////////////////////////////
+// This is a hack to get Doxygen to show the inheritance relation between
+// regex_error and std::runtime_error.
+#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+/// INTERNAL ONLY
+namespace std
+{
+ /// INTERNAL ONLY
+ struct runtime_error {};
+}
+#endif
+//}}AFX_DOC_COMMENT
+
+namespace boost { namespace xpressive
+{
+
+////////////////////////////////////////////////////////////////////////////////
+// regex_error
+//
+/// \brief The class regex_error defines the type of objects thrown as
+/// exceptions to report errors during the conversion from a string representing
+/// a regular expression to a finite state machine.
+struct regex_error
+ : std::runtime_error
+ , boost::exception
+{
+ /// Constructs an object of class regex_error.
+ /// \param code The error_type this regex_error represents.
+ /// \post code() == code
+ explicit regex_error(regex_constants::error_type code, char const *str = "")
+ : std::runtime_error(str)
+ , boost::exception()
+ , code_(code)
+ {
+ }
+
+ /// Accessor for the error_type value
+ /// \return the error_type code passed to the constructor
+ /// \throw nothrow
+ regex_constants::error_type code() const
+ {
+ return this->code_;
+ }
+
+ /// Destructor for class regex_error
+ /// \throw nothrow
+ virtual ~regex_error() throw()
+ {}
+
+private:
+
+ regex_constants::error_type code_;
+};
+
+namespace detail
+{
+ inline bool ensure_(
+ bool cond
+ , regex_constants::error_type code
+ , char const *msg
+ , char const *fun
+ , char const *file
+ , unsigned long line
+ )
+ {
+ if(!cond)
+ {
+ #ifndef BOOST_EXCEPTION_DISABLE
+ boost::throw_exception(
+ boost::xpressive::regex_error(code, msg)
+ << boost::throw_function(fun)
+ << boost::throw_file(file)
+ << boost::throw_line((int)line)
+ );
+ #else
+ boost::throw_exception(boost::xpressive::regex_error(code, msg));
+ #endif
+ }
+ return true;
+ }
+}
+
+#define BOOST_XPR_ENSURE_(pred, code, msg) \
+ boost::xpressive::detail::ensure_(pred, code, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) \
+ /**/
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/regex_iterator.hpp b/boost/xpressive/regex_iterator.hpp
new file mode 100644
index 0000000000..e577300006
--- /dev/null
+++ b/boost/xpressive/regex_iterator.hpp
@@ -0,0 +1,260 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_iterator.hpp
+/// Contains the definition of the regex_iterator type, an STL-compatible iterator
+/// for stepping through all the matches in a sequence.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_REGEX_ITERATOR_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_REGEX_ITERATOR_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/access.hpp>
+#include <boost/xpressive/detail/utility/counted_base.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+//////////////////////////////////////////////////////////////////////////
+// regex_iterator_impl
+//
+template<typename BidiIter>
+struct regex_iterator_impl
+ : counted_base<regex_iterator_impl<BidiIter> >
+{
+ typedef detail::core_access<BidiIter> access;
+
+ regex_iterator_impl
+ (
+ BidiIter begin
+ , BidiIter cur
+ , BidiIter end
+ , BidiIter next_search
+ , basic_regex<BidiIter> const &rex
+ , regex_constants::match_flag_type flags
+ , bool not_null = false
+ )
+ : rex_(rex)
+ , what_()
+ , state_(begin, end, what_, *access::get_regex_impl(rex_), flags)
+ , flags_(flags)
+ , not_null_(not_null)
+ {
+ this->state_.cur_ = cur;
+ this->state_.next_search_ = next_search;
+ }
+
+ bool next()
+ {
+ this->state_.reset(this->what_, *access::get_regex_impl(this->rex_));
+ if(!regex_search_impl(this->state_, this->rex_, this->not_null_))
+ {
+ return false;
+ }
+
+ // Report position() correctly by setting the base different from prefix().first
+ access::set_base(this->what_, this->state_.begin_);
+
+ this->state_.cur_ = this->state_.next_search_ = this->what_[0].second;
+ this->not_null_ = (0 == this->what_.length());
+
+ return true;
+ }
+
+ bool equal_to(regex_iterator_impl<BidiIter> const &that) const
+ {
+ return this->rex_.regex_id() == that.rex_.regex_id()
+ && this->state_.begin_ == that.state_.begin_
+ && this->state_.cur_ == that.state_.cur_
+ && this->state_.end_ == that.state_.end_
+ && this->flags_ == that.flags_
+ ;
+ }
+
+ basic_regex<BidiIter> rex_;
+ match_results<BidiIter> what_;
+ match_state<BidiIter> state_;
+ regex_constants::match_flag_type const flags_;
+ bool not_null_;
+};
+
+} // namespace detail
+
+//////////////////////////////////////////////////////////////////////////
+// regex_iterator
+//
+template<typename BidiIter>
+struct regex_iterator
+{
+ typedef basic_regex<BidiIter> regex_type;
+ typedef match_results<BidiIter> value_type;
+ typedef typename iterator_difference<BidiIter>::type difference_type;
+ typedef value_type const *pointer;
+ typedef value_type const &reference;
+ typedef std::forward_iterator_tag iterator_category;
+
+ /// INTERNAL ONLY
+ typedef detail::regex_iterator_impl<BidiIter> impl_type_;
+
+ regex_iterator()
+ : impl_()
+ {
+ }
+
+ regex_iterator
+ (
+ BidiIter begin
+ , BidiIter end
+ , basic_regex<BidiIter> const &rex
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ )
+ : impl_()
+ {
+ if(0 != rex.regex_id()) // Empty regexes are guaranteed to match nothing
+ {
+ this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags);
+ this->next_();
+ }
+ }
+
+ template<typename LetExpr>
+ regex_iterator
+ (
+ BidiIter begin
+ , BidiIter end
+ , basic_regex<BidiIter> const &rex
+ , detail::let_<LetExpr> const &args
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ )
+ : impl_()
+ {
+ if(0 != rex.regex_id()) // Empty regexes are guaranteed to match nothing
+ {
+ this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags);
+ detail::bind_args(args, this->impl_->what_);
+ this->next_();
+ }
+ }
+
+ regex_iterator(regex_iterator<BidiIter> const &that)
+ : impl_(that.impl_) // COW
+ {
+ }
+
+ regex_iterator<BidiIter> &operator =(regex_iterator<BidiIter> const &that)
+ {
+ this->impl_ = that.impl_; // COW
+ return *this;
+ }
+
+ friend bool operator ==(regex_iterator<BidiIter> const &left, regex_iterator<BidiIter> const &right)
+ {
+ if(!left.impl_ || !right.impl_)
+ {
+ return !left.impl_ && !right.impl_;
+ }
+
+ return left.impl_->equal_to(*right.impl_);
+ }
+
+ friend bool operator !=(regex_iterator<BidiIter> const &left, regex_iterator<BidiIter> const &right)
+ {
+ return !(left == right);
+ }
+
+ value_type const &operator *() const
+ {
+ return this->impl_->what_;
+ }
+
+ value_type const *operator ->() const
+ {
+ return &this->impl_->what_;
+ }
+
+ /// If what.prefix().first != what[0].second and if the element match_prev_avail is not set in
+ /// flags then sets it. Then behaves as if by calling regex_search(what[0].second, end, what, *pre, flags),
+ /// with the following variation: in the event that the previous match found was of zero length
+ /// (what[0].length() == 0) then attempts to find a non-zero length match starting at what[0].second,
+ /// only if that fails and provided what[0].second != suffix().second does it look for a (possibly
+ /// zero length) match starting from what[0].second + 1. If no further match is found then sets
+ /// *this equal to the end of sequence iterator.
+ /// \post (*this)-\>size() == pre-\>mark_count() + 1
+ /// \post (*this)-\>empty() == false
+ /// \post (*this)-\>prefix().first == An iterator denoting the end point of the previous match found
+ /// \post (*this)-\>prefix().last == (**this)[0].first
+ /// \post (*this)-\>prefix().matched == (*this)-\>prefix().first != (*this)-\>prefix().second
+ /// \post (*this)-\>suffix().first == (**this)[0].second
+ /// \post (*this)-\>suffix().last == end
+ /// \post (*this)-\>suffix().matched == (*this)-\>suffix().first != (*this)-\>suffix().second
+ /// \post (**this)[0].first == The starting iterator for this match.
+ /// \post (**this)[0].second == The ending iterator for this match.
+ /// \post (**this)[0].matched == true if a full match was found, and false if it was a partial match (found as a result of the match_partial flag being set).
+ /// \post (**this)[n].first == For all integers n \< (*this)-\>size(), the start of the sequence that matched sub-expression n. Alternatively, if sub-expression n did not participate in the match, then end.
+ /// \post (**this)[n].second == For all integers n \< (*this)-\>size(), the end of the sequence that matched sub-expression n. Alternatively, if sub-expression n did not participate in the match, then end.
+ /// \post (**this)[n].matched == For all integers n \< (*this)-\>size(), true if sub-expression n participated in the match, false otherwise.
+ /// \post (*this)-\>position() == The distance from the start of the original sequence being iterated, to the start of this match.
+ regex_iterator<BidiIter> &operator ++()
+ {
+ this->fork_(); // un-share the implementation
+ this->next_();
+ return *this;
+ }
+
+ regex_iterator<BidiIter> operator ++(int)
+ {
+ regex_iterator<BidiIter> tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+private:
+
+ /// INTERNAL ONLY
+ void fork_()
+ {
+ if(1 != this->impl_->use_count())
+ {
+ // This is OK, the use_count is > 1
+ impl_type_ *that = this->impl_.get();
+ this->impl_ = new impl_type_
+ (
+ that->state_.begin_
+ , that->state_.cur_
+ , that->state_.end_
+ , that->state_.next_search_
+ , that->rex_
+ , that->flags_
+ , that->not_null_
+ );
+ detail::core_access<BidiIter>::get_action_args(this->impl_->what_)
+ = detail::core_access<BidiIter>::get_action_args(that->what_);
+ }
+ }
+
+ /// INTERNAL ONLY
+ void next_()
+ {
+ BOOST_ASSERT(this->impl_ && 1 == this->impl_->use_count());
+ if(!this->impl_->next())
+ {
+ this->impl_ = 0;
+ }
+ }
+
+ intrusive_ptr<impl_type_> impl_;
+};
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/regex_primitives.hpp b/boost/xpressive/regex_primitives.hpp
new file mode 100644
index 0000000000..11230f60df
--- /dev/null
+++ b/boost/xpressive/regex_primitives.hpp
@@ -0,0 +1,927 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_primitives.hpp
+/// Contains the syntax elements for writing static regular expressions.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_REGEX_PRIMITIVES_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_REGEX_PRIMITIVES_HPP_EAN_10_04_2005
+
+#include <vector>
+#include <climits>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/core/matchers.hpp>
+#include <boost/xpressive/detail/core/regex_domain.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+// Doxygen can't handle proto :-(
+#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+# include <boost/proto/core.hpp>
+# include <boost/proto/transform/arg.hpp>
+# include <boost/proto/transform/when.hpp>
+# include <boost/xpressive/detail/core/icase.hpp>
+# include <boost/xpressive/detail/static/compile.hpp>
+# include <boost/xpressive/detail/static/modifier.hpp>
+#endif
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+ typedef assert_word_placeholder<word_boundary<mpl::true_> > assert_word_boundary;
+ typedef assert_word_placeholder<word_begin> assert_word_begin;
+ typedef assert_word_placeholder<word_end> assert_word_end;
+
+ // workaround msvc-7.1 bug with function pointer types
+ // within function types:
+ #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ #define mark_number(x) proto::call<mark_number(x)>
+ #define minus_one() proto::make<minus_one()>
+ #endif
+
+ struct push_back : proto::callable
+ {
+ typedef int result_type;
+
+ template<typename Subs>
+ int operator ()(Subs &subs, int i) const
+ {
+ subs.push_back(i);
+ return i;
+ }
+ };
+
+ struct mark_number : proto::callable
+ {
+ typedef int result_type;
+
+ template<typename Expr>
+ int operator ()(Expr const &expr) const
+ {
+ return expr.mark_number_;
+ }
+ };
+
+ typedef mpl::int_<-1> minus_one;
+
+ // s1 or -s1
+ struct SubMatch
+ : proto::or_<
+ proto::when<basic_mark_tag, push_back(proto::_data, mark_number(proto::_value)) >
+ , proto::when<proto::negate<basic_mark_tag>, push_back(proto::_data, minus_one()) >
+ >
+ {};
+
+ struct SubMatchList
+ : proto::or_<SubMatch, proto::comma<SubMatchList, SubMatch> >
+ {};
+
+ template<typename Subs>
+ typename enable_if<
+ mpl::and_<proto::is_expr<Subs>, proto::matches<Subs, SubMatchList> >
+ , std::vector<int>
+ >::type
+ to_vector(Subs const &subs)
+ {
+ std::vector<int> subs_;
+ SubMatchList()(subs, 0, subs_);
+ return subs_;
+ }
+
+ #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ #undef mark_number
+ #undef minus_one
+ #endif
+
+ // replace "Expr" with "keep(*State) >> Expr"
+ struct skip_primitives : proto::transform<skip_primitives>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename proto::shift_right<
+ typename proto::unary_expr<
+ keeper_tag
+ , typename proto::dereference<State>::type
+ >::type
+ , Expr
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param
+ ) const
+ {
+ result_type that = {{{state}}, expr};
+ return that;
+ }
+ };
+ };
+
+ struct Primitives
+ : proto::or_<
+ proto::terminal<proto::_>
+ , proto::comma<proto::_, proto::_>
+ , proto::subscript<proto::terminal<set_initializer>, proto::_>
+ , proto::assign<proto::terminal<set_initializer>, proto::_>
+ , proto::assign<proto::terminal<attribute_placeholder<proto::_> >, proto::_>
+ , proto::complement<Primitives>
+ >
+ {};
+
+ struct SkipGrammar
+ : proto::or_<
+ proto::when<Primitives, skip_primitives>
+ , proto::assign<proto::terminal<mark_placeholder>, SkipGrammar> // don't "skip" mark tags
+ , proto::subscript<SkipGrammar, proto::_> // don't put skips in actions
+ , proto::binary_expr<modifier_tag, proto::_, SkipGrammar> // don't skip modifiers
+ , proto::unary_expr<lookbehind_tag, proto::_> // don't skip lookbehinds
+ , proto::nary_expr<proto::_, proto::vararg<SkipGrammar> > // everything else is fair game!
+ >
+ {};
+
+ template<typename Skip>
+ struct skip_directive
+ {
+ typedef typename proto::result_of::as_expr<Skip>::type skip_type;
+
+ skip_directive(Skip const &skip)
+ : skip_(proto::as_expr(skip))
+ {}
+
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Expr>
+ struct result<This(Expr)>
+ {
+ typedef
+ SkipGrammar::impl<
+ typename proto::result_of::as_expr<Expr>::type
+ , skip_type const &
+ , mpl::void_ &
+ >
+ skip_transform;
+
+ typedef
+ typename proto::shift_right<
+ typename skip_transform::result_type
+ , typename proto::dereference<skip_type>::type
+ >::type
+ type;
+ };
+
+ template<typename Expr>
+ typename result<skip_directive(Expr)>::type
+ operator ()(Expr const &expr) const
+ {
+ mpl::void_ ignore;
+ typedef result<skip_directive(Expr)> result_fun;
+ typename result_fun::type that = {
+ typename result_fun::skip_transform()(proto::as_expr(expr), this->skip_, ignore)
+ , {skip_}
+ };
+ return that;
+ }
+
+ private:
+ skip_type skip_;
+ };
+
+/*
+///////////////////////////////////////////////////////////////////////////////
+/// INTERNAL ONLY
+// BOOST_XPRESSIVE_GLOBAL
+// for defining globals that neither violate the One Definition Rule nor
+// lead to undefined behavior due to global object initialization order.
+//#define BOOST_XPRESSIVE_GLOBAL(type, name, init) \
+// namespace detail \
+// { \
+// template<int Dummy> \
+// struct BOOST_PP_CAT(global_pod_, name) \
+// { \
+// static type const value; \
+// private: \
+// union type_must_be_pod \
+// { \
+// type t; \
+// char ch; \
+// } u; \
+// }; \
+// template<int Dummy> \
+// type const BOOST_PP_CAT(global_pod_, name)<Dummy>::value = init; \
+// } \
+// type const &name = detail::BOOST_PP_CAT(global_pod_, name)<0>::value
+*/
+
+
+} // namespace detail
+
+/// INTERNAL ONLY (for backwards compatibility)
+unsigned int const repeat_max = UINT_MAX-1;
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief For infinite repetition of a sub-expression.
+///
+/// Magic value used with the repeat\<\>() function template
+/// to specify an unbounded repeat. Use as: repeat<17, inf>('a').
+/// The equivalent in perl is /a{17,}/.
+unsigned int const inf = UINT_MAX-1;
+
+/// INTERNAL ONLY (for backwards compatibility)
+proto::terminal<detail::epsilon_matcher>::type const epsilon = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Successfully matches nothing.
+///
+/// Successfully matches a zero-width sequence. nil always succeeds and
+/// never consumes any characters.
+proto::terminal<detail::epsilon_matcher>::type const nil = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches an alpha-numeric character.
+///
+/// The regex traits are used to determine which characters are alpha-numeric.
+/// To match any character that is not alpha-numeric, use ~alnum.
+///
+/// \attention alnum is equivalent to /[[:alnum:]]/ in perl. ~alnum is equivalent
+/// to /[[:^alnum:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const alnum = {{"alnum", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches an alphabetic character.
+///
+/// The regex traits are used to determine which characters are alphabetic.
+/// To match any character that is not alphabetic, use ~alpha.
+///
+/// \attention alpha is equivalent to /[[:alpha:]]/ in perl. ~alpha is equivalent
+/// to /[[:^alpha:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const alpha = {{"alpha", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a blank (horizonal white-space) character.
+///
+/// The regex traits are used to determine which characters are blank characters.
+/// To match any character that is not blank, use ~blank.
+///
+/// \attention blank is equivalent to /[[:blank:]]/ in perl. ~blank is equivalent
+/// to /[[:^blank:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const blank = {{"blank", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a control character.
+///
+/// The regex traits are used to determine which characters are control characters.
+/// To match any character that is not a control character, use ~cntrl.
+///
+/// \attention cntrl is equivalent to /[[:cntrl:]]/ in perl. ~cntrl is equivalent
+/// to /[[:^cntrl:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const cntrl = {{"cntrl", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a digit character.
+///
+/// The regex traits are used to determine which characters are digits.
+/// To match any character that is not a digit, use ~digit.
+///
+/// \attention digit is equivalent to /[[:digit:]]/ in perl. ~digit is equivalent
+/// to /[[:^digit:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const digit = {{"digit", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a graph character.
+///
+/// The regex traits are used to determine which characters are graphable.
+/// To match any character that is not graphable, use ~graph.
+///
+/// \attention graph is equivalent to /[[:graph:]]/ in perl. ~graph is equivalent
+/// to /[[:^graph:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const graph = {{"graph", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a lower-case character.
+///
+/// The regex traits are used to determine which characters are lower-case.
+/// To match any character that is not a lower-case character, use ~lower.
+///
+/// \attention lower is equivalent to /[[:lower:]]/ in perl. ~lower is equivalent
+/// to /[[:^lower:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const lower = {{"lower", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a printable character.
+///
+/// The regex traits are used to determine which characters are printable.
+/// To match any character that is not printable, use ~print.
+///
+/// \attention print is equivalent to /[[:print:]]/ in perl. ~print is equivalent
+/// to /[[:^print:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const print = {{"print", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a punctuation character.
+///
+/// The regex traits are used to determine which characters are punctuation.
+/// To match any character that is not punctuation, use ~punct.
+///
+/// \attention punct is equivalent to /[[:punct:]]/ in perl. ~punct is equivalent
+/// to /[[:^punct:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const punct = {{"punct", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a space character.
+///
+/// The regex traits are used to determine which characters are space characters.
+/// To match any character that is not white-space, use ~space.
+///
+/// \attention space is equivalent to /[[:space:]]/ in perl. ~space is equivalent
+/// to /[[:^space:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const space = {{"space", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches an upper-case character.
+///
+/// The regex traits are used to determine which characters are upper-case.
+/// To match any character that is not upper-case, use ~upper.
+///
+/// \attention upper is equivalent to /[[:upper:]]/ in perl. ~upper is equivalent
+/// to /[[:^upper:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const upper = {{"upper", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a hexadecimal digit character.
+///
+/// The regex traits are used to determine which characters are hex digits.
+/// To match any character that is not a hex digit, use ~xdigit.
+///
+/// \attention xdigit is equivalent to /[[:xdigit:]]/ in perl. ~xdigit is equivalent
+/// to /[[:^xdigit:]]/ in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const xdigit = {{"xdigit", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Beginning of sequence assertion.
+///
+/// For the character sequence [begin, end), 'bos' matches the
+/// zero-width sub-sequence [begin, begin).
+proto::terminal<detail::assert_bos_matcher>::type const bos = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief End of sequence assertion.
+///
+/// For the character sequence [begin, end),
+/// 'eos' matches the zero-width sub-sequence [end, end).
+///
+/// \attention Unlike the perl end of sequence assertion \$, 'eos' will
+/// not match at the position [end-1, end-1) if *(end-1) is '\\n'. To
+/// get that behavior, use (!_n >> eos).
+proto::terminal<detail::assert_eos_matcher>::type const eos = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Beginning of line assertion.
+///
+/// 'bol' matches the zero-width sub-sequence
+/// immediately following a logical newline sequence. The regex traits
+/// is used to determine what constitutes a logical newline sequence.
+proto::terminal<detail::assert_bol_placeholder>::type const bol = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief End of line assertion.
+///
+/// 'eol' matches the zero-width sub-sequence
+/// immediately preceeding a logical newline sequence. The regex traits
+/// is used to determine what constitutes a logical newline sequence.
+proto::terminal<detail::assert_eol_placeholder>::type const eol = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Beginning of word assertion.
+///
+/// 'bow' matches the zero-width sub-sequence
+/// immediately following a non-word character and preceeding a word character.
+/// The regex traits are used to determine what constitutes a word character.
+proto::terminal<detail::assert_word_begin>::type const bow = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief End of word assertion.
+///
+/// 'eow' matches the zero-width sub-sequence
+/// immediately following a word character and preceeding a non-word character.
+/// The regex traits are used to determine what constitutes a word character.
+proto::terminal<detail::assert_word_end>::type const eow = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Word boundary assertion.
+///
+/// '_b' matches the zero-width sub-sequence at the beginning or the end of a word.
+/// It is equivalent to (bow | eow). The regex traits are used to determine what
+/// constitutes a word character. To match a non-word boundary, use ~_b.
+///
+/// \attention _b is like \\b in perl. ~_b is like \\B in perl.
+proto::terminal<detail::assert_word_boundary>::type const _b = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a word character.
+///
+/// '_w' matches a single word character. The regex traits are used to determine which
+/// characters are word characters. Use ~_w to match a character that is not a word
+/// character.
+///
+/// \attention _w is like \\w in perl. ~_w is like \\W in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const _w = {{"w", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a digit character.
+///
+/// '_d' matches a single digit character. The regex traits are used to determine which
+/// characters are digits. Use ~_d to match a character that is not a digit
+/// character.
+///
+/// \attention _d is like \\d in perl. ~_d is like \\D in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const _d = {{"d", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a space character.
+///
+/// '_s' matches a single space character. The regex traits are used to determine which
+/// characters are space characters. Use ~_s to match a character that is not a space
+/// character.
+///
+/// \attention _s is like \\s in perl. ~_s is like \\S in perl.
+proto::terminal<detail::posix_charset_placeholder>::type const _s = {{"s", false}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a literal newline character, '\\n'.
+///
+/// '_n' matches a single newline character, '\\n'. Use ~_n to match a character
+/// that is not a newline.
+///
+/// \attention ~_n is like '.' in perl without the /s modifier.
+proto::terminal<char>::type const _n = {'\n'};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches a logical newline sequence.
+///
+/// '_ln' matches a logical newline sequence. This can be any character in the
+/// line separator class, as determined by the regex traits, or the '\\r\\n' sequence.
+/// For the purpose of back-tracking, '\\r\\n' is treated as a unit.
+/// To match any one character that is not a logical newline, use ~_ln.
+detail::logical_newline_xpression const _ln = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Matches any one character.
+///
+/// Match any character, similar to '.' in perl syntax with the /s modifier.
+/// '_' matches any one character, including the newline.
+///
+/// \attention To match any character except the newline, use ~_n
+proto::terminal<detail::any_matcher>::type const _ = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Reference to the current regex object
+///
+/// Useful when constructing recursive regular expression objects. The 'self'
+/// identifier is a short-hand for the current regex object. For instance,
+/// sregex rx = '(' >> (self | nil) >> ')'; will create a regex object that
+/// matches balanced parens such as "((()))".
+proto::terminal<detail::self_placeholder>::type const self = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Used to create character sets.
+///
+/// There are two ways to create character sets with the 'set' identifier. The
+/// easiest is to create a comma-separated list of the characters in the set,
+/// as in (set= 'a','b','c'). This set will match 'a', 'b', or 'c'. The other
+/// way is to define the set as an argument to the set subscript operator.
+/// For instance, set[ 'a' | range('b','c') | digit ] will match an 'a', 'b',
+/// 'c' or a digit character.
+///
+/// To complement a set, apply the '~' operator. For instance, ~(set= 'a','b','c')
+/// will match any character that is not an 'a', 'b', or 'c'.
+///
+/// Sets can be composed of other, possibly complemented, sets. For instance,
+/// set[ ~digit | ~(set= 'a','b','c') ].
+detail::set_initializer_type const set = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Sub-match placeholder type, used to create named captures in
+/// static regexes.
+///
+/// \c mark_tag is the type of the global sub-match placeholders \c s0, \c s1, etc.. You
+/// can use the \c mark_tag type to create your own sub-match placeholders with
+/// more meaningful names. This is roughly equivalent to the "named capture"
+/// feature of dynamic regular expressions.
+///
+/// To create a named sub-match placeholder, initialize it with a unique integer.
+/// The integer must only be unique within the regex in which the placeholder
+/// is used. Then you can use it within static regexes to created sub-matches
+/// by assigning a sub-expression to it, or to refer back to already created
+/// sub-matches.
+///
+/// \code
+/// mark_tag number(1); // "number" is now equivalent to "s1"
+/// // Match a number, followed by a space and the same number again
+/// sregex rx = (number = +_d) >> ' ' >> number;
+/// \endcode
+///
+/// After a successful \c regex_match() or \c regex_search(), the sub-match placeholder
+/// can be used to index into the <tt>match_results\<\></tt> object to retrieve the
+/// corresponding sub-match.
+struct mark_tag
+ : proto::extends<detail::basic_mark_tag, mark_tag, detail::regex_domain>
+{
+private:
+ typedef proto::extends<detail::basic_mark_tag, mark_tag, detail::regex_domain> base_type;
+
+ static detail::basic_mark_tag make_tag(int mark_nbr)
+ {
+ detail::basic_mark_tag mark = {{mark_nbr}};
+ return mark;
+ }
+
+public:
+ /// \brief Initialize a mark_tag placeholder
+ /// \param mark_nbr An integer that uniquely identifies this \c mark_tag
+ /// within the static regexes in which this \c mark_tag will be used.
+ /// \pre <tt>mark_nbr \> 0</tt>
+ mark_tag(int mark_nbr)
+ : base_type(mark_tag::make_tag(mark_nbr))
+ {
+ // Marks numbers must be integers greater than 0.
+ BOOST_ASSERT(mark_nbr > 0);
+ }
+
+ /// INTERNAL ONLY
+ operator detail::basic_mark_tag const &() const
+ {
+ return this->proto_base();
+ }
+
+ BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT(mark_tag)
+};
+
+// This macro is used when declaring mark_tags that are global because
+// it guarantees that they are statically initialized. That avoids
+// order-of-initialization bugs. In user code, the simpler: mark_tag s0(0);
+// would be preferable.
+/// INTERNAL ONLY
+#define BOOST_XPRESSIVE_GLOBAL_MARK_TAG(NAME, VALUE) \
+ boost::xpressive::mark_tag::proto_base_expr const NAME = {{VALUE}} \
+ /**/
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Sub-match placeholder, like $& in Perl
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s0, 0);
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Sub-match placeholder, like $1 in perl.
+///
+/// To create a sub-match, assign a sub-expression to the sub-match placeholder.
+/// For instance, (s1= _) will match any one character and remember which
+/// character was matched in the 1st sub-match. Later in the pattern, you can
+/// refer back to the sub-match. For instance, (s1= _) >> s1 will match any
+/// character, and then match the same character again.
+///
+/// After a successful regex_match() or regex_search(), the sub-match placeholders
+/// can be used to index into the match_results\<\> object to retrieve the Nth
+/// sub-match.
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s1, 1);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s2, 2);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s3, 3);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s4, 4);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s5, 5);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s6, 6);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s7, 7);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s8, 8);
+BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s9, 9);
+
+// NOTE: For the purpose of xpressive's documentation, make icase() look like an
+// ordinary function. In reality, it is a function object defined in detail/icase.hpp
+// so that it can serve double-duty as regex_constants::icase, the syntax_option_type.
+#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Makes a sub-expression case-insensitive.
+///
+/// Use icase() to make a sub-expression case-insensitive. For instance,
+/// "foo" >> icase(set['b'] >> "ar") will match "foo" exactly followed by
+/// "bar" irrespective of case.
+template<typename Expr> detail::unspecified icase(Expr const &expr) { return 0; }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Makes a literal into a regular expression.
+///
+/// Use as_xpr() to turn a literal into a regular expression. For instance,
+/// "foo" >> "bar" will not compile because both operands to the right-shift
+/// operator are const char*, and no such operator exists. Use as_xpr("foo") >> "bar"
+/// instead.
+///
+/// You can use as_xpr() with character literals in addition to string literals.
+/// For instance, as_xpr('a') will match an 'a'. You can also complement a
+/// character literal, as with ~as_xpr('a'). This will match any one character
+/// that is not an 'a'.
+#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+template<typename Literal> detail::unspecified as_xpr(Literal const &literal) { return 0; }
+#else
+proto::functional::as_expr<> const as_xpr = {};
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Embed a regex object by reference.
+///
+/// \param rex The basic_regex object to embed by reference.
+template<typename BidiIter>
+inline typename proto::terminal<reference_wrapper<basic_regex<BidiIter> const> >::type const
+by_ref(basic_regex<BidiIter> const &rex)
+{
+ reference_wrapper<basic_regex<BidiIter> const> ref(rex);
+ return proto::terminal<reference_wrapper<basic_regex<BidiIter> const> >::type::make(ref);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Match a range of characters.
+///
+/// Match any character in the range [ch_min, ch_max].
+///
+/// \param ch_min The lower end of the range to match.
+/// \param ch_max The upper end of the range to match.
+template<typename Char>
+inline typename proto::terminal<detail::range_placeholder<Char> >::type const
+range(Char ch_min, Char ch_max)
+{
+ detail::range_placeholder<Char> that = {ch_min, ch_max, false};
+ return proto::terminal<detail::range_placeholder<Char> >::type::make(that);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Make a sub-expression optional. Equivalent to !as_xpr(expr).
+///
+/// \param expr The sub-expression to make optional.
+template<typename Expr>
+typename proto::result_of::make_expr<
+ proto::tag::logical_not
+ , proto::default_domain
+ , Expr const &
+>::type const
+optional(Expr const &expr)
+{
+ return proto::make_expr<
+ proto::tag::logical_not
+ , proto::default_domain
+ >(boost::ref(expr));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Repeat a sub-expression multiple times.
+///
+/// There are two forms of the repeat\<\>() function template. To match a
+/// sub-expression N times, use repeat\<N\>(expr). To match a sub-expression
+/// from M to N times, use repeat\<M,N\>(expr).
+///
+/// The repeat\<\>() function creates a greedy quantifier. To make the quantifier
+/// non-greedy, apply the unary minus operator, as in -repeat\<M,N\>(expr).
+///
+/// \param expr The sub-expression to repeat.
+template<unsigned int Min, unsigned int Max, typename Expr>
+typename proto::result_of::make_expr<
+ detail::generic_quant_tag<Min, Max>
+ , proto::default_domain
+ , Expr const &
+>::type const
+repeat(Expr const &expr)
+{
+ return proto::make_expr<
+ detail::generic_quant_tag<Min, Max>
+ , proto::default_domain
+ >(boost::ref(expr));
+}
+
+/// \overload
+///
+template<unsigned int Count, typename Expr2>
+typename proto::result_of::make_expr<
+ detail::generic_quant_tag<Count, Count>
+ , proto::default_domain
+ , Expr2 const &
+>::type const
+repeat(Expr2 const &expr2)
+{
+ return proto::make_expr<
+ detail::generic_quant_tag<Count, Count>
+ , proto::default_domain
+ >(boost::ref(expr2));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Create an independent sub-expression.
+///
+/// Turn off back-tracking for a sub-expression. Any branches or repeats within
+/// the sub-expression will match only one way, and no other alternatives are
+/// tried.
+///
+/// \attention keep(expr) is equivalent to the perl (?>...) extension.
+///
+/// \param expr The sub-expression to modify.
+template<typename Expr>
+typename proto::result_of::make_expr<
+ detail::keeper_tag
+ , proto::default_domain
+ , Expr const &
+>::type const
+keep(Expr const &expr)
+{
+ return proto::make_expr<
+ detail::keeper_tag
+ , proto::default_domain
+ >(boost::ref(expr));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Look-ahead assertion.
+///
+/// before(expr) succeeds if the expr sub-expression would match at the current
+/// position in the sequence, but expr is not included in the match. For instance,
+/// before("foo") succeeds if we are before a "foo". Look-ahead assertions can be
+/// negated with the bit-compliment operator.
+///
+/// \attention before(expr) is equivalent to the perl (?=...) extension.
+/// ~before(expr) is a negative look-ahead assertion, equivalent to the
+/// perl (?!...) extension.
+///
+/// \param expr The sub-expression to put in the look-ahead assertion.
+template<typename Expr>
+typename proto::result_of::make_expr<
+ detail::lookahead_tag
+ , proto::default_domain
+ , Expr const &
+>::type const
+before(Expr const &expr)
+{
+ return proto::make_expr<
+ detail::lookahead_tag
+ , proto::default_domain
+ >(boost::ref(expr));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Look-behind assertion.
+///
+/// after(expr) succeeds if the expr sub-expression would match at the current
+/// position minus N in the sequence, where N is the width of expr. expr is not included in
+/// the match. For instance, after("foo") succeeds if we are after a "foo". Look-behind
+/// assertions can be negated with the bit-complement operator.
+///
+/// \attention after(expr) is equivalent to the perl (?<=...) extension.
+/// ~after(expr) is a negative look-behind assertion, equivalent to the
+/// perl (?<!...) extension.
+///
+/// \param expr The sub-expression to put in the look-ahead assertion.
+///
+/// \pre expr cannot match a variable number of characters.
+template<typename Expr>
+typename proto::result_of::make_expr<
+ detail::lookbehind_tag
+ , proto::default_domain
+ , Expr const &
+>::type const
+after(Expr const &expr)
+{
+ return proto::make_expr<
+ detail::lookbehind_tag
+ , proto::default_domain
+ >(boost::ref(expr));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Specify a regex traits or a std::locale.
+///
+/// imbue() instructs the regex engine to use the specified traits or locale
+/// when matching the regex. The entire expression must use the same traits/locale.
+/// For instance, the following specifies a locale for use with a regex:
+/// std::locale loc;
+/// sregex rx = imbue(loc)(+digit);
+///
+/// \param loc The std::locale or regex traits object.
+template<typename Locale>
+inline detail::modifier_op<detail::locale_modifier<Locale> > const
+imbue(Locale const &loc)
+{
+ detail::modifier_op<detail::locale_modifier<Locale> > mod =
+ {
+ detail::locale_modifier<Locale>(loc)
+ , regex_constants::ECMAScript
+ };
+ return mod;
+}
+
+proto::terminal<detail::attribute_placeholder<mpl::int_<1> > >::type const a1 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<2> > >::type const a2 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<3> > >::type const a3 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<4> > >::type const a4 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<5> > >::type const a5 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<6> > >::type const a6 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<7> > >::type const a7 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<8> > >::type const a8 = {{}};
+proto::terminal<detail::attribute_placeholder<mpl::int_<9> > >::type const a9 = {{}};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief Specify which characters to skip when matching a regex.
+///
+/// <tt>skip()</tt> instructs the regex engine to skip certain characters when matching
+/// a regex. It is most useful for writing regexes that ignore whitespace.
+/// For instance, the following specifies a regex that skips whitespace and
+/// punctuation:
+///
+/// \code
+/// // A sentence is one or more words separated by whitespace
+/// // and punctuation.
+/// sregex word = +alpha;
+/// sregex sentence = skip(set[_s | punct])( +word );
+/// \endcode
+///
+/// The way it works in the above example is to insert
+/// <tt>keep(*set[_s | punct])</tt> before each primitive within the regex.
+/// A "primitive" includes terminals like strings, character sets and nested
+/// regexes. A final <tt>*set[_s | punct]</tt> is added to the end of the
+/// regex. The regex <tt>sentence</tt> specified above is equivalent to
+/// the following:
+///
+/// \code
+/// sregex sentence = +( keep(*set[_s | punct]) >> word )
+/// >> *set[_s | punct];
+/// \endcode
+///
+/// \attention Skipping does not affect how nested regexes are handled because
+/// they are treated atomically. String literals are also treated
+/// atomically; that is, no skipping is done within a string literal. So
+/// <tt>skip(_s)("this that")</tt> is not the same as
+/// <tt>skip(_s)("this" >> as_xpr("that"))</tt>. The first will only match
+/// when there is only one space between "this" and "that". The second will
+/// skip any and all whitespace between "this" and "that".
+///
+/// \param skip A regex that specifies which characters to skip.
+template<typename Skip>
+detail::skip_directive<Skip> skip(Skip const &skip)
+{
+ return detail::skip_directive<Skip>(skip);
+}
+
+namespace detail
+{
+ inline void ignore_unused_regex_primitives()
+ {
+ detail::ignore_unused(repeat_max);
+ detail::ignore_unused(inf);
+ detail::ignore_unused(epsilon);
+ detail::ignore_unused(nil);
+ detail::ignore_unused(alnum);
+ detail::ignore_unused(bos);
+ detail::ignore_unused(eos);
+ detail::ignore_unused(bol);
+ detail::ignore_unused(eol);
+ detail::ignore_unused(bow);
+ detail::ignore_unused(eow);
+ detail::ignore_unused(_b);
+ detail::ignore_unused(_w);
+ detail::ignore_unused(_d);
+ detail::ignore_unused(_s);
+ detail::ignore_unused(_n);
+ detail::ignore_unused(_ln);
+ detail::ignore_unused(_);
+ detail::ignore_unused(self);
+ detail::ignore_unused(set);
+ detail::ignore_unused(s0);
+ detail::ignore_unused(s1);
+ detail::ignore_unused(s2);
+ detail::ignore_unused(s3);
+ detail::ignore_unused(s4);
+ detail::ignore_unused(s5);
+ detail::ignore_unused(s6);
+ detail::ignore_unused(s7);
+ detail::ignore_unused(s8);
+ detail::ignore_unused(s9);
+ detail::ignore_unused(a1);
+ detail::ignore_unused(a2);
+ detail::ignore_unused(a3);
+ detail::ignore_unused(a4);
+ detail::ignore_unused(a5);
+ detail::ignore_unused(a6);
+ detail::ignore_unused(a7);
+ detail::ignore_unused(a8);
+ detail::ignore_unused(a9);
+ detail::ignore_unused(as_xpr);
+ }
+}
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/regex_token_iterator.hpp b/boost/xpressive/regex_token_iterator.hpp
new file mode 100644
index 0000000000..0eb18d57aa
--- /dev/null
+++ b/boost/xpressive/regex_token_iterator.hpp
@@ -0,0 +1,370 @@
+ ///////////////////////////////////////////////////////////////////////////////
+/// \file regex_token_iterator.hpp
+/// Contains the definition of regex_token_iterator, and STL-compatible iterator
+/// for tokenizing a string using a regular expression.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_REGEX_TOKEN_ITERATOR_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_REGEX_TOKEN_ITERATOR_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <vector>
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/xpressive/regex_iterator.hpp>
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+//////////////////////////////////////////////////////////////////////////
+// regex_token_iterator_impl
+//
+template<typename BidiIter>
+struct regex_token_iterator_impl
+ : counted_base<regex_token_iterator_impl<BidiIter> >
+{
+ typedef sub_match<BidiIter> value_type;
+
+ regex_token_iterator_impl
+ (
+ BidiIter begin
+ , BidiIter cur
+ , BidiIter end
+ , BidiIter next_search
+ , basic_regex<BidiIter> const &rex
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ , std::vector<int> subs = std::vector<int>(1, 0)
+ , int n = -2
+ , bool not_null = false
+ )
+ : iter_(begin, cur, end, next_search, rex, flags, not_null)
+ , result_()
+ , n_((-2 == n) ? (int)subs.size() - 1 : n)
+ , subs_()
+ {
+ BOOST_ASSERT(0 != subs.size());
+ this->subs_.swap(subs);
+ }
+
+ bool next()
+ {
+ if(-1 != this->n_)
+ {
+ BidiIter cur = this->iter_.state_.cur_;
+ if(0 != (++this->n_ %= (int)this->subs_.size()) || this->iter_.next())
+ {
+ this->result_ = (-1 == this->subs_[ this->n_ ])
+ ? this->iter_.what_.prefix()
+ : this->iter_.what_[ this->subs_[ this->n_ ] ];
+ return true;
+ }
+ else if(-1 == this->subs_[ this->n_-- ] && cur != this->iter_.state_.end_)
+ {
+ this->result_ = value_type(cur, this->iter_.state_.end_, true);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool equal_to(regex_token_iterator_impl<BidiIter> const &that) const
+ {
+ return this->iter_.equal_to(that.iter_) && this->n_ == that.n_;
+ }
+
+ regex_iterator_impl<BidiIter> iter_;
+ value_type result_;
+ int n_;
+ std::vector<int> subs_;
+};
+
+inline int get_mark_number(int i)
+{
+ return i;
+}
+
+inline std::vector<int> to_vector(int subs)
+{
+ return std::vector<int>(1, subs);
+}
+
+inline std::vector<int> const &to_vector(std::vector<int> const &subs)
+{
+ return subs;
+}
+
+template<typename Int, std::size_t Size>
+inline std::vector<int> to_vector(Int const (&sub_matches)[ Size ])
+{
+ // so that people can specify sub-match indices inline with
+ // string literals, like "\1\2\3", leave off the trailing '\0'
+ std::size_t const size = Size - is_same<Int, char>::value;
+ std::vector<int> vect(size);
+ for(std::size_t i = 0; i < size; ++i)
+ {
+ vect[i] = get_mark_number(sub_matches[i]);
+ }
+ return vect;
+}
+
+template<typename Int>
+inline std::vector<int> to_vector(std::vector<Int> const &sub_matches)
+{
+ BOOST_MPL_ASSERT((is_convertible<Int, int>));
+ return std::vector<int>(sub_matches.begin(), sub_matches.end());
+}
+
+} // namespace detail
+
+//////////////////////////////////////////////////////////////////////////
+// regex_token_iterator
+//
+template<typename BidiIter>
+struct regex_token_iterator
+{
+ typedef basic_regex<BidiIter> regex_type;
+ typedef typename iterator_value<BidiIter>::type char_type;
+ typedef sub_match<BidiIter> value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef value_type const *pointer;
+ typedef value_type const &reference;
+ typedef std::forward_iterator_tag iterator_category;
+
+ /// INTERNAL ONLY
+ typedef detail::regex_token_iterator_impl<BidiIter> impl_type_;
+
+ /// \post \c *this is the end of sequence iterator.
+ regex_token_iterator()
+ : impl_()
+ {
+ }
+
+ /// \param begin The beginning of the character range to search.
+ /// \param end The end of the character range to search.
+ /// \param rex The regex pattern to search for.
+ /// \pre \c [begin,end) is a valid range.
+ regex_token_iterator
+ (
+ BidiIter begin
+ , BidiIter end
+ , basic_regex<BidiIter> const &rex
+ )
+ : impl_()
+ {
+ if(0 != rex.regex_id())
+ {
+ this->impl_ = new impl_type_(begin, begin, end, begin, rex);
+ this->next_();
+ }
+ }
+
+ /// \param begin The beginning of the character range to search.
+ /// \param end The end of the character range to search.
+ /// \param rex The regex pattern to search for.
+ /// \param args A let() expression with argument bindings for semantic actions.
+ /// \pre \c [begin,end) is a valid range.
+ template<typename LetExpr>
+ regex_token_iterator
+ (
+ BidiIter begin
+ , BidiIter end
+ , basic_regex<BidiIter> const &rex
+ , detail::let_<LetExpr> const &args
+ )
+ : impl_()
+ {
+ if(0 != rex.regex_id())
+ {
+ this->impl_ = new impl_type_(begin, begin, end, begin, rex);
+ detail::bind_args(args, this->impl_->iter_.what_);
+ this->next_();
+ }
+ }
+
+ /// \param begin The beginning of the character range to search.
+ /// \param end The end of the character range to search.
+ /// \param rex The regex pattern to search for.
+ /// \param flags Optional match flags, used to control how the expression is matched against the sequence. (See match_flag_type.)
+ /// \pre \c [begin,end) is a valid range.
+ /// \pre \c subs is either an integer greater or equal to -1,
+ /// or else an array or non-empty \c std::vector\<\> of such integers.
+ template<typename Subs>
+ regex_token_iterator
+ (
+ BidiIter begin
+ , BidiIter end
+ , basic_regex<BidiIter> const &rex
+ , Subs const &subs
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ )
+ : impl_()
+ {
+ if(0 != rex.regex_id())
+ {
+ this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags, detail::to_vector(subs));
+ this->next_();
+ }
+ }
+
+ /// \param begin The beginning of the character range to search.
+ /// \param end The end of the character range to search.
+ /// \param rex The regex pattern to search for.
+ /// \param args A let() expression with argument bindings for semantic actions.
+ /// \param flags Optional match flags, used to control how the expression is matched against the sequence. (See match_flag_type.)
+ /// \pre \c [begin,end) is a valid range.
+ /// \pre \c subs is either an integer greater or equal to -1,
+ /// or else an array or non-empty \c std::vector\<\> of such integers.
+ template<typename Subs, typename LetExpr>
+ regex_token_iterator
+ (
+ BidiIter begin
+ , BidiIter end
+ , basic_regex<BidiIter> const &rex
+ , Subs const &subs
+ , detail::let_<LetExpr> const &args
+ , regex_constants::match_flag_type flags = regex_constants::match_default
+ )
+ : impl_()
+ {
+ if(0 != rex.regex_id())
+ {
+ this->impl_ = new impl_type_(begin, begin, end, begin, rex, flags, detail::to_vector(subs));
+ detail::bind_args(args, this->impl_->iter_.what_);
+ this->next_();
+ }
+ }
+
+ /// \post <tt>*this == that</tt>
+ regex_token_iterator(regex_token_iterator<BidiIter> const &that)
+ : impl_(that.impl_) // COW
+ {
+ }
+
+ /// \post <tt>*this == that</tt>
+ regex_token_iterator<BidiIter> &operator =(regex_token_iterator<BidiIter> const &that)
+ {
+ this->impl_ = that.impl_; // COW
+ return *this;
+ }
+
+ friend bool operator ==(regex_token_iterator<BidiIter> const &left, regex_token_iterator<BidiIter> const &right)
+ {
+ if(!left.impl_ || !right.impl_)
+ {
+ return !left.impl_ && !right.impl_;
+ }
+
+ return left.impl_->equal_to(*right.impl_);
+ }
+
+ friend bool operator !=(regex_token_iterator<BidiIter> const &left, regex_token_iterator<BidiIter> const &right)
+ {
+ return !(left == right);
+ }
+
+ value_type const &operator *() const
+ {
+ return this->impl_->result_;
+ }
+
+ value_type const *operator ->() const
+ {
+ return &this->impl_->result_;
+ }
+
+ /// If N == -1 then sets *this equal to the end of sequence iterator.
+ /// Otherwise if N+1 \< subs.size(), then increments N and sets result equal to
+ /// ((subs[N] == -1) ? value_type(what.prefix().str()) : value_type(what[subs[N]].str())).
+ /// Otherwise if what.prefix().first != what[0].second and if the element match_prev_avail is
+ /// not set in flags then sets it. Then locates the next match as if by calling
+ /// regex_search(what[0].second, end, what, *pre, flags), with the following variation:
+ /// in the event that the previous match found was of zero length (what[0].length() == 0)
+ /// then attempts to find a non-zero length match starting at what[0].second, only if that
+ /// fails and provided what[0].second != suffix().second does it look for a (possibly zero
+ /// length) match starting from what[0].second + 1. If such a match is found then sets N
+ /// equal to zero, and sets result equal to
+ /// ((subs[N] == -1) ? value_type(what.prefix().str()) : value_type(what[subs[N]].str())).
+ /// Otherwise if no further matches were found, then let last_end be the endpoint of the last
+ /// match that was found. Then if last_end != end and subs[0] == -1 sets N equal to -1 and
+ /// sets result equal to value_type(last_end, end). Otherwise sets *this equal to the end
+ /// of sequence iterator.
+ regex_token_iterator<BidiIter> &operator ++()
+ {
+ this->fork_(); // un-share the implementation
+ this->next_();
+ return *this;
+ }
+
+ regex_token_iterator<BidiIter> operator ++(int)
+ {
+ regex_token_iterator<BidiIter> tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+private:
+
+ /// INTERNAL ONLY
+ void fork_()
+ {
+ if(1 != this->impl_->use_count())
+ {
+ intrusive_ptr<impl_type_> clone = new impl_type_
+ (
+ this->impl_->iter_.state_.begin_
+ , this->impl_->iter_.state_.cur_
+ , this->impl_->iter_.state_.end_
+ , this->impl_->iter_.state_.next_search_
+ , this->impl_->iter_.rex_
+ , this->impl_->iter_.flags_
+ , this->impl_->subs_
+ , this->impl_->n_
+ , this->impl_->iter_.not_null_
+ );
+
+ // only copy the match_results struct if we have to. Note: if the next call
+ // to impl_->next() will return false or call regex_search, we don't need to
+ // copy the match_results struct.
+ if(-1 != this->impl_->n_ && this->impl_->n_ + 1 != static_cast<int>(this->impl_->subs_.size()))
+ {
+ // BUGBUG This is expensive -- it causes the sequence_stack to be cleared.
+ // Find a better way
+ clone->iter_.what_ = this->impl_->iter_.what_;
+ }
+ else
+ {
+ // At the very least, copy the action args
+ detail::core_access<BidiIter>::get_action_args(clone->iter_.what_)
+ = detail::core_access<BidiIter>::get_action_args(this->impl_->iter_.what_);
+ }
+
+ this->impl_.swap(clone);
+ }
+ }
+
+ /// INTERNAL ONLY
+ void next_()
+ {
+ BOOST_ASSERT(this->impl_ && 1 == this->impl_->use_count());
+ if(!this->impl_->next())
+ {
+ this->impl_ = 0;
+ }
+ }
+
+ intrusive_ptr<impl_type_> impl_;
+};
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/regex_traits.hpp b/boost/xpressive/regex_traits.hpp
new file mode 100644
index 0000000000..f7a03e2cb4
--- /dev/null
+++ b/boost/xpressive/regex_traits.hpp
@@ -0,0 +1,107 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file regex_traits.hpp
+/// Includes the C regex traits or the CPP regex traits header file depending on the
+/// BOOST_XPRESSIVE_USE_C_TRAITS macro.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_REGEX_TRAITS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_REGEX_TRAITS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+#ifdef BOOST_XPRESSIVE_USE_C_TRAITS
+# include <boost/xpressive/traits/c_regex_traits.hpp>
+#else
+# include <boost/xpressive/traits/cpp_regex_traits.hpp>
+#endif
+
+namespace boost { namespace xpressive
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_traits_version_1_tag
+/// Tag used to denote that a traits class conforms to the version 1 traits
+/// interface.
+struct regex_traits_version_1_tag
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_traits_version_2_tag
+/// Tag used to denote that a traits class conforms to the version 2 traits
+/// interface.
+struct regex_traits_version_2_tag
+ : regex_traits_version_1_tag
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_traits_version_1_case_fold_tag DEPRECATED use has_fold_case trait
+/// INTERNAL ONLY
+///
+struct regex_traits_version_1_case_fold_tag
+ : regex_traits_version_1_tag
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// has_fold_case
+/// Trait used to denote that a traits class has the fold_case member function.
+template<typename Traits>
+struct has_fold_case
+ : is_convertible<
+ typename Traits::version_tag *
+ , regex_traits_version_1_case_fold_tag *
+ >
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_traits
+/// Thin wrapper around the default regex_traits implementation, either
+/// cpp_regex_traits or c_regex_traits
+///
+template<typename Char, typename Impl>
+struct regex_traits
+ : Impl
+{
+ typedef typename Impl::locale_type locale_type;
+
+ regex_traits()
+ : Impl()
+ {
+ }
+
+ explicit regex_traits(locale_type const &loc)
+ : Impl(loc)
+ {
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// lookup_classname
+/// INTERNAL ONLY
+template<typename Traits, std::size_t N>
+inline typename Traits::char_class_type
+lookup_classname(Traits const &traits, char const (&cname)[N], bool icase)
+{
+ typename Traits::char_type name[N] = {0};
+ for(std::size_t j = 0; j < N-1; ++j)
+ {
+ name[j] = traits.widen(cname[j]);
+ }
+ return traits.lookup_classname(name, name + N - 1, icase);
+}
+
+}}
+
+#endif
diff --git a/boost/xpressive/sub_match.hpp b/boost/xpressive/sub_match.hpp
new file mode 100644
index 0000000000..5bd778ba9f
--- /dev/null
+++ b/boost/xpressive/sub_match.hpp
@@ -0,0 +1,392 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file sub_match.hpp
+/// Contains the definition of the class template sub_match\<\>
+/// and associated helper functions
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_SUB_MATCH_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_SUB_MATCH_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <iosfwd>
+#include <string>
+#include <utility>
+#include <iterator>
+#include <algorithm>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+//{{AFX_DOC_COMMENT
+///////////////////////////////////////////////////////////////////////////////
+// This is a hack to get Doxygen to show the inheritance relation between
+// sub_match<T> and std::pair<T,T>.
+#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
+/// INTERNAL ONLY
+namespace std
+{
+ /// INTERNAL ONLY
+ template<typename, typename> struct pair {};
+}
+#endif
+//}}AFX_DOC_COMMENT
+
+namespace boost { namespace xpressive
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// sub_match
+//
+/// \brief Class template sub_match denotes the sequence of characters matched by a particular marked sub-expression.
+///
+/// When the marked sub-expression denoted by an object of type sub_match\<\> participated in a
+/// regular expression match then member matched evaluates to true, and members first and second
+/// denote the range of characters [first,second) which formed that match. Otherwise matched is false,
+/// and members first and second contained undefined values.
+///
+/// If an object of type sub_match\<\> represents sub-expression 0 - that is to say the whole match -
+/// then member matched is always true, unless a partial match was obtained as a result of the flag
+/// match_partial being passed to a regular expression algorithm, in which case member matched is
+/// false, and members first and second represent the character range that formed the partial match.
+template<typename BidiIter>
+struct sub_match
+ : std::pair<BidiIter, BidiIter>
+{
+private:
+ /// INTERNAL ONLY
+ ///
+ struct dummy { int i_; };
+ typedef int dummy::*bool_type;
+
+public:
+ typedef typename iterator_value<BidiIter>::type value_type;
+ typedef typename iterator_difference<BidiIter>::type difference_type;
+ typedef typename detail::string_type<value_type>::type string_type;
+ typedef BidiIter iterator;
+
+ sub_match()
+ : std::pair<BidiIter, BidiIter>()
+ , matched(false)
+ {
+ }
+
+ sub_match(BidiIter first, BidiIter second, bool matched_ = false)
+ : std::pair<BidiIter, BidiIter>(first, second)
+ , matched(matched_)
+ {
+ }
+
+ string_type str() const
+ {
+ return this->matched ? string_type(this->first, this->second) : string_type();
+ }
+
+ operator string_type() const
+ {
+ return this->matched ? string_type(this->first, this->second) : string_type();
+ }
+
+ difference_type length() const
+ {
+ return this->matched ? std::distance(this->first, this->second) : 0;
+ }
+
+ operator bool_type() const
+ {
+ return this->matched ? &dummy::i_ : 0;
+ }
+
+ bool operator !() const
+ {
+ return !this->matched;
+ }
+
+ /// \brief Performs a lexicographic string comparison
+ /// \param str the string against which to compare
+ /// \return the results of (*this).str().compare(str)
+ int compare(string_type const &str) const
+ {
+ return this->str().compare(str);
+ }
+
+ /// \overload
+ ///
+ int compare(sub_match const &sub) const
+ {
+ return this->str().compare(sub.str());
+ }
+
+ /// \overload
+ ///
+ int compare(value_type const *ptr) const
+ {
+ return this->str().compare(ptr);
+ }
+
+ /// \brief true if this sub-match participated in the full match.
+ bool matched;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief insertion operator for sending sub-matches to ostreams
+/// \param sout output stream.
+/// \param sub sub_match object to be written to the stream.
+/// \return sout \<\< sub.str()
+template<typename BidiIter, typename Char, typename Traits>
+inline std::basic_ostream<Char, Traits> &operator <<
+(
+ std::basic_ostream<Char, Traits> &sout
+ , sub_match<BidiIter> const &sub
+)
+{
+ typedef typename iterator_value<BidiIter>::type char_type;
+ if(sub.matched)
+ {
+ std::ostream_iterator<char_type, Char, Traits> iout(sout);
+ std::copy(sub.first, sub.second, iout);
+ }
+ return sout;
+}
+
+
+// BUGBUG make these more efficient
+
+template<typename BidiIter>
+bool operator == (sub_match<BidiIter> const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs.compare(rhs) == 0;
+}
+
+template<typename BidiIter>
+bool operator != (sub_match<BidiIter> const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs.compare(rhs) != 0;
+}
+
+template<typename BidiIter>
+bool operator < (sub_match<BidiIter> const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs.compare(rhs) < 0;
+}
+
+template<typename BidiIter>
+bool operator <= (sub_match<BidiIter> const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs.compare(rhs) <= 0;
+}
+
+template<typename BidiIter>
+bool operator >= (sub_match<BidiIter> const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs.compare(rhs) >= 0;
+}
+
+template<typename BidiIter>
+bool operator > (sub_match<BidiIter> const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs.compare(rhs) > 0;
+}
+
+template<typename BidiIter>
+bool operator == (typename iterator_value<BidiIter>::type const *lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs == rhs.str();
+}
+
+template<typename BidiIter>
+bool operator != (typename iterator_value<BidiIter>::type const *lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs != rhs.str();
+}
+
+template<typename BidiIter>
+bool operator < (typename iterator_value<BidiIter>::type const *lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs < rhs.str();
+}
+
+template<typename BidiIter>
+bool operator > (typename iterator_value<BidiIter>::type const *lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs> rhs.str();
+}
+
+template<typename BidiIter>
+bool operator >= (typename iterator_value<BidiIter>::type const *lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs >= rhs.str();
+}
+
+template<typename BidiIter>
+bool operator <= (typename iterator_value<BidiIter>::type const *lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs <= rhs.str();
+}
+
+template<typename BidiIter>
+bool operator == (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const *rhs)
+{
+ return lhs.str() == rhs;
+}
+
+template<typename BidiIter>
+bool operator != (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const *rhs)
+{
+ return lhs.str() != rhs;
+}
+
+template<typename BidiIter>
+bool operator < (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const *rhs)
+{
+ return lhs.str() < rhs;
+}
+
+template<typename BidiIter>
+bool operator > (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const *rhs)
+{
+ return lhs.str() > rhs;
+}
+
+template<typename BidiIter>
+bool operator >= (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const *rhs)
+{
+ return lhs.str() >= rhs;
+}
+
+template<typename BidiIter>
+bool operator <= (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const *rhs)
+{
+ return lhs.str() <= rhs;
+}
+
+template<typename BidiIter>
+bool operator == (typename iterator_value<BidiIter>::type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs == rhs.str();
+}
+
+template<typename BidiIter>
+bool operator != (typename iterator_value<BidiIter>::type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs != rhs.str();
+}
+
+template<typename BidiIter>
+bool operator < (typename iterator_value<BidiIter>::type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs < rhs.str();
+}
+
+template<typename BidiIter>
+bool operator > (typename iterator_value<BidiIter>::type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs> rhs.str();
+}
+
+template<typename BidiIter>
+bool operator >= (typename iterator_value<BidiIter>::type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs >= rhs.str();
+}
+
+template<typename BidiIter>
+bool operator <= (typename iterator_value<BidiIter>::type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs <= rhs.str();
+}
+
+template<typename BidiIter>
+bool operator == (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const &rhs)
+{
+ return lhs.str() == rhs;
+}
+
+template<typename BidiIter>
+bool operator != (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const &rhs)
+{
+ return lhs.str() != rhs;
+}
+
+template<typename BidiIter>
+bool operator < (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const &rhs)
+{
+ return lhs.str() < rhs;
+}
+
+template<typename BidiIter>
+bool operator > (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const &rhs)
+{
+ return lhs.str() > rhs;
+}
+
+template<typename BidiIter>
+bool operator >= (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const &rhs)
+{
+ return lhs.str() >= rhs;
+}
+
+template<typename BidiIter>
+bool operator <= (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const &rhs)
+{
+ return lhs.str() <= rhs;
+}
+
+// Operator+ convenience function
+template<typename BidiIter>
+typename sub_match<BidiIter>::string_type
+operator + (sub_match<BidiIter> const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs.str() + rhs.str();
+}
+
+template<typename BidiIter>
+typename sub_match<BidiIter>::string_type
+operator + (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const &rhs)
+{
+ return lhs.str() + rhs;
+}
+
+template<typename BidiIter>
+typename sub_match<BidiIter>::string_type
+operator + (typename iterator_value<BidiIter>::type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs + rhs.str();
+}
+
+template<typename BidiIter>
+typename sub_match<BidiIter>::string_type
+operator + (sub_match<BidiIter> const &lhs, typename iterator_value<BidiIter>::type const *rhs)
+{
+ return lhs.str() + rhs;
+}
+
+template<typename BidiIter>
+typename sub_match<BidiIter>::string_type
+operator + (typename iterator_value<BidiIter>::type const *lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs + rhs.str();
+}
+
+template<typename BidiIter>
+typename sub_match<BidiIter>::string_type
+operator + (sub_match<BidiIter> const &lhs, typename sub_match<BidiIter>::string_type const &rhs)
+{
+ return lhs.str() + rhs;
+}
+
+template<typename BidiIter>
+typename sub_match<BidiIter>::string_type
+operator + (typename sub_match<BidiIter>::string_type const &lhs, sub_match<BidiIter> const &rhs)
+{
+ return lhs + rhs.str();
+}
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/traits/c_regex_traits.hpp b/boost/xpressive/traits/c_regex_traits.hpp
new file mode 100644
index 0000000000..805dcd3773
--- /dev/null
+++ b/boost/xpressive/traits/c_regex_traits.hpp
@@ -0,0 +1,413 @@
+//////////////////////////////////////////////////////////////////////////////
+/// \file c_regex_traits.hpp
+/// Contains the definition of the c_regex_traits\<\> template, which is a
+/// wrapper for the C locale functions that can be used to customize the
+/// behavior of static and dynamic regexes.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_TRAITS_C_REGEX_TRAITS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_TRAITS_C_REGEX_TRAITS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <cstdlib>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/xpressive/traits/detail/c_ctype.hpp>
+
+namespace boost { namespace xpressive
+{
+
+namespace detail
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // empty_locale
+ struct empty_locale
+ {
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // c_regex_traits_base
+ template<typename Char, std::size_t SizeOfChar = sizeof(Char)>
+ struct c_regex_traits_base
+ {
+ protected:
+ template<typename Traits>
+ void imbue(Traits const &tr)
+ {
+ }
+ };
+
+ template<typename Char>
+ struct c_regex_traits_base<Char, 1>
+ {
+ protected:
+ template<typename Traits>
+ static void imbue(Traits const &)
+ {
+ }
+ };
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ template<std::size_t SizeOfChar>
+ struct c_regex_traits_base<wchar_t, SizeOfChar>
+ {
+ protected:
+ template<typename Traits>
+ static void imbue(Traits const &)
+ {
+ }
+ };
+ #endif
+
+ template<typename Char>
+ Char c_tolower(Char);
+
+ template<typename Char>
+ Char c_toupper(Char);
+
+ template<>
+ inline char c_tolower(char ch)
+ {
+ using namespace std;
+ return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+ }
+
+ template<>
+ inline char c_toupper(char ch)
+ {
+ using namespace std;
+ return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+ }
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ template<>
+ inline wchar_t c_tolower(wchar_t ch)
+ {
+ using namespace std;
+ return towlower(ch);
+ }
+
+ template<>
+ inline wchar_t c_toupper(wchar_t ch)
+ {
+ using namespace std;
+ return towupper(ch);
+ }
+ #endif
+
+} // namespace detail
+
+///////////////////////////////////////////////////////////////////////////////
+// regex_traits_version_1_tag
+//
+struct regex_traits_version_1_tag;
+
+///////////////////////////////////////////////////////////////////////////////
+// c_regex_traits
+//
+/// \brief Encapsaulates the standard C locale functions for use by the
+/// basic_regex\<\> class template.
+template<typename Char>
+struct c_regex_traits
+ : detail::c_regex_traits_base<Char>
+{
+ typedef Char char_type;
+ typedef std::basic_string<char_type> string_type;
+ typedef detail::empty_locale locale_type;
+ typedef typename detail::char_class_impl<Char>::char_class_type char_class_type;
+ typedef regex_traits_version_2_tag version_tag;
+ typedef detail::c_regex_traits_base<Char> base_type;
+
+ /// Initialize a c_regex_traits object to use the global C locale.
+ ///
+ c_regex_traits(locale_type const &loc = locale_type())
+ : base_type()
+ {
+ this->imbue(loc);
+ }
+
+ /// Checks two c_regex_traits objects for equality
+ ///
+ /// \return true.
+ bool operator ==(c_regex_traits<char_type> const &) const
+ {
+ return true;
+ }
+
+ /// Checks two c_regex_traits objects for inequality
+ ///
+ /// \return false.
+ bool operator !=(c_regex_traits<char_type> const &) const
+ {
+ return false;
+ }
+
+ /// Convert a char to a Char
+ ///
+ /// \param ch The source character.
+ /// \return ch if Char is char, std::btowc(ch) if Char is wchar_t.
+ static char_type widen(char ch);
+
+ /// Returns a hash value for a Char in the range [0, UCHAR_MAX]
+ ///
+ /// \param ch The source character.
+ /// \return a value between 0 and UCHAR_MAX, inclusive.
+ static unsigned char hash(char_type ch)
+ {
+ return static_cast<unsigned char>(std::char_traits<Char>::to_int_type(ch));
+ }
+
+ /// No-op
+ ///
+ /// \param ch The source character.
+ /// \return ch
+ static char_type translate(char_type ch)
+ {
+ return ch;
+ }
+
+ /// Converts a character to lower-case using the current global C locale.
+ ///
+ /// \param ch The source character.
+ /// \return std::tolower(ch) if Char is char, std::towlower(ch) if Char is wchar_t.
+ static char_type translate_nocase(char_type ch)
+ {
+ return detail::c_tolower(ch);
+ }
+
+ /// Converts a character to lower-case using the current global C locale.
+ ///
+ /// \param ch The source character.
+ /// \return std::tolower(ch) if Char is char, std::towlower(ch) if Char is wchar_t.
+ static char_type tolower(char_type ch)
+ {
+ return detail::c_tolower(ch);
+ }
+
+ /// Converts a character to upper-case using the current global C locale.
+ ///
+ /// \param ch The source character.
+ /// \return std::toupper(ch) if Char is char, std::towupper(ch) if Char is wchar_t.
+ static char_type toupper(char_type ch)
+ {
+ return detail::c_toupper(ch);
+ }
+
+ /// Returns a string_type containing all the characters that compare equal
+ /// disregrarding case to the one passed in. This function can only be called
+ /// if has_fold_case<c_regex_traits<Char> >::value is true.
+ ///
+ /// \param ch The source character.
+ /// \return string_type containing all chars which are equal to ch when disregarding
+ /// case
+ //typedef array<char_type, 2> fold_case_type;
+ string_type fold_case(char_type ch) const
+ {
+ BOOST_MPL_ASSERT((is_same<char_type, char>));
+ char_type ntcs[] = {
+ detail::c_tolower(ch)
+ , detail::c_toupper(ch)
+ , 0
+ };
+ if(ntcs[1] == ntcs[0])
+ ntcs[1] = 0;
+ return string_type(ntcs);
+ }
+
+ /// Checks to see if a character is within a character range.
+ ///
+ /// \param first The bottom of the range, inclusive.
+ /// \param last The top of the range, inclusive.
+ /// \param ch The source character.
+ /// \return first <= ch && ch <= last.
+ static bool in_range(char_type first, char_type last, char_type ch)
+ {
+ return first <= ch && ch <= last;
+ }
+
+ /// Checks to see if a character is within a character range, irregardless of case.
+ ///
+ /// \param first The bottom of the range, inclusive.
+ /// \param last The top of the range, inclusive.
+ /// \param ch The source character.
+ /// \return in_range(first, last, ch) || in_range(first, last, tolower(ch)) || in_range(first,
+ /// last, toupper(ch))
+ /// \attention The default implementation doesn't do proper Unicode
+ /// case folding, but this is the best we can do with the standard
+ /// C locale functions.
+ static bool in_range_nocase(char_type first, char_type last, char_type ch)
+ {
+ return c_regex_traits::in_range(first, last, ch)
+ || c_regex_traits::in_range(first, last, detail::c_tolower(ch))
+ || c_regex_traits::in_range(first, last, detail::c_toupper(ch));
+ }
+
+ /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
+ /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
+ /// then v.transform(G1, G2) < v.transform(H1, H2).
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ static string_type transform(FwdIter begin, FwdIter end)
+ {
+ BOOST_ASSERT(false); // BUGBUG implement me
+ }
+
+ /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
+ /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
+ /// when character case is not considered then
+ /// v.transform_primary(G1, G2) < v.transform_primary(H1, H2).
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ static string_type transform_primary(FwdIter begin, FwdIter end)
+ {
+ BOOST_ASSERT(false); // BUGBUG implement me
+ }
+
+ /// Returns a sequence of characters that represents the collating element
+ /// consisting of the character sequence designated by the iterator range [F1, F2).
+ /// Returns an empty string if the character sequence is not a valid collating element.
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ static string_type lookup_collatename(FwdIter begin, FwdIter end)
+ {
+ BOOST_ASSERT(false); // BUGBUG implement me
+ }
+
+ /// For the character class name represented by the specified character sequence,
+ /// return the corresponding bitmask representation.
+ ///
+ /// \param begin A forward iterator to the start of the character sequence representing
+ /// the name of the character class.
+ /// \param end The end of the character sequence.
+ /// \param icase Specifies whether the returned bitmask should represent the case-insensitive
+ /// version of the character class.
+ /// \return A bitmask representing the character class.
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ return detail::char_class_impl<char_type>::lookup_classname(begin, end, icase);
+ }
+
+ /// Tests a character against a character class bitmask.
+ ///
+ /// \param ch The character to test.
+ /// \param mask The character class bitmask against which to test.
+ /// \pre mask is a bitmask returned by lookup_classname, or is several such masks bit-or'ed
+ /// together.
+ /// \return true if the character is a member of any of the specified character classes, false
+ /// otherwise.
+ static bool isctype(char_type ch, char_class_type mask)
+ {
+ return detail::char_class_impl<char_type>::isctype(ch, mask);
+ }
+
+ /// Convert a digit character into the integer it represents.
+ ///
+ /// \param ch The digit character.
+ /// \param radix The radix to use for the conversion.
+ /// \pre radix is one of 8, 10, or 16.
+ /// \return -1 if ch is not a digit character, the integer value of the character otherwise. If
+ /// char_type is char, std::strtol is used for the conversion. If char_type is wchar_t,
+ /// std::wcstol is used.
+ static int value(char_type ch, int radix);
+
+ /// No-op
+ ///
+ locale_type imbue(locale_type loc)
+ {
+ this->base_type::imbue(*this);
+ return loc;
+ }
+
+ /// No-op
+ ///
+ static locale_type getloc()
+ {
+ locale_type loc;
+ return loc;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// c_regex_traits<>::widen specializations
+/// INTERNAL ONLY
+template<>
+inline char c_regex_traits<char>::widen(char ch)
+{
+ return ch;
+}
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+/// INTERNAL ONLY
+template<>
+inline wchar_t c_regex_traits<wchar_t>::widen(char ch)
+{
+ using namespace std;
+ return btowc(ch);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// c_regex_traits<>::hash specializations
+/// INTERNAL ONLY
+template<>
+inline unsigned char c_regex_traits<char>::hash(char ch)
+{
+ return static_cast<unsigned char>(ch);
+}
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+/// INTERNAL ONLY
+template<>
+inline unsigned char c_regex_traits<wchar_t>::hash(wchar_t ch)
+{
+ return static_cast<unsigned char>(ch);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// c_regex_traits<>::value specializations
+/// INTERNAL ONLY
+template<>
+inline int c_regex_traits<char>::value(char ch, int radix)
+{
+ using namespace std;
+ BOOST_ASSERT(8 == radix || 10 == radix || 16 == radix);
+ char begin[2] = { ch, '\0' }, *end = 0;
+ int val = strtol(begin, &end, radix);
+ return begin == end ? -1 : val;
+}
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+/// INTERNAL ONLY
+template<>
+inline int c_regex_traits<wchar_t>::value(wchar_t ch, int radix)
+{
+ using namespace std;
+ BOOST_ASSERT(8 == radix || 10 == radix || 16 == radix);
+ wchar_t begin[2] = { ch, L'\0' }, *end = 0;
+ int val = wcstol(begin, &end, radix);
+ return begin == end ? -1 : val;
+}
+#endif
+
+// Narrow C traits has fold_case() member function.
+template<>
+struct has_fold_case<c_regex_traits<char> >
+ : mpl::true_
+{
+};
+
+}}
+
+#endif
diff --git a/boost/xpressive/traits/cpp_regex_traits.hpp b/boost/xpressive/traits/cpp_regex_traits.hpp
new file mode 100644
index 0000000000..5d5c7fd0b1
--- /dev/null
+++ b/boost/xpressive/traits/cpp_regex_traits.hpp
@@ -0,0 +1,694 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file cpp_regex_traits.hpp
+/// Contains the definition of the cpp_regex_traits\<\> template, which is a
+/// wrapper for std::locale that can be used to customize the behavior of
+/// static and dynamic regexes.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_TRAITS_CPP_REGEX_TRAITS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_TRAITS_CPP_REGEX_TRAITS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <ios>
+#include <string>
+#include <locale>
+#include <sstream>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/integer.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/utility/literals.hpp>
+
+// From John Maddock:
+// Fix for gcc prior to 3.4: std::ctype<wchar_t> doesn't allow masks to be combined, for example:
+// std::use_facet<std::ctype<wchar_t> >(locale()).is(std::ctype_base::lower|std::ctype_base::upper, L'a');
+// incorrectly returns false.
+// NOTE: later version of the gcc define __GLIBCXX__, not __GLIBCPP__
+#if BOOST_WORKAROUND(__GLIBCPP__, != 0)
+# define BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
+#endif
+
+namespace boost { namespace xpressive
+{
+
+namespace detail
+{
+ // define an unsigned integral typedef of the same size as std::ctype_base::mask
+ typedef boost::uint_t<sizeof(std::ctype_base::mask) * CHAR_BIT>::least umask_t;
+ BOOST_MPL_ASSERT_RELATION(sizeof(std::ctype_base::mask), ==, sizeof(umask_t));
+
+ // Calculate what the size of the umaskex_t type should be to fix the 3 extra bitmasks
+ // 11 char categories in ctype_base
+ // + 3 extra categories for xpressive
+ // = 14 total bits needed
+ int const umaskex_bits = (14 > (sizeof(umask_t) * CHAR_BIT)) ? 14 : sizeof(umask_t) * CHAR_BIT;
+
+ // define an unsigned integral type with at least umaskex_bits
+ typedef boost::uint_t<umaskex_bits>::fast umaskex_t;
+ BOOST_MPL_ASSERT_RELATION(sizeof(umask_t), <=, sizeof(umaskex_t));
+
+ // cast a ctype mask to a umaskex_t
+ template<std::ctype_base::mask Mask>
+ struct mask_cast
+ {
+ BOOST_STATIC_CONSTANT(umaskex_t, value = static_cast<umask_t>(Mask));
+ };
+
+ #ifdef __CYGWIN__
+ // Work around a gcc warning on cygwin
+ template<>
+ struct mask_cast<std::ctype_base::print>
+ {
+ BOOST_MPL_ASSERT_RELATION('\227', ==, std::ctype_base::print);
+ BOOST_STATIC_CONSTANT(umaskex_t, value = 0227);
+ };
+ #endif
+
+ #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+ template<std::ctype_base::mask Mask>
+ umaskex_t const mask_cast<Mask>::value;
+ #endif
+
+ #ifndef BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
+ // an unsigned integer with the highest bit set
+ umaskex_t const highest_bit = static_cast<umaskex_t>(1) << (sizeof(umaskex_t) * CHAR_BIT - 1);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // unused_mask
+ // find a bit in an int that isn't set
+ template<umaskex_t In, umaskex_t Out = highest_bit, bool Done = (0 == (Out & In))>
+ struct unused_mask
+ {
+ BOOST_MPL_ASSERT_RELATION(1, !=, Out);
+ BOOST_STATIC_CONSTANT(umaskex_t, value = (unused_mask<In, (Out >> 1)>::value));
+ };
+
+ template<umaskex_t In, umaskex_t Out>
+ struct unused_mask<In, Out, true>
+ {
+ BOOST_STATIC_CONSTANT(umaskex_t, value = Out);
+ };
+
+ #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+ template<umaskex_t In, umaskex_t Out, bool Done>
+ umaskex_t const unused_mask<In, Out, Done>::value;
+ #endif
+
+ umaskex_t const std_ctype_alnum = mask_cast<std::ctype_base::alnum>::value;
+ umaskex_t const std_ctype_alpha = mask_cast<std::ctype_base::alpha>::value;
+ umaskex_t const std_ctype_cntrl = mask_cast<std::ctype_base::cntrl>::value;
+ umaskex_t const std_ctype_digit = mask_cast<std::ctype_base::digit>::value;
+ umaskex_t const std_ctype_graph = mask_cast<std::ctype_base::graph>::value;
+ umaskex_t const std_ctype_lower = mask_cast<std::ctype_base::lower>::value;
+ umaskex_t const std_ctype_print = mask_cast<std::ctype_base::print>::value;
+ umaskex_t const std_ctype_punct = mask_cast<std::ctype_base::punct>::value;
+ umaskex_t const std_ctype_space = mask_cast<std::ctype_base::space>::value;
+ umaskex_t const std_ctype_upper = mask_cast<std::ctype_base::upper>::value;
+ umaskex_t const std_ctype_xdigit = mask_cast<std::ctype_base::xdigit>::value;
+
+ // Reserve some bits for the implementation
+ #if defined(__GLIBCXX__)
+ umaskex_t const std_ctype_reserved = 0x8000;
+ #elif defined(_CPPLIB_VER) && defined(BOOST_WINDOWS)
+ umaskex_t const std_ctype_reserved = 0x8200;
+ #else
+ umaskex_t const std_ctype_reserved = 0;
+ #endif
+
+ // Bitwise-or all the ctype masks together
+ umaskex_t const all_ctype_masks = std_ctype_reserved
+ | std_ctype_alnum | std_ctype_alpha | std_ctype_cntrl | std_ctype_digit
+ | std_ctype_graph | std_ctype_lower | std_ctype_print | std_ctype_punct
+ | std_ctype_space | std_ctype_upper | std_ctype_xdigit;
+
+ // define a new mask for "underscore" ("word" == alnum | underscore)
+ umaskex_t const non_std_ctype_underscore = unused_mask<all_ctype_masks>::value;
+
+ // define a new mask for "blank"
+ umaskex_t const non_std_ctype_blank = unused_mask<all_ctype_masks | non_std_ctype_underscore>::value;
+
+ // define a new mask for "newline"
+ umaskex_t const non_std_ctype_newline = unused_mask<all_ctype_masks | non_std_ctype_underscore | non_std_ctype_blank>::value;
+
+ #else
+ ///////////////////////////////////////////////////////////////////////////////
+ // Ugly work-around for buggy ctype facets.
+ umaskex_t const std_ctype_alnum = 1 << 0;
+ umaskex_t const std_ctype_alpha = 1 << 1;
+ umaskex_t const std_ctype_cntrl = 1 << 2;
+ umaskex_t const std_ctype_digit = 1 << 3;
+ umaskex_t const std_ctype_graph = 1 << 4;
+ umaskex_t const std_ctype_lower = 1 << 5;
+ umaskex_t const std_ctype_print = 1 << 6;
+ umaskex_t const std_ctype_punct = 1 << 7;
+ umaskex_t const std_ctype_space = 1 << 8;
+ umaskex_t const std_ctype_upper = 1 << 9;
+ umaskex_t const std_ctype_xdigit = 1 << 10;
+ umaskex_t const non_std_ctype_underscore = 1 << 11;
+ umaskex_t const non_std_ctype_blank = 1 << 12;
+ umaskex_t const non_std_ctype_newline = 1 << 13;
+
+ static umaskex_t const std_masks[] =
+ {
+ mask_cast<std::ctype_base::alnum>::value
+ , mask_cast<std::ctype_base::alpha>::value
+ , mask_cast<std::ctype_base::cntrl>::value
+ , mask_cast<std::ctype_base::digit>::value
+ , mask_cast<std::ctype_base::graph>::value
+ , mask_cast<std::ctype_base::lower>::value
+ , mask_cast<std::ctype_base::print>::value
+ , mask_cast<std::ctype_base::punct>::value
+ , mask_cast<std::ctype_base::space>::value
+ , mask_cast<std::ctype_base::upper>::value
+ , mask_cast<std::ctype_base::xdigit>::value
+ };
+
+ inline int mylog2(umaskex_t i)
+ {
+ return "\0\0\1\0\2\0\0\0\3"[i & 0xf]
+ + "\0\4\5\0\6\0\0\0\7"[(i & 0xf0) >> 04]
+ + "\0\10\11\0\12\0\0\0\13"[(i & 0xf00) >> 010];
+ }
+ #endif
+
+ // convenient constant for the extra masks
+ umaskex_t const non_std_ctype_masks = non_std_ctype_underscore | non_std_ctype_blank | non_std_ctype_newline;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // cpp_regex_traits_base
+ // BUGBUG this should be replaced with a regex facet that lets you query for
+ // an array of underscore characters and an array of line separator characters.
+ template<typename Char, std::size_t SizeOfChar = sizeof(Char)>
+ struct cpp_regex_traits_base
+ {
+ protected:
+ void imbue(std::locale const &)
+ {
+ }
+
+ static bool is(std::ctype<Char> const &ct, Char ch, umaskex_t mask)
+ {
+ #ifndef BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
+
+ if(ct.is((std::ctype_base::mask)(umask_t)mask, ch))
+ {
+ return true;
+ }
+
+ #else
+
+ umaskex_t tmp = mask & ~non_std_ctype_masks;
+ for(umaskex_t i; 0 != (i = (tmp & (~tmp+1))); tmp &= ~i)
+ {
+ std::ctype_base::mask m = (std::ctype_base::mask)(umask_t)std_masks[mylog2(i)];
+ if(ct.is(m, ch))
+ {
+ return true;
+ }
+ }
+
+ #endif
+
+ return ((mask & non_std_ctype_blank) && cpp_regex_traits_base::is_blank(ch))
+ || ((mask & non_std_ctype_underscore) && cpp_regex_traits_base::is_underscore(ch))
+ || ((mask & non_std_ctype_newline) && cpp_regex_traits_base::is_newline(ch));
+ }
+
+ private:
+ static bool is_blank(Char ch)
+ {
+ BOOST_MPL_ASSERT_RELATION('\t', ==, L'\t');
+ BOOST_MPL_ASSERT_RELATION(' ', ==, L' ');
+ return L' ' == ch || L'\t' == ch;
+ }
+
+ static bool is_underscore(Char ch)
+ {
+ BOOST_MPL_ASSERT_RELATION('_', ==, L'_');
+ return L'_' == ch;
+ }
+
+ static bool is_newline(Char ch)
+ {
+ BOOST_MPL_ASSERT_RELATION('\r', ==, L'\r');
+ BOOST_MPL_ASSERT_RELATION('\n', ==, L'\n');
+ BOOST_MPL_ASSERT_RELATION('\f', ==, L'\f');
+ return L'\r' == ch || L'\n' == ch || L'\f' == ch
+ || (1 < SizeOfChar && (0x2028u == ch || 0x2029u == ch || 0x85u == ch));
+ }
+ };
+
+ #ifndef BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
+
+ template<typename Char>
+ struct cpp_regex_traits_base<Char, 1>
+ {
+ protected:
+ void imbue(std::locale const &loc)
+ {
+ int i = 0;
+ Char allchars[UCHAR_MAX + 1];
+ for(i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
+ {
+ allchars[i] = static_cast<Char>(i);
+ }
+
+ std::ctype<Char> const &ct = BOOST_USE_FACET(std::ctype<Char>, loc);
+ std::ctype_base::mask tmp[UCHAR_MAX + 1];
+ ct.is(allchars, allchars + UCHAR_MAX + 1, tmp);
+ for(i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
+ {
+ this->masks_[i] = static_cast<umask_t>(tmp[i]);
+ BOOST_ASSERT(0 == (this->masks_[i] & non_std_ctype_masks));
+ }
+
+ this->masks_[static_cast<unsigned char>('_')] |= non_std_ctype_underscore;
+ this->masks_[static_cast<unsigned char>(' ')] |= non_std_ctype_blank;
+ this->masks_[static_cast<unsigned char>('\t')] |= non_std_ctype_blank;
+ this->masks_[static_cast<unsigned char>('\n')] |= non_std_ctype_newline;
+ this->masks_[static_cast<unsigned char>('\r')] |= non_std_ctype_newline;
+ this->masks_[static_cast<unsigned char>('\f')] |= non_std_ctype_newline;
+ }
+
+ bool is(std::ctype<Char> const &, Char ch, umaskex_t mask) const
+ {
+ return 0 != (this->masks_[static_cast<unsigned char>(ch)] & mask);
+ }
+
+ private:
+ umaskex_t masks_[UCHAR_MAX + 1];
+ };
+
+ #endif
+
+} // namespace detail
+
+
+///////////////////////////////////////////////////////////////////////////////
+// cpp_regex_traits
+//
+/// \brief Encapsaulates a std::locale for use by the
+/// basic_regex\<\> class template.
+template<typename Char>
+struct cpp_regex_traits
+ : detail::cpp_regex_traits_base<Char>
+{
+ typedef Char char_type;
+ typedef std::basic_string<char_type> string_type;
+ typedef std::locale locale_type;
+ typedef detail::umaskex_t char_class_type;
+ typedef regex_traits_version_2_tag version_tag;
+ typedef detail::cpp_regex_traits_base<Char> base_type;
+
+ /// Initialize a cpp_regex_traits object to use the specified std::locale,
+ /// or the global std::locale if none is specified.
+ ///
+ cpp_regex_traits(locale_type const &loc = locale_type())
+ : base_type()
+ , loc_()
+ {
+ this->imbue(loc);
+ }
+
+ /// Checks two cpp_regex_traits objects for equality
+ ///
+ /// \return this->getloc() == that.getloc().
+ bool operator ==(cpp_regex_traits<char_type> const &that) const
+ {
+ return this->loc_ == that.loc_;
+ }
+
+ /// Checks two cpp_regex_traits objects for inequality
+ ///
+ /// \return this->getloc() != that.getloc().
+ bool operator !=(cpp_regex_traits<char_type> const &that) const
+ {
+ return this->loc_ != that.loc_;
+ }
+
+ /// Convert a char to a Char
+ ///
+ /// \param ch The source character.
+ /// \return std::use_facet\<std::ctype\<char_type\> \>(this->getloc()).widen(ch).
+ char_type widen(char ch) const
+ {
+ return this->ctype_->widen(ch);
+ }
+
+ /// Returns a hash value for a Char in the range [0, UCHAR_MAX]
+ ///
+ /// \param ch The source character.
+ /// \return a value between 0 and UCHAR_MAX, inclusive.
+ static unsigned char hash(char_type ch)
+ {
+ return static_cast<unsigned char>(std::char_traits<Char>::to_int_type(ch));
+ }
+
+ /// No-op
+ ///
+ /// \param ch The source character.
+ /// \return ch
+ static char_type translate(char_type ch)
+ {
+ return ch;
+ }
+
+ /// Converts a character to lower-case using the internally-stored std::locale.
+ ///
+ /// \param ch The source character.
+ /// \return std::tolower(ch, this->getloc()).
+ char_type translate_nocase(char_type ch) const
+ {
+ return this->ctype_->tolower(ch);
+ }
+
+ /// Converts a character to lower-case using the internally-stored std::locale.
+ ///
+ /// \param ch The source character.
+ /// \return std::tolower(ch, this->getloc()).
+ char_type tolower(char_type ch) const
+ {
+ return this->ctype_->tolower(ch);
+ }
+
+ /// Converts a character to upper-case using the internally-stored std::locale.
+ ///
+ /// \param ch The source character.
+ /// \return std::toupper(ch, this->getloc()).
+ char_type toupper(char_type ch) const
+ {
+ return this->ctype_->toupper(ch);
+ }
+
+ /// Returns a string_type containing all the characters that compare equal
+ /// disregrarding case to the one passed in. This function can only be called
+ /// if has_fold_case\<cpp_regex_traits\<Char\> \>::value is true.
+ ///
+ /// \param ch The source character.
+ /// \return string_type containing all chars which are equal to ch when disregarding
+ /// case
+ string_type fold_case(char_type ch) const
+ {
+ BOOST_MPL_ASSERT((is_same<char_type, char>));
+ char_type ntcs[] = {
+ this->ctype_->tolower(ch)
+ , this->ctype_->toupper(ch)
+ , 0
+ };
+ if(ntcs[1] == ntcs[0])
+ ntcs[1] = 0;
+ return string_type(ntcs);
+ }
+
+ /// Checks to see if a character is within a character range.
+ ///
+ /// \param first The bottom of the range, inclusive.
+ /// \param last The top of the range, inclusive.
+ /// \param ch The source character.
+ /// \return first <= ch && ch <= last.
+ static bool in_range(char_type first, char_type last, char_type ch)
+ {
+ return first <= ch && ch <= last;
+ }
+
+ /// Checks to see if a character is within a character range, irregardless of case.
+ ///
+ /// \param first The bottom of the range, inclusive.
+ /// \param last The top of the range, inclusive.
+ /// \param ch The source character.
+ /// \return in_range(first, last, ch) || in_range(first, last, tolower(ch, this->getloc())) ||
+ /// in_range(first, last, toupper(ch, this->getloc()))
+ /// \attention The default implementation doesn't do proper Unicode
+ /// case folding, but this is the best we can do with the standard
+ /// ctype facet.
+ bool in_range_nocase(char_type first, char_type last, char_type ch) const
+ {
+ // NOTE: this default implementation doesn't do proper Unicode
+ // case folding, but this is the best we can do with the standard
+ // std::ctype facet.
+ return this->in_range(first, last, ch)
+ || this->in_range(first, last, this->ctype_->toupper(ch))
+ || this->in_range(first, last, this->ctype_->tolower(ch));
+ }
+
+ /// INTERNAL ONLY
+ //string_type transform(char_type const *begin, char_type const *end) const
+ //{
+ // return this->collate_->transform(begin, end);
+ //}
+
+ /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
+ /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
+ /// then v.transform(G1, G2) \< v.transform(H1, H2).
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ string_type transform(FwdIter begin, FwdIter end) const
+ {
+ //string_type str(begin, end);
+ //return this->transform(str.data(), str.data() + str.size());
+
+ BOOST_ASSERT(false);
+ return string_type();
+ }
+
+ /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
+ /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
+ /// when character case is not considered then
+ /// v.transform_primary(G1, G2) \< v.transform_primary(H1, H2).
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ string_type transform_primary(FwdIter begin, FwdIter end) const
+ {
+ BOOST_ASSERT(false); // TODO implement me
+ return string_type();
+ }
+
+ /// Returns a sequence of characters that represents the collating element
+ /// consisting of the character sequence designated by the iterator range [F1, F2).
+ /// Returns an empty string if the character sequence is not a valid collating element.
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ string_type lookup_collatename(FwdIter begin, FwdIter end) const
+ {
+ BOOST_ASSERT(false); // TODO implement me
+ return string_type();
+ }
+
+ /// For the character class name represented by the specified character sequence,
+ /// return the corresponding bitmask representation.
+ ///
+ /// \param begin A forward iterator to the start of the character sequence representing
+ /// the name of the character class.
+ /// \param end The end of the character sequence.
+ /// \param icase Specifies whether the returned bitmask should represent the case-insensitive
+ /// version of the character class.
+ /// \return A bitmask representing the character class.
+ template<typename FwdIter>
+ char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase) const
+ {
+ static detail::umaskex_t const icase_masks =
+ detail::std_ctype_lower | detail::std_ctype_upper;
+
+ BOOST_ASSERT(begin != end);
+ char_class_type char_class = this->lookup_classname_impl_(begin, end);
+ if(0 == char_class)
+ {
+ // convert the string to lowercase
+ string_type classname(begin, end);
+ for(typename string_type::size_type i = 0, len = classname.size(); i < len; ++i)
+ {
+ classname[i] = this->translate_nocase(classname[i]);
+ }
+ char_class = this->lookup_classname_impl_(classname.begin(), classname.end());
+ }
+ // erase case-sensitivity if icase==true
+ if(icase && 0 != (char_class & icase_masks))
+ {
+ char_class |= icase_masks;
+ }
+ return char_class;
+ }
+
+ /// Tests a character against a character class bitmask.
+ ///
+ /// \param ch The character to test.
+ /// \param mask The character class bitmask against which to test.
+ /// \pre mask is a bitmask returned by lookup_classname, or is several such masks bit-or'ed
+ /// together.
+ /// \return true if the character is a member of any of the specified character classes, false
+ /// otherwise.
+ bool isctype(char_type ch, char_class_type mask) const
+ {
+ return this->base_type::is(*this->ctype_, ch, mask);
+ }
+
+ /// Convert a digit character into the integer it represents.
+ ///
+ /// \param ch The digit character.
+ /// \param radix The radix to use for the conversion.
+ /// \pre radix is one of 8, 10, or 16.
+ /// \return -1 if ch is not a digit character, the integer value of the character otherwise.
+ /// The conversion is performed by imbueing a std::stringstream with this-\>getloc();
+ /// setting the radix to one of oct, hex or dec; inserting ch into the stream; and
+ /// extracting an int.
+ int value(char_type ch, int radix) const
+ {
+ BOOST_ASSERT(8 == radix || 10 == radix || 16 == radix);
+ int val = -1;
+ std::basic_stringstream<char_type> str;
+ str.imbue(this->getloc());
+ str << (8 == radix ? std::oct : (16 == radix ? std::hex : std::dec));
+ str.put(ch);
+ str >> val;
+ return str.fail() ? -1 : val;
+ }
+
+ /// Imbues *this with loc
+ ///
+ /// \param loc A std::locale.
+ /// \return the previous std::locale used by *this.
+ locale_type imbue(locale_type loc)
+ {
+ locale_type old_loc = this->loc_;
+ this->loc_ = loc;
+ this->ctype_ = &BOOST_USE_FACET(std::ctype<char_type>, this->loc_);
+ //this->collate_ = &BOOST_USE_FACET(std::collate<char_type>, this->loc_);
+ this->base_type::imbue(this->loc_);
+ return old_loc;
+ }
+
+ /// Returns the current std::locale used by *this.
+ ///
+ locale_type getloc() const
+ {
+ return this->loc_;
+ }
+
+private:
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // char_class_pair
+ /// INTERNAL ONLY
+ struct char_class_pair
+ {
+ char_type const *class_name_;
+ char_class_type class_type_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // char_class
+ /// INTERNAL ONLY
+ static char_class_pair const &char_class(std::size_t j)
+ {
+ static char_class_pair const s_char_class_map[] =
+ {
+ { BOOST_XPR_CSTR_(char_type, "alnum"), detail::std_ctype_alnum }
+ , { BOOST_XPR_CSTR_(char_type, "alpha"), detail::std_ctype_alpha }
+ , { BOOST_XPR_CSTR_(char_type, "blank"), detail::non_std_ctype_blank }
+ , { BOOST_XPR_CSTR_(char_type, "cntrl"), detail::std_ctype_cntrl }
+ , { BOOST_XPR_CSTR_(char_type, "d"), detail::std_ctype_digit }
+ , { BOOST_XPR_CSTR_(char_type, "digit"), detail::std_ctype_digit }
+ , { BOOST_XPR_CSTR_(char_type, "graph"), detail::std_ctype_graph }
+ , { BOOST_XPR_CSTR_(char_type, "lower"), detail::std_ctype_lower }
+ , { BOOST_XPR_CSTR_(char_type, "newline"),detail::non_std_ctype_newline }
+ , { BOOST_XPR_CSTR_(char_type, "print"), detail::std_ctype_print }
+ , { BOOST_XPR_CSTR_(char_type, "punct"), detail::std_ctype_punct }
+ , { BOOST_XPR_CSTR_(char_type, "s"), detail::std_ctype_space }
+ , { BOOST_XPR_CSTR_(char_type, "space"), detail::std_ctype_space }
+ , { BOOST_XPR_CSTR_(char_type, "upper"), detail::std_ctype_upper }
+ , { BOOST_XPR_CSTR_(char_type, "w"), detail::std_ctype_alnum | detail::non_std_ctype_underscore }
+ , { BOOST_XPR_CSTR_(char_type, "xdigit"), detail::std_ctype_xdigit }
+ , { 0, 0 }
+ };
+ return s_char_class_map[j];
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // lookup_classname_impl
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ static char_class_type lookup_classname_impl_(FwdIter begin, FwdIter end)
+ {
+ // find the classname
+ typedef cpp_regex_traits<Char> this_t;
+ for(std::size_t j = 0; 0 != this_t::char_class(j).class_name_; ++j)
+ {
+ if(this_t::compare_(this_t::char_class(j).class_name_, begin, end))
+ {
+ return this_t::char_class(j).class_type_;
+ }
+ }
+ return 0;
+ }
+
+ /// INTERNAL ONLY
+ template<typename FwdIter>
+ static bool compare_(char_type const *name, FwdIter begin, FwdIter end)
+ {
+ for(; *name && begin != end; ++name, ++begin)
+ {
+ if(*name != *begin)
+ {
+ return false;
+ }
+ }
+ return !*name && begin == end;
+ }
+
+ locale_type loc_;
+ std::ctype<char_type> const *ctype_;
+ //std::collate<char_type> const *collate_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// cpp_regex_traits<>::hash specializations
+template<>
+inline unsigned char cpp_regex_traits<unsigned char>::hash(unsigned char ch)
+{
+ return ch;
+}
+
+template<>
+inline unsigned char cpp_regex_traits<char>::hash(char ch)
+{
+ return static_cast<unsigned char>(ch);
+}
+
+template<>
+inline unsigned char cpp_regex_traits<signed char>::hash(signed char ch)
+{
+ return static_cast<unsigned char>(ch);
+}
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+template<>
+inline unsigned char cpp_regex_traits<wchar_t>::hash(wchar_t ch)
+{
+ return static_cast<unsigned char>(ch);
+}
+#endif
+
+// Narrow C++ traits has fold_case() member function.
+template<>
+struct has_fold_case<cpp_regex_traits<char> >
+ : mpl::true_
+{
+};
+
+
+}}
+
+#endif
diff --git a/boost/xpressive/traits/detail/c_ctype.hpp b/boost/xpressive/traits/detail/c_ctype.hpp
new file mode 100644
index 0000000000..5ed5d97c78
--- /dev/null
+++ b/boost/xpressive/traits/detail/c_ctype.hpp
@@ -0,0 +1,841 @@
+///////////////////////////////////////////////////////////////////////////////
+// c_ctype.hpp
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_TRAITS_DETAIL_C_CTYPE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_TRAITS_DETAIL_C_CTYPE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <cctype>
+#include <cstring>
+#include <boost/mpl/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+# include <cwchar>
+# include <cwctype>
+#endif
+
+namespace boost { namespace xpressive { namespace detail
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// isnewline
+//
+inline bool isnewline(char ch)
+{
+ switch(ch)
+ {
+ case L'\n': case L'\r': case L'\f':
+ return true;
+ default:
+ return false;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// iswnewline
+//
+inline bool iswnewline(wchar_t ch)
+{
+ switch(ch)
+ {
+ case L'\n': case L'\r': case L'\f': case 0x2028u: case 0x2029u: case 0x85u:
+ return true;
+ default:
+ return false;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// classname_a
+//
+template<typename FwdIter>
+inline std::string classname_a(FwdIter begin, FwdIter end)
+{
+ std::string name(begin, end);
+ for(std::size_t i = 0; i < name.size(); ++i)
+ {
+ using namespace std;
+ name[i] = static_cast<char>(tolower(static_cast<unsigned char>(name[i])));
+ }
+ return name;
+}
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+///////////////////////////////////////////////////////////////////////////////
+// classname_w
+//
+template<typename FwdIter>
+inline std::wstring classname_w(FwdIter begin, FwdIter end)
+{
+ std::wstring name(begin, end);
+ for(std::size_t i = 0; i < name.size(); ++i)
+ {
+ using namespace std;
+ name[i] = towlower(name[i]);
+ }
+ return name;
+}
+#endif
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// char_class_impl
+//
+template<typename Char>
+struct char_class_impl;
+
+
+#if defined(__QNXNTO__)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<char>
+{
+ typedef short char_class_type;
+ BOOST_MPL_ASSERT_RELATION(0x07FF, ==, (_XB|_XA|_XS|_BB|_CN|_DI|_LO|_PU|_SP|_UP|_XD));
+ BOOST_STATIC_CONSTANT(short, char_class_underscore = 0x1000);
+ BOOST_STATIC_CONSTANT(short, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ string const name = classname_a(begin, end);
+ if(name == "alnum") return _DI|_LO|_UP|_XA;
+ if(name == "alpha") return _LO|_UP|_XA;
+ if(name == "blank") return _SP|_XB;
+ if(name == "cntrl") return _BB;
+ if(name == "d") return _DI;
+ if(name == "digit") return _DI;
+ if(name == "graph") return _DI|_LO|_PU|_UP|_XA;
+ if(name == "lower") return icase ? (_LO|_UP) : _LO;
+ if(name == "newline") return char_class_newline;
+ if(name == "print") return _DI|_LO|_PU|_SP|_UP|_XA;
+ if(name == "punct") return _PU;
+ if(name == "s") return _CN|_SP|_XS;
+ if(name == "space") return _CN|_SP|_XS;
+ if(name == "upper") return icase ? (_UP|_LO) : _UP;
+ if(name == "w") return _DI|_LO|_UP|_XA|char_class_underscore;
+ if(name == "xdigit") return _XD;
+ return 0;
+ }
+
+ static bool isctype(char ch, char_class_type mask)
+ {
+ using namespace std;
+ if(0 != (_Getchrtype((unsigned char)ch) & mask))
+ {
+ return true;
+ }
+
+ switch(ch)
+ {
+ case '_': return 0 != (mask & char_class_underscore);
+ case '\n': case '\r': case '\f': return 0 != (mask & char_class_newline);
+ default:;
+ }
+
+ return false;
+ }
+};
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<wchar_t>
+{
+ typedef int char_class_type;
+ //BOOST_STATIC_CONSTANT(int, char_class_alnum = 0x0001);
+ BOOST_STATIC_CONSTANT(int, char_class_alpha = 0x0002);
+ BOOST_STATIC_CONSTANT(int, char_class_blank = 0x0004);
+ BOOST_STATIC_CONSTANT(int, char_class_cntrl = 0x0008);
+ BOOST_STATIC_CONSTANT(int, char_class_digit = 0x0010);
+ //BOOST_STATIC_CONSTANT(int, char_class_graph = 0x0020);
+ BOOST_STATIC_CONSTANT(int, char_class_lower = 0x0040);
+ //BOOST_STATIC_CONSTANT(int, char_class_print = 0x0080);
+ BOOST_STATIC_CONSTANT(int, char_class_punct = 0x0100);
+ BOOST_STATIC_CONSTANT(int, char_class_space = 0x0200);
+ BOOST_STATIC_CONSTANT(int, char_class_upper = 0x0400);
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x0800);
+ BOOST_STATIC_CONSTANT(int, char_class_xdigit = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ wstring const name = classname_w(begin, end);
+ if(name == L"alnum") return char_class_alpha|char_class_digit;
+ if(name == L"alpha") return char_class_alpha;
+ if(name == L"blank") return char_class_blank;
+ if(name == L"cntrl") return char_class_cntrl;
+ if(name == L"d") return char_class_digit;
+ if(name == L"digit") return char_class_digit;
+ if(name == L"graph") return char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"lower") return icase ? (char_class_lower|char_class_upper) : char_class_lower;
+ if(name == L"newline") return char_class_newline;
+ if(name == L"print") return char_class_blank|char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"punct") return char_class_punct;
+ if(name == L"s") return char_class_space;
+ if(name == L"space") return char_class_space;
+ if(name == L"upper") return icase ? (char_class_upper|char_class_lower) : char_class_upper;
+ if(name == L"w") return char_class_alpha|char_class_digit|char_class_underscore;
+ if(name == L"xdigit") return char_class_xdigit;
+ return 0;
+ }
+
+ static bool isctype(wchar_t ch, char_class_type mask)
+ {
+ using namespace std;
+ return ((char_class_alpha & mask) && iswalpha(ch))
+ || ((char_class_blank & mask) && (L' ' == ch || L'\t' == ch)) // BUGBUG
+ || ((char_class_cntrl & mask) && iswcntrl(ch))
+ || ((char_class_digit & mask) && iswdigit(ch))
+ || ((char_class_lower & mask) && iswlower(ch))
+ || ((char_class_newline & mask) && detail::iswnewline(ch))
+ || ((char_class_punct & mask) && iswpunct(ch))
+ || ((char_class_space & mask) && iswspace(ch))
+ || ((char_class_upper & mask) && iswupper(ch))
+ || ((char_class_underscore & mask) && L'_' == ch)
+ || ((char_class_xdigit & mask) && iswxdigit(ch))
+ ;
+ }
+};
+#endif
+
+
+#elif defined(__MINGW32_VERSION)
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<char>
+{
+ typedef int char_class_type;
+ BOOST_MPL_ASSERT_RELATION(0x81FF, ==, (_ALPHA|_UPPER|_LOWER|_DIGIT|_SPACE|_PUNCT|_CONTROL|_BLANK|_HEX|_LEADBYTE));
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ string const name = classname_a(begin, end);
+ if(name == "alnum") return _ALPHA|_DIGIT;
+ if(name == "alpha") return _ALPHA;
+ if(name == "blank") return _BLANK; // this is ONLY space!!!
+ if(name == "cntrl") return _CONTROL;
+ if(name == "d") return _DIGIT;
+ if(name == "digit") return _DIGIT;
+ if(name == "graph") return _PUNCT|_ALPHA|_DIGIT;
+ if(name == "lower") return icase ? (_LOWER|_UPPER) : _LOWER;
+ if(name == "newline") return char_class_newline;
+ if(name == "print") return _BLANK|_PUNCT|_ALPHA|_DIGIT;
+ if(name == "punct") return _PUNCT;
+ if(name == "s") return _SPACE;
+ if(name == "space") return _SPACE;
+ if(name == "upper") return icase ? (_UPPER|_LOWER) : _UPPER;
+ if(name == "w") return _ALPHA|_DIGIT|char_class_underscore;
+ if(name == "xdigit") return _HEX;
+ return 0;
+ }
+
+ static bool isctype(char ch, char_class_type mask)
+ {
+ using namespace std;
+ if(0 != _isctype(static_cast<unsigned char>(ch), mask))
+ {
+ return true;
+ }
+
+ switch(ch)
+ {
+ case '\t': return 0 != (mask & _BLANK);
+ case '_': return 0 != (mask & char_class_underscore);
+ case '\n': case '\r': case '\f': return 0 != (mask & char_class_newline);
+ default:;
+ }
+
+ return false;
+ }
+};
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<wchar_t>
+{
+ typedef wctype_t char_class_type;
+ BOOST_MPL_ASSERT_RELATION(0x81FF, ==, (_ALPHA|_UPPER|_LOWER|_DIGIT|_SPACE|_PUNCT|_CONTROL|_BLANK|_HEX|_LEADBYTE));
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ wstring const name = classname_w(begin, end);
+ if(name == L"alnum") return _ALPHA|_DIGIT;
+ if(name == L"alpha") return _ALPHA;
+ if(name == L"blank") return _BLANK; // this is ONLY space!!!
+ if(name == L"cntrl") return _CONTROL;
+ if(name == L"d") return _DIGIT;
+ if(name == L"digit") return _DIGIT;
+ if(name == L"graph") return _PUNCT|_ALPHA|_DIGIT;
+ if(name == L"lower") return icase ? (_LOWER|_UPPER) : _LOWER;
+ if(name == L"newline") return char_class_newline;
+ if(name == L"print") return _BLANK|_PUNCT|_ALPHA|_DIGIT;
+ if(name == L"punct") return _PUNCT;
+ if(name == L"s") return _SPACE;
+ if(name == L"space") return _SPACE;
+ if(name == L"upper") return icase ? (_UPPER|_LOWER) : _UPPER;
+ if(name == L"w") return _ALPHA|_DIGIT|char_class_underscore;
+ if(name == L"xdigit") return _HEX;
+ return 0;
+ }
+
+ static bool isctype(wchar_t ch, char_class_type mask)
+ {
+ using namespace std;
+ if(0 != iswctype(ch, mask))
+ {
+ return true;
+ }
+
+ switch(ch)
+ {
+ case L'\t': return 0 != (mask & _BLANK);
+ case L'_': return 0 != (mask & char_class_underscore);
+ case L'\n': case L'\r': case L'\f': case 0x2028u: case 0x2029u: case 0x85u:
+ return 0 != (mask & char_class_newline);
+ default:;
+ }
+
+ return false;
+ }
+};
+#endif
+
+
+#elif defined(__CYGWIN__)
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<char>
+{
+ typedef int char_class_type;
+ BOOST_MPL_ASSERT_RELATION(0377, ==, (_U|_L|_N|_S|_P|_C|_B|_X));
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0400);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 01000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ string const name = classname_a(begin, end);
+ if(name == "alnum") return _U|_L|_N;
+ if(name == "alpha") return _U|_L;
+ if(name == "blank") return _B; // BUGBUG what is this?
+ if(name == "cntrl") return _C;
+ if(name == "d") return _N;
+ if(name == "digit") return _N;
+ if(name == "graph") return _P|_U|_L|_N;
+ if(name == "lower") return icase ? (_L|_U) : _L;
+ if(name == "newline") return char_class_newline;
+ if(name == "print") return _B|_P|_U|_L|_N;
+ if(name == "punct") return _P;
+ if(name == "s") return _S;
+ if(name == "space") return _S;
+ if(name == "upper") return icase ? (_U|_L) : _U;
+ if(name == "w") return _U|_L|_N|char_class_underscore;
+ if(name == "xdigit") return _X;
+ return 0;
+ }
+
+ static bool isctype(char ch, char_class_type mask)
+ {
+ if(0 != static_cast<unsigned char>(((_ctype_+1)[(unsigned)(ch)]) & mask))
+ {
+ return true;
+ }
+
+ switch(ch)
+ {
+ case '_': return 0 != (mask & char_class_underscore);
+ case '\n': case '\r': case '\f': return 0 != (mask & char_class_newline);
+ default:;
+ }
+
+ return false;
+ }
+};
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<wchar_t>
+{
+ typedef int char_class_type;
+ //BOOST_STATIC_CONSTANT(int, char_class_alnum = 0x0001);
+ BOOST_STATIC_CONSTANT(int, char_class_alpha = 0x0002);
+ BOOST_STATIC_CONSTANT(int, char_class_blank = 0x0004);
+ BOOST_STATIC_CONSTANT(int, char_class_cntrl = 0x0008);
+ BOOST_STATIC_CONSTANT(int, char_class_digit = 0x0010);
+ //BOOST_STATIC_CONSTANT(int, char_class_graph = 0x0020);
+ BOOST_STATIC_CONSTANT(int, char_class_lower = 0x0040);
+ //BOOST_STATIC_CONSTANT(int, char_class_print = 0x0080);
+ BOOST_STATIC_CONSTANT(int, char_class_punct = 0x0100);
+ BOOST_STATIC_CONSTANT(int, char_class_space = 0x0200);
+ BOOST_STATIC_CONSTANT(int, char_class_upper = 0x0400);
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x0800);
+ BOOST_STATIC_CONSTANT(int, char_class_xdigit = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ wstring const name = classname_w(begin, end);
+ if(name == L"alnum") return char_class_alpha|char_class_digit;
+ if(name == L"alpha") return char_class_alpha;
+ if(name == L"blank") return char_class_blank;
+ if(name == L"cntrl") return char_class_cntrl;
+ if(name == L"d") return char_class_digit;
+ if(name == L"digit") return char_class_digit;
+ if(name == L"graph") return char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"lower") return icase ? (char_class_lower|char_class_upper) : char_class_lower;
+ if(name == L"newline") return char_class_newline;
+ if(name == L"print") return char_class_blank|char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"punct") return char_class_punct;
+ if(name == L"s") return char_class_space;
+ if(name == L"space") return char_class_space;
+ if(name == L"upper") return icase ? (char_class_upper|char_class_lower) : char_class_upper;
+ if(name == L"w") return char_class_alpha|char_class_digit|char_class_underscore;
+ if(name == L"xdigit") return char_class_xdigit;
+ return 0;
+ }
+
+ static bool isctype(wchar_t ch, char_class_type mask)
+ {
+ using namespace std;
+ return ((char_class_alpha & mask) && iswalpha(ch))
+ || ((char_class_blank & mask) && (L' ' == ch || L'\t' == ch)) // BUGBUG
+ || ((char_class_cntrl & mask) && iswcntrl(ch))
+ || ((char_class_digit & mask) && iswdigit(ch))
+ || ((char_class_lower & mask) && iswlower(ch))
+ || ((char_class_newline & mask) && detail::iswnewline(ch))
+ || ((char_class_punct & mask) && iswpunct(ch))
+ || ((char_class_space & mask) && iswspace(ch))
+ || ((char_class_upper & mask) && iswupper(ch))
+ || ((char_class_underscore & mask) && L'_' == ch)
+ || ((char_class_xdigit & mask) && iswxdigit(ch))
+ ;
+ }
+};
+#endif
+
+
+
+#elif defined(__GLIBC__)
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<char>
+{
+ typedef int char_class_type;
+ BOOST_MPL_ASSERT_RELATION(0xffff, ==, (_ISalnum|_ISalpha|_ISblank|_IScntrl|_ISdigit|_ISgraph|
+ _ISlower|_ISprint|_ISpunct|_ISspace|_ISupper|_ISxdigit|0xffff));
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x00010000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x00020000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ string const name = classname_a(begin, end);
+ if(name == "alnum") return _ISalnum;
+ if(name == "alpha") return _ISalpha;
+ if(name == "blank") return _ISblank;
+ if(name == "cntrl") return _IScntrl;
+ if(name == "d") return _ISdigit;
+ if(name == "digit") return _ISdigit;
+ if(name == "graph") return _ISgraph;
+ if(name == "lower") return icase ? (_ISlower|_ISupper) : _ISlower;
+ if(name == "print") return _ISprint;
+ if(name == "newline") return char_class_newline;
+ if(name == "punct") return _ISpunct;
+ if(name == "s") return _ISspace;
+ if(name == "space") return _ISspace;
+ if(name == "upper") return icase ? (_ISupper|_ISlower) : _ISupper;
+ if(name == "w") return _ISalnum|char_class_underscore;
+ if(name == "xdigit") return _ISxdigit;
+ return 0;
+ }
+
+ static bool isctype(char ch, char_class_type mask)
+ {
+ using namespace std;
+ if(0 != __isctype(static_cast<unsigned char>(ch), mask))
+ {
+ return true;
+ }
+
+ switch(ch)
+ {
+ case '_': return 0 != (mask & char_class_underscore);
+ case '\n': case '\r': case '\f': return 0 != (mask & char_class_newline);
+ default:;
+ }
+
+ return false;
+ }
+};
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<wchar_t>
+{
+ typedef int char_class_type;
+ //BOOST_STATIC_CONSTANT(int, char_class_alnum = 0x0001);
+ BOOST_STATIC_CONSTANT(int, char_class_alpha = 0x0002);
+ BOOST_STATIC_CONSTANT(int, char_class_blank = 0x0004);
+ BOOST_STATIC_CONSTANT(int, char_class_cntrl = 0x0008);
+ BOOST_STATIC_CONSTANT(int, char_class_digit = 0x0010);
+ //BOOST_STATIC_CONSTANT(int, char_class_graph = 0x0020);
+ BOOST_STATIC_CONSTANT(int, char_class_lower = 0x0040);
+ //BOOST_STATIC_CONSTANT(int, char_class_print = 0x0080);
+ BOOST_STATIC_CONSTANT(int, char_class_punct = 0x0100);
+ BOOST_STATIC_CONSTANT(int, char_class_space = 0x0200);
+ BOOST_STATIC_CONSTANT(int, char_class_upper = 0x0400);
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x0800);
+ BOOST_STATIC_CONSTANT(int, char_class_xdigit = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ wstring const name = classname_w(begin, end);
+ if(name == L"alnum") return char_class_alpha|char_class_digit;
+ if(name == L"alpha") return char_class_alpha;
+ if(name == L"blank") return char_class_blank;
+ if(name == L"cntrl") return char_class_cntrl;
+ if(name == L"d") return char_class_digit;
+ if(name == L"digit") return char_class_digit;
+ if(name == L"graph") return char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"lower") return icase ? (char_class_lower|char_class_upper) : char_class_lower;
+ if(name == L"newline") return char_class_newline;
+ if(name == L"print") return char_class_blank|char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"punct") return char_class_punct;
+ if(name == L"s") return char_class_space;
+ if(name == L"space") return char_class_space;
+ if(name == L"upper") return icase ? (char_class_upper|char_class_lower) : char_class_upper;
+ if(name == L"w") return char_class_alpha|char_class_digit|char_class_underscore;
+ if(name == L"xdigit") return char_class_xdigit;
+ return 0;
+ }
+
+ static bool isctype(wchar_t ch, char_class_type mask)
+ {
+ using namespace std;
+ return ((char_class_alpha & mask) && iswalpha(ch))
+ || ((char_class_blank & mask) && (L' ' == ch || L'\t' == ch)) // BUGBUG
+ || ((char_class_cntrl & mask) && iswcntrl(ch))
+ || ((char_class_digit & mask) && iswdigit(ch))
+ || ((char_class_lower & mask) && iswlower(ch))
+ || ((char_class_newline & mask) && detail::iswnewline(ch))
+ || ((char_class_punct & mask) && iswpunct(ch))
+ || ((char_class_space & mask) && iswspace(ch))
+ || ((char_class_upper & mask) && iswupper(ch))
+ || ((char_class_underscore & mask) && L'_' == ch)
+ || ((char_class_xdigit & mask) && iswxdigit(ch))
+ ;
+ }
+};
+#endif
+
+
+
+#elif defined(_CPPLIB_VER) // Dinkumware STL
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<char>
+{
+ typedef int char_class_type;
+ BOOST_MPL_ASSERT_RELATION(0x81FF, ==, (_ALPHA|_UPPER|_LOWER|_DIGIT|_SPACE|_PUNCT|_CONTROL|_BLANK|_HEX|_LEADBYTE));
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ string const name = classname_a(begin, end);
+ if(name == "alnum") return _ALPHA|_DIGIT;
+ if(name == "alpha") return _ALPHA;
+ if(name == "blank") return _BLANK; // this is ONLY space!!!
+ if(name == "cntrl") return _CONTROL;
+ if(name == "d") return _DIGIT;
+ if(name == "digit") return _DIGIT;
+ if(name == "graph") return _PUNCT|_ALPHA|_DIGIT;
+ if(name == "lower") return icase ? (_LOWER|_UPPER) : _LOWER;
+ if(name == "newline") return char_class_newline;
+ if(name == "print") return _BLANK|_PUNCT|_ALPHA|_DIGIT;
+ if(name == "punct") return _PUNCT;
+ if(name == "s") return _SPACE;
+ if(name == "space") return _SPACE;
+ if(name == "upper") return icase ? (_UPPER|_LOWER) : _UPPER;
+ if(name == "w") return _ALPHA|_DIGIT|char_class_underscore;
+ if(name == "xdigit") return _HEX;
+ return 0;
+ }
+
+ static bool isctype(char ch, char_class_type mask)
+ {
+ using namespace std;
+ if(0 != _isctype(static_cast<unsigned char>(ch), mask))
+ {
+ return true;
+ }
+
+ switch(ch)
+ {
+ case '\t': return 0 != (mask & _BLANK);
+ case '_': return 0 != (mask & char_class_underscore);
+ case '\n': case '\r': case '\f': return 0 != (mask & char_class_newline);
+ default:;
+ }
+
+ return false;
+ }
+};
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<wchar_t>
+{
+ typedef wctype_t char_class_type;
+ BOOST_MPL_ASSERT_RELATION(0x81FF, ==, (_ALPHA|_UPPER|_LOWER|_DIGIT|_SPACE|_PUNCT|_CONTROL|_BLANK|_HEX|_LEADBYTE));
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ wstring const name = classname_w(begin, end);
+ if(name == L"alnum") return _ALPHA|_DIGIT;
+ if(name == L"alpha") return _ALPHA;
+ if(name == L"blank") return _BLANK; // this is ONLY space!!!
+ if(name == L"cntrl") return _CONTROL;
+ if(name == L"d") return _DIGIT;
+ if(name == L"digit") return _DIGIT;
+ if(name == L"graph") return _PUNCT|_ALPHA|_DIGIT;
+ if(name == L"lower") return icase ? _LOWER|_UPPER : _LOWER;
+ if(name == L"newline") return char_class_newline;
+ if(name == L"print") return _BLANK|_PUNCT|_ALPHA|_DIGIT;
+ if(name == L"punct") return _PUNCT;
+ if(name == L"s") return _SPACE;
+ if(name == L"space") return _SPACE;
+ if(name == L"upper") return icase ? _UPPER|_LOWER : _UPPER;
+ if(name == L"w") return _ALPHA|_DIGIT|char_class_underscore;
+ if(name == L"xdigit") return _HEX;
+ return 0;
+ }
+
+ static bool isctype(wchar_t ch, char_class_type mask)
+ {
+ using namespace std;
+ if(0 != iswctype(ch, mask))
+ {
+ return true;
+ }
+
+ switch(ch)
+ {
+ case L'\t': return 0 != (mask & _BLANK);
+ case L'_': return 0 != (mask & char_class_underscore);
+ case L'\n': case L'\r': case L'\f': case 0x2028u: case 0x2029u: case 0x85u:
+ return 0 != (mask & char_class_newline);
+ default:;
+ }
+
+ return false;
+ }
+};
+#endif
+
+
+
+#else // unknown, use portable implementation
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<char>
+{
+ typedef int char_class_type;
+ //BOOST_STATIC_CONSTANT(int, char_class_alnum = 0x0001);
+ BOOST_STATIC_CONSTANT(int, char_class_alpha = 0x0002);
+ BOOST_STATIC_CONSTANT(int, char_class_blank = 0x0004);
+ BOOST_STATIC_CONSTANT(int, char_class_cntrl = 0x0008);
+ BOOST_STATIC_CONSTANT(int, char_class_digit = 0x0010);
+ //BOOST_STATIC_CONSTANT(int, char_class_graph = 0x0020);
+ BOOST_STATIC_CONSTANT(int, char_class_lower = 0x0040);
+ //BOOST_STATIC_CONSTANT(int, char_class_print = 0x0080);
+ BOOST_STATIC_CONSTANT(int, char_class_punct = 0x0100);
+ BOOST_STATIC_CONSTANT(int, char_class_space = 0x0200);
+ BOOST_STATIC_CONSTANT(int, char_class_upper = 0x0400);
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x0800);
+ BOOST_STATIC_CONSTANT(int, char_class_xdigit = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ string const name = classname_a(begin, end);
+ if(name == "alnum") return char_class_alpha|char_class_digit;
+ if(name == "alpha") return char_class_alpha;
+ if(name == "blank") return char_class_blank;
+ if(name == "cntrl") return char_class_cntrl;
+ if(name == "d") return char_class_digit;
+ if(name == "digit") return char_class_digit;
+ if(name == "graph") return char_class_punct|char_class_alpha|char_class_digit;
+ if(name == "lower") return icase ? (char_class_lower|char_class_upper) : char_class_lower;
+ if(name == "newline") return char_class_newline;
+ if(name == "print") return char_class_blank|char_class_punct|char_class_alpha|char_class_digit;
+ if(name == "punct") return char_class_punct;
+ if(name == "s") return char_class_space;
+ if(name == "space") return char_class_space;
+ if(name == "upper") return icase ? (char_class_upper|char_class_lower) : char_class_upper;
+ if(name == "w") return char_class_alpha|char_class_digit|char_class_underscore;
+ if(name == "xdigit") return char_class_xdigit;
+ return 0;
+ }
+
+ static bool isctype(char ch, char_class_type mask)
+ {
+ using namespace std;
+ unsigned char uch = static_cast<unsigned char>(ch);
+ return ((char_class_alpha & mask) && isalpha(uch))
+ || ((char_class_blank & mask) && (' ' == ch || '\t' == ch)) // BUGBUG
+ || ((char_class_cntrl & mask) && iscntrl(uch))
+ || ((char_class_digit & mask) && isdigit(uch))
+ || ((char_class_lower & mask) && islower(uch))
+ || ((char_class_newline & mask) && detail::isnewline(ch))
+ || ((char_class_punct & mask) && ispunct(uch))
+ || ((char_class_space & mask) && isspace(uch))
+ || ((char_class_upper & mask) && isupper(uch))
+ || ((char_class_underscore & mask) && '_' == ch)
+ || ((char_class_xdigit & mask) && isxdigit(uch))
+ ;
+ }
+};
+
+#ifndef BOOST_XPRESSIVE_NO_WREGEX
+///////////////////////////////////////////////////////////////////////////////
+//
+template<>
+struct char_class_impl<wchar_t>
+{
+ typedef int char_class_type;
+ //BOOST_STATIC_CONSTANT(int, char_class_alnum = 0x0001);
+ BOOST_STATIC_CONSTANT(int, char_class_alpha = 0x0002);
+ BOOST_STATIC_CONSTANT(int, char_class_blank = 0x0004);
+ BOOST_STATIC_CONSTANT(int, char_class_cntrl = 0x0008);
+ BOOST_STATIC_CONSTANT(int, char_class_digit = 0x0010);
+ //BOOST_STATIC_CONSTANT(int, char_class_graph = 0x0020);
+ BOOST_STATIC_CONSTANT(int, char_class_lower = 0x0040);
+ //BOOST_STATIC_CONSTANT(int, char_class_print = 0x0080);
+ BOOST_STATIC_CONSTANT(int, char_class_punct = 0x0100);
+ BOOST_STATIC_CONSTANT(int, char_class_space = 0x0200);
+ BOOST_STATIC_CONSTANT(int, char_class_upper = 0x0400);
+ BOOST_STATIC_CONSTANT(int, char_class_underscore = 0x0800);
+ BOOST_STATIC_CONSTANT(int, char_class_xdigit = 0x1000);
+ BOOST_STATIC_CONSTANT(int, char_class_newline = 0x2000);
+
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ using namespace std;
+ wstring const name = classname_w(begin, end);
+ if(name == L"alnum") return char_class_alpha|char_class_digit;
+ if(name == L"alpha") return char_class_alpha;
+ if(name == L"blank") return char_class_blank;
+ if(name == L"cntrl") return char_class_cntrl;
+ if(name == L"d") return char_class_digit;
+ if(name == L"digit") return char_class_digit;
+ if(name == L"graph") return char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"newline") return char_class_newline;
+ if(name == L"lower") return icase ? (char_class_lower|char_class_upper) : char_class_lower;
+ if(name == L"print") return char_class_blank|char_class_punct|char_class_alpha|char_class_digit;
+ if(name == L"punct") return char_class_punct;
+ if(name == L"s") return char_class_space;
+ if(name == L"space") return char_class_space;
+ if(name == L"upper") return icase ? (char_class_upper|char_class_lower) : char_class_upper;
+ if(name == L"w") return char_class_alpha|char_class_digit|char_class_underscore;
+ if(name == L"xdigit") return char_class_xdigit;
+ return 0;
+ }
+
+ static bool isctype(wchar_t ch, char_class_type mask)
+ {
+ using namespace std;
+ return ((char_class_alpha & mask) && iswalpha(ch))
+ || ((char_class_blank & mask) && (L' ' == ch || L'\t' == ch)) // BUGBUG
+ || ((char_class_cntrl & mask) && iswcntrl(ch))
+ || ((char_class_digit & mask) && iswdigit(ch))
+ || ((char_class_lower & mask) && iswlower(ch))
+ || ((char_class_newline & mask) && detail::iswnewline(ch))
+ || ((char_class_punct & mask) && iswpunct(ch))
+ || ((char_class_space & mask) && iswspace(ch))
+ || ((char_class_upper & mask) && iswupper(ch))
+ || ((char_class_underscore & mask) && L'_' == ch)
+ || ((char_class_xdigit & mask) && iswxdigit(ch))
+ ;
+ }
+};
+#endif
+
+
+#endif
+
+
+}}} // namespace boost::xpressive::detail
+
+#endif
diff --git a/boost/xpressive/traits/null_regex_traits.hpp b/boost/xpressive/traits/null_regex_traits.hpp
new file mode 100644
index 0000000000..6892e88206
--- /dev/null
+++ b/boost/xpressive/traits/null_regex_traits.hpp
@@ -0,0 +1,231 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file null_regex_traits.hpp
+/// Contains the definition of the null_regex_traits\<\> template, which is a
+/// stub regex traits implementation that can be used by static and dynamic
+/// regexes for searching non-character data.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_TRAITS_NULL_REGEX_TRAITS_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_TRAITS_NULL_REGEX_TRAITS_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <vector>
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+#include <boost/xpressive/detail/utility/never_true.hpp>
+#include <boost/xpressive/detail/utility/ignore_unused.hpp>
+
+namespace boost { namespace xpressive
+{
+
+namespace detail
+{
+ struct not_a_locale {};
+}
+
+struct regex_traits_version_1_tag;
+
+///////////////////////////////////////////////////////////////////////////////
+// null_regex_traits
+//
+/// \brief stub regex_traits for non-char data
+///
+template<typename Elem>
+struct null_regex_traits
+{
+ typedef Elem char_type;
+ typedef std::vector<char_type> string_type;
+ typedef detail::not_a_locale locale_type;
+ typedef int char_class_type;
+ typedef regex_traits_version_1_tag version_tag;
+
+ /// Initialize a null_regex_traits object.
+ ///
+ null_regex_traits(locale_type = locale_type())
+ {
+ }
+
+ /// Checks two null_regex_traits objects for equality
+ ///
+ /// \return true.
+ bool operator ==(null_regex_traits<char_type> const &that) const
+ {
+ detail::ignore_unused(that);
+ return true;
+ }
+
+ /// Checks two null_regex_traits objects for inequality
+ ///
+ /// \return false.
+ bool operator !=(null_regex_traits<char_type> const &that) const
+ {
+ detail::ignore_unused(that);
+ return false;
+ }
+
+ /// Convert a char to a Elem
+ ///
+ /// \param ch The source character.
+ /// \return Elem(ch).
+ char_type widen(char ch) const
+ {
+ return char_type(ch);
+ }
+
+ /// Returns a hash value for a Elem in the range [0, UCHAR_MAX]
+ ///
+ /// \param ch The source character.
+ /// \return a value between 0 and UCHAR_MAX, inclusive.
+ static unsigned char hash(char_type ch)
+ {
+ return static_cast<unsigned char>(ch);
+ }
+
+ /// No-op
+ ///
+ /// \param ch The source character.
+ /// \return ch
+ static char_type translate(char_type ch)
+ {
+ return ch;
+ }
+
+ /// No-op
+ ///
+ /// \param ch The source character.
+ /// \return ch
+ static char_type translate_nocase(char_type ch)
+ {
+ return ch;
+ }
+
+ /// Checks to see if a character is within a character range.
+ ///
+ /// \param first The bottom of the range, inclusive.
+ /// \param last The top of the range, inclusive.
+ /// \param ch The source character.
+ /// \return first <= ch && ch <= last.
+ static bool in_range(char_type first, char_type last, char_type ch)
+ {
+ return first <= ch && ch <= last;
+ }
+
+ /// Checks to see if a character is within a character range.
+ ///
+ /// \param first The bottom of the range, inclusive.
+ /// \param last The top of the range, inclusive.
+ /// \param ch The source character.
+ /// \return first <= ch && ch <= last.
+ /// \attention Since the null_regex_traits does not do case-folding,
+ /// this function is equivalent to in_range().
+ static bool in_range_nocase(char_type first, char_type last, char_type ch)
+ {
+ return first <= ch && ch <= last;
+ }
+
+ /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
+ /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
+ /// then v.transform(G1, G2) < v.transform(H1, H2).
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ static string_type transform(FwdIter begin, FwdIter end)
+ {
+ return string_type(begin, end);
+ }
+
+ /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
+ /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
+ /// when character case is not considered then
+ /// v.transform_primary(G1, G2) < v.transform_primary(H1, H2).
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ static string_type transform_primary(FwdIter begin, FwdIter end)
+ {
+ return string_type(begin, end);
+ }
+
+ /// Returns a sequence of characters that represents the collating element
+ /// consisting of the character sequence designated by the iterator range [F1, F2).
+ /// Returns an empty string if the character sequence is not a valid collating element.
+ ///
+ /// \attention Not currently used
+ template<typename FwdIter>
+ static string_type lookup_collatename(FwdIter begin, FwdIter end)
+ {
+ detail::ignore_unused(begin);
+ detail::ignore_unused(end);
+ return string_type();
+ }
+
+ /// The null_regex_traits does not have character classifications, so lookup_classname()
+ /// is unused.
+ ///
+ /// \param begin not used
+ /// \param end not used
+ /// \param icase not used
+ /// \return static_cast\<char_class_type\>(0)
+ template<typename FwdIter>
+ static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase)
+ {
+ detail::ignore_unused(begin);
+ detail::ignore_unused(end);
+ detail::ignore_unused(icase);
+ return 0;
+ }
+
+ /// The null_regex_traits does not have character classifications, so isctype()
+ /// is unused.
+ ///
+ /// \param ch not used
+ /// \param mask not used
+ /// \return false
+ static bool isctype(char_type ch, char_class_type mask)
+ {
+ detail::ignore_unused(ch);
+ detail::ignore_unused(mask);
+ return false;
+ }
+
+ /// The null_regex_traits recognizes no elements as digits, so value() is unused.
+ ///
+ /// \param ch not used
+ /// \param radix not used
+ /// \return -1
+ static int value(char_type ch, int radix)
+ {
+ detail::ignore_unused(ch);
+ detail::ignore_unused(radix);
+ return -1;
+ }
+
+ /// Not used
+ ///
+ /// \param loc not used
+ /// \return loc
+ static locale_type imbue(locale_type loc)
+ {
+ return loc;
+ }
+
+ /// Returns locale_type().
+ ///
+ /// \return locale_type()
+ static locale_type getloc()
+ {
+ return locale_type();
+ }
+};
+
+}}
+
+#endif
diff --git a/boost/xpressive/xpressive.hpp b/boost/xpressive/xpressive.hpp
new file mode 100644
index 0000000000..03021bed5b
--- /dev/null
+++ b/boost/xpressive/xpressive.hpp
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file xpressive.hpp
+/// Includes all of xpressive including support for both static and
+/// dynamic regular expressions.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/xpressive_static.hpp>
+#include <boost/xpressive/xpressive_dynamic.hpp>
+
+#endif
diff --git a/boost/xpressive/xpressive_dynamic.hpp b/boost/xpressive/xpressive_dynamic.hpp
new file mode 100644
index 0000000000..6f0e4d0bad
--- /dev/null
+++ b/boost/xpressive/xpressive_dynamic.hpp
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file xpressive_dynamic.hpp
+/// Includes everything you need to write and use dynamic regular expressions.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_DYNAMIC_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_DYNAMIC_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/xpressive/regex_compiler.hpp>
+#include <boost/xpressive/basic_regex.hpp>
+#include <boost/xpressive/sub_match.hpp>
+#include <boost/xpressive/match_results.hpp>
+#include <boost/xpressive/regex_algorithms.hpp>
+#include <boost/xpressive/regex_iterator.hpp>
+#include <boost/xpressive/regex_token_iterator.hpp>
+
+#endif
diff --git a/boost/xpressive/xpressive_fwd.hpp b/boost/xpressive/xpressive_fwd.hpp
new file mode 100644
index 0000000000..00c8c61506
--- /dev/null
+++ b/boost/xpressive/xpressive_fwd.hpp
@@ -0,0 +1,243 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file xpressive_fwd.hpp
+/// Forward declarations for all of xpressive's public data types.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_XPRESSIVE_FWD_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_XPRESSIVE_FWD_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <string>
+#include <boost/config.hpp>
+#include <boost/version.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+#if BOOST_VERSION >= 103500
+# define BOOST_PROTO_FUSION_V2
+#endif
+
+#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+# error Sorry, xpressive requires a compiler that supports partial template specialization.
+#endif
+
+#if defined(BOOST_NO_STD_LOCALE) & !defined(BOOST_XPRESSIVE_USE_C_TRAITS)
+# define BOOST_XPRESSIVE_USE_C_TRAITS
+#endif
+
+#if defined(BOOST_NO_CWCHAR) | defined(BOOST_NO_CWCTYPE) | defined(BOOST_NO_STD_WSTRING)
+# ifndef BOOST_XPRESSIVE_NO_WREGEX
+# define BOOST_XPRESSIVE_NO_WREGEX
+# endif
+#endif
+
+// Stack protection under MS Windows
+// Config logic taken from boost/regex/config.hpp
+#ifndef BOOST_XPRESSIVE_HAS_MS_STACK_GUARD
+# if (defined(_WIN32) || defined(_WIN64) || defined(_WINCE)) \
+ && !defined(__GNUC__) \
+ && !(defined(__BORLANDC__) && (__BORLANDC__ >= 0x600)) \
+ && !(defined(__MWERKS__) && (__MWERKS__ <= 0x3003))
+# define BOOST_XPRESSIVE_HAS_MS_STACK_GUARD 1
+# else
+# define BOOST_XPRESSIVE_HAS_MS_STACK_GUARD 0
+# endif
+#endif
+
+#include <boost/proto/proto_fwd.hpp>
+
+namespace boost { namespace xpressive
+{
+
+ template<typename Char>
+ struct cpp_regex_traits;
+
+ template<typename Char>
+ struct c_regex_traits;
+
+ template<typename Elem>
+ struct null_regex_traits;
+
+ namespace detail
+ {
+ template<typename Char>
+ struct default_regex_traits
+ {
+ #ifdef BOOST_XPRESSIVE_USE_C_TRAITS
+ typedef c_regex_traits<Char> type;
+ #else
+ typedef cpp_regex_traits<Char> type;
+ #endif
+ };
+
+ struct mark_placeholder;
+ typedef proto::expr<proto::tag::terminal, proto::term<mark_placeholder>, 0> basic_mark_tag;
+
+ struct regex_domain;
+
+ } // namespace detail
+
+ struct mark_tag;
+
+ typedef void const *regex_id_type;
+
+ struct regex_error;
+
+ struct regex_traits_version_1_tag;
+
+ struct regex_traits_version_2_tag;
+
+ // DEPRECATED
+ /// INTERNAL ONLY
+ ///
+ struct regex_traits_version_1_case_fold_tag;
+
+ template<typename Trait>
+ struct has_fold_case;
+
+ template<typename BidiIter>
+ struct basic_regex;
+
+ template<typename BidiIter>
+ struct match_results;
+
+ template<typename BidiIter>
+ struct regex_iterator;
+
+ template<typename BidiIter>
+ struct regex_token_iterator;
+
+ template<typename BidiIter>
+ struct regex_id_filter_predicate;
+
+ template<typename BidiIter>
+ struct sub_match;
+
+ template<typename RegexTraits>
+ struct compiler_traits;
+
+ template<typename Char, typename Impl = typename detail::default_regex_traits<Char>::type>
+ struct regex_traits;
+
+ template
+ <
+ typename BidiIter
+ , typename RegexTraits = regex_traits<typename iterator_value<BidiIter>::type>
+ , typename CompilerTraits = compiler_traits<RegexTraits>
+ >
+ struct regex_compiler;
+
+ template<typename T>
+ struct value;
+
+ template<typename T>
+ struct reference;
+
+ template<typename T>
+ struct local;
+
+ template<typename T, int I = 0, typename Dummy = proto::is_proto_expr>
+ struct placeholder;
+
+ namespace op
+ {
+ struct at;
+ struct push;
+ struct push_back;
+ struct push_front;
+ struct pop;
+ struct pop_back;
+ struct pop_front;
+ struct front;
+ struct back;
+ struct top;
+ struct first;
+ struct second;
+ struct matched;
+ struct length;
+ struct str;
+ struct insert;
+ struct make_pair;
+ template<typename T>
+ struct as;
+ template<typename T>
+ struct static_cast_;
+ template<typename T>
+ struct dynamic_cast_;
+ template<typename T>
+ struct const_cast_;
+ template<typename T>
+ struct construct;
+ template<typename Except>
+ struct throw_;
+ struct unwrap_reference;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Common typedefs
+ //
+ typedef basic_regex<std::string::const_iterator> sregex;
+ typedef basic_regex<char const *> cregex;
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ typedef basic_regex<std::wstring::const_iterator> wsregex;
+ typedef basic_regex<wchar_t const *> wcregex;
+ #endif
+
+ typedef sub_match<std::string::const_iterator> ssub_match;
+ typedef sub_match<char const *> csub_match;
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ typedef sub_match<std::wstring::const_iterator> wssub_match;
+ typedef sub_match<wchar_t const *> wcsub_match;
+ #endif
+
+ typedef regex_compiler<std::string::const_iterator> sregex_compiler;
+ typedef regex_compiler<char const *> cregex_compiler;
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ typedef regex_compiler<std::wstring::const_iterator> wsregex_compiler;
+ typedef regex_compiler<wchar_t const *> wcregex_compiler;
+ #endif
+
+ typedef regex_iterator<std::string::const_iterator> sregex_iterator;
+ typedef regex_iterator<char const *> cregex_iterator;
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ typedef regex_iterator<std::wstring::const_iterator> wsregex_iterator;
+ typedef regex_iterator<wchar_t const *> wcregex_iterator;
+ #endif
+
+ typedef regex_token_iterator<std::string::const_iterator> sregex_token_iterator;
+ typedef regex_token_iterator<char const *> cregex_token_iterator;
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ typedef regex_token_iterator<std::wstring::const_iterator> wsregex_token_iterator;
+ typedef regex_token_iterator<wchar_t const *> wcregex_token_iterator;
+ #endif
+
+ typedef match_results<std::string::const_iterator> smatch;
+ typedef match_results<char const *> cmatch;
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ typedef match_results<std::wstring::const_iterator> wsmatch;
+ typedef match_results<wchar_t const *> wcmatch;
+ #endif
+
+ typedef regex_id_filter_predicate<std::string::const_iterator> sregex_id_filter_predicate;
+ typedef regex_id_filter_predicate<char const *> cregex_id_filter_predicate;
+
+ #ifndef BOOST_XPRESSIVE_NO_WREGEX
+ typedef regex_id_filter_predicate<std::wstring::const_iterator> wsregex_id_filter_predicate;
+ typedef regex_id_filter_predicate<wchar_t const *> wcregex_id_filter_predicate;
+ #endif
+
+}} // namespace boost::xpressive
+
+#endif
diff --git a/boost/xpressive/xpressive_static.hpp b/boost/xpressive/xpressive_static.hpp
new file mode 100644
index 0000000000..e7695dfd55
--- /dev/null
+++ b/boost/xpressive/xpressive_static.hpp
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file xpressive_static.hpp
+/// Includes everything you need to write static regular expressions and use
+/// them.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_STATIC_HPP_EAN_10_04_2005
+#define BOOST_XPRESSIVE_STATIC_HPP_EAN_10_04_2005
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+// inline aggressively
+# pragma inline_recursion(on) // turn on inline recursion
+# pragma inline_depth(255) // max inline depth
+#endif
+
+#include <boost/xpressive/regex_primitives.hpp>
+#include <boost/xpressive/basic_regex.hpp>
+#include <boost/xpressive/sub_match.hpp>
+#include <boost/xpressive/match_results.hpp>
+#include <boost/xpressive/regex_algorithms.hpp>
+#include <boost/xpressive/regex_iterator.hpp>
+#include <boost/xpressive/regex_token_iterator.hpp>
+
+#endif
diff --git a/boost/xpressive/xpressive_typeof.hpp b/boost/xpressive/xpressive_typeof.hpp
new file mode 100644
index 0000000000..0be12986b9
--- /dev/null
+++ b/boost/xpressive/xpressive_typeof.hpp
@@ -0,0 +1,150 @@
+///////////////////////////////////////////////////////////////////////////////
+/// \file xpressive_typeof.hpp
+/// Type registrations so that xpressive can be used with the Boost.Typeof library.
+//
+// Copyright 2008 Eric Niebler. 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)
+
+#ifndef BOOST_XPRESSIVE_XPRESSIVE_TYPEOF_H
+#define BOOST_XPRESSIVE_XPRESSIVE_TYPEOF_H
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/typeof/typeof.hpp>
+#ifndef BOOST_NO_STD_LOCALE
+# include <boost/typeof/std/locale.hpp>
+#endif
+#include <boost/proto/proto_typeof.hpp>
+#include <boost/xpressive/detail/detail_fwd.hpp>
+
+#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::mpl::bool_, (bool))
+
+///////////////////////////////////////////////////////////////////////////////
+// Misc.
+//
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::set_initializer)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::keeper_tag)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::modifier_tag)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::lookahead_tag)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::lookbehind_tag)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::check_tag)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::mark_tag)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::word_begin)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::word_end)
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::generic_quant_tag, (unsigned int)(unsigned int))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::basic_regex, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::word_boundary, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::value, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::reference, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::local, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::placeholder, (typename)(int)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::tracking_ptr, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::regex_impl, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::let_, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::action_arg, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::named_mark, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::sub_match, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::nested_results, (typename))
+
+///////////////////////////////////////////////////////////////////////////////
+// Placeholders
+//
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::mark_placeholder)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::posix_charset_placeholder)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::assert_bol_placeholder)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::assert_eol_placeholder)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::logical_newline_placeholder)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::self_placeholder)
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::assert_word_placeholder, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::range_placeholder, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::attribute_placeholder, (typename))
+
+///////////////////////////////////////////////////////////////////////////////
+// Matchers
+//
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::epsilon_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::true_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::end_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::independent_end_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::any_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::assert_bos_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::assert_eos_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::mark_begin_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::mark_end_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::repeat_begin_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::alternate_end_matcher)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::attr_end_matcher)
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::assert_bol_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::assert_eol_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::literal_matcher, (typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::string_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::charset_matcher, (typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::logical_newline_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::mark_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::repeat_end_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::alternate_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::optional_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::optional_mark_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::simple_repeat_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::regex_byref_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::regex_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::posix_charset_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::assert_word_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::range_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::keeper_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::lookahead_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::lookbehind_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::set_matcher, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::predicate_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::action_matcher, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::attr_matcher, (typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::attr_begin_matcher, (typename))
+
+///////////////////////////////////////////////////////////////////////////////
+// Ops
+//
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::push)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::push_back)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::pop)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::push_front)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::pop_back)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::pop_front)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::back)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::front)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::top)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::first)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::second)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::matched)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::length)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::str)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::insert)
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::op::make_pair)
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::op::as, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::op::static_cast_, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::op::dynamic_cast_, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::op::const_cast_, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::op::construct, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::op::throw_, (typename))
+
+///////////////////////////////////////////////////////////////////////////////
+// Modifiers
+//
+BOOST_TYPEOF_REGISTER_TYPE(boost::xpressive::detail::icase_modifier)
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::detail::locale_modifier, (typename))
+
+///////////////////////////////////////////////////////////////////////////////
+// Traits
+//
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::null_regex_traits, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::cpp_regex_traits, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::c_regex_traits, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::xpressive::regex_traits, (typename)(typename))
+
+#endif