/////////////////////////////////////////////////////////////////////////////// /// \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) # pragma once #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // These are very often needed by client code. #include #include // Doxygen can't handle proto :-( #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED # include # include # include #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 { template struct action_arg { typedef T type; typedef typename add_reference::type reference; reference cast(void *pv) const { return *static_cast::type *>(pv); } }; template 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 struct result {}; template struct result { typedef Expr type; }; template 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 , proto::vararg< proto::when< proto::assign , proto::call > > > {}; struct let_domain : boost::proto::domain > {}; template struct let_ { BOOST_PROTO_BASIC_EXTENDS(Expr, let_, let_domain) BOOST_PROTO_EXTENDS_FUNCTION() }; template void bind_args(let_ const &args, match_results &what) { BindArgs()(args, 0, what); } typedef boost::proto::functional::make_expr make_function; } namespace op { /// \brief \c at is a PolymorphicFunctionObject for indexing into a sequence struct at { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename Cont::reference type; }; template struct result { typedef typename Cont::const_reference type; }; template struct result { typedef typename Cont::const_reference type; }; /// \pre \c Cont is a model of RandomAccessSequence /// \param c The RandomAccessSequence to index into /// \param idx The index /// \return c[idx] template typename Cont::reference operator()(Cont &c, Idx idx BOOST_PROTO_DISABLE_IF_IS_CONST(Cont)) const { return c[idx]; } /// \overload /// template typename Cont::const_reference operator()(Cont const &c, Idx idx) const { return c[idx]; } }; /// \brief \c push is a PolymorphicFunctionObject for pushing an element into a container. struct push { BOOST_PROTO_CALLABLE() typedef void result_type; /// \param seq The sequence into which the value should be pushed. /// \param val The value to push into the sequence. /// \brief Equivalent to seq.push(val). /// \return \c void template void operator()(Sequence &seq, Value const &val) const { seq.push(val); } }; /// \brief \c push_back is a PolymorphicFunctionObject for pushing an element into the back of a container. struct push_back { BOOST_PROTO_CALLABLE() typedef void result_type; /// \param seq The sequence into which the value should be pushed. /// \param val The value to push into the sequence. /// \brief Equivalent to seq.push_back(val). /// \return \c void template void operator()(Sequence &seq, Value const &val) const { seq.push_back(val); } }; /// \brief \c push_front is a PolymorphicFunctionObject for pushing an element into the front of a container. struct push_front { BOOST_PROTO_CALLABLE() typedef void result_type; /// \param seq The sequence into which the value should be pushed. /// \param val The value to push into the sequence. /// \brief Equivalent to seq.push_front(val). /// \return \c void template void operator()(Sequence &seq, Value const &val) const { seq.push_front(val); } }; /// \brief \c pop is a PolymorphicFunctionObject for popping an element from a container. struct pop { BOOST_PROTO_CALLABLE() typedef void result_type; /// \param seq The sequence from which to pop. /// \brief Equivalent to seq.pop(). /// \return \c void template void operator()(Sequence &seq) const { seq.pop(); } }; /// \brief \c pop_back is a PolymorphicFunctionObject for popping an element from the back of a container. struct pop_back { BOOST_PROTO_CALLABLE() typedef void result_type; /// \param seq The sequence from which to pop. /// \brief Equivalent to seq.pop_back(). /// \return \c void template void operator()(Sequence &seq) const { seq.pop_back(); } }; /// \brief \c pop_front is a PolymorphicFunctionObject for popping an element from the front of a container. struct pop_front { BOOST_PROTO_CALLABLE() typedef void result_type; /// \param seq The sequence from which to pop. /// \brief Equivalent to seq.pop_front(). /// \return \c void template void operator()(Sequence &seq) const { seq.pop_front(); } }; /// \brief \c front is a PolymorphicFunctionObject for fetching the front element of a container. struct front { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename remove_reference::type sequence_type; typedef typename mpl::if_c< is_const::value , typename sequence_type::const_reference , typename sequence_type::reference >::type type; }; /// \param seq The sequence from which to fetch the front. /// \return seq.front() template typename result::type operator()(Sequence &seq) const { return seq.front(); } }; /// \brief \c back is a PolymorphicFunctionObject for fetching the back element of a container. struct back { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename remove_reference::type sequence_type; typedef typename mpl::if_c< is_const::value , typename sequence_type::const_reference , typename sequence_type::reference >::type type; }; /// \param seq The sequence from which to fetch the back. /// \return seq.back() template typename result::type operator()(Sequence &seq) const { return seq.back(); } }; /// \brief \c top is a PolymorphicFunctionObject for fetching the top element of a stack. struct top { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename remove_reference::type sequence_type; typedef typename mpl::if_c< is_const::value , typename sequence_type::value_type const & , typename sequence_type::value_type & >::type type; }; /// \param seq The sequence from which to fetch the top. /// \return seq.top() template typename result::type operator()(Sequence &seq) const { return seq.top(); } }; /// \brief \c first is a PolymorphicFunctionObject for fetching the first element of a pair. struct first { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename remove_reference::type::first_type type; }; /// \param p The pair from which to fetch the first element. /// \return p.first template typename Pair::first_type operator()(Pair const &p) const { return p.first; } }; /// \brief \c second is a PolymorphicFunctionObject for fetching the second element of a pair. struct second { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename remove_reference::type::second_type type; }; /// \param p The pair from which to fetch the second element. /// \return p.second template typename Pair::second_type operator()(Pair const &p) const { return p.second; } }; /// \brief \c matched is a PolymorphicFunctionObject for assessing whether a \c sub_match object /// matched or not. struct matched { BOOST_PROTO_CALLABLE() typedef bool result_type; /// \param sub The \c sub_match object. /// \return sub.matched template bool operator()(Sub const &sub) const { return sub.matched; } }; /// \brief \c length is a PolymorphicFunctionObject for fetching the length of \c sub_match. struct length { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename remove_reference::type::difference_type type; }; /// \param sub The \c sub_match object. /// \return sub.length() template typename Sub::difference_type operator()(Sub const &sub) const { return sub.length(); } }; /// \brief \c str is a PolymorphicFunctionObject for turning a \c sub_match into an /// equivalent \c std::string. struct str { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename remove_reference::type::string_type type; }; /// \param sub The \c sub_match object. /// \return sub.str() template 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. // /// \brief \c insert is a PolymorphicFunctionObject for inserting a value or a /// sequence of values into a sequence container, an associative /// container, or a string. struct insert { BOOST_PROTO_CALLABLE() /// INTERNAL ONLY /// struct detail { template struct result_detail {}; // assoc containers template struct result_detail { typedef typename remove_reference::type cont_type; typedef typename remove_reference::type 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); 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 >::type type; }; // sequence containers, assoc containers, strings template struct result_detail::type>::type> , is_same< typename remove_cv::type>::type , typename remove_cv::type>::type > > >::type > { typedef typename remove_reference::type::iterator type; }; // strings template struct result_detail::type>::type> >::type > { typedef typename remove_reference::type &type; }; // assoc containers template struct result_detail { typedef void type; }; // sequence containers, strings template struct result_detail::type>::type> >::type > { typedef void type; }; // strings template struct result_detail::type>::type> >::type > { typedef typename remove_reference::type &type; }; // strings template struct result_detail { typedef typename remove_reference::type &type; }; }; template struct result { typedef typename detail::result_detail::type type; }; /// \overload /// template typename result::type operator()(Cont &cont, A0 const &a0) const { return cont.insert(a0); } /// \overload /// template typename result::type operator()(Cont &cont, A0 const &a0, A1 const &a1) const { return cont.insert(a0, a1); } /// \overload /// template typename result::type operator()(Cont &cont, A0 const &a0, A1 const &a1, A2 const &a2) const { return cont.insert(a0, a1, a2); } /// \param cont The container into which to insert the element(s) /// \param a0 A value, iterator, or count /// \param a1 A value, iterator, string, count, or character /// \param a2 A value, iterator, or count /// \param a3 A count /// \return \li For the form insert()(cont, a0), return cont.insert(a0). /// \li For the form insert()(cont, a0, a1), return cont.insert(a0, a1). /// \li For the form insert()(cont, a0, a1, a2), return cont.insert(a0, a1, a2). /// \li For the form insert()(cont, a0, a1, a2, a3), return cont.insert(a0, a1, a2, a3). template typename result::type operator()(Cont &cont, A0 const &a0, A1 const &a1, A2 const &a2, A3 const &a3) const { return cont.insert(a0, a1, a2, a3); } }; /// \brief \c make_pair is a PolymorphicFunctionObject for building a \c std::pair out of two parameters struct make_pair { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { /// \brief For exposition only typedef typename decay::type first_type; /// \brief For exposition only typedef typename decay::type second_type; typedef std::pair type; }; /// \param first The first element of the pair /// \param second The second element of the pair /// \return std::make_pair(first, second) template std::pair operator()(First const &first, Second const &second) const { return std::make_pair(first, second); } }; /// \brief \c as\<\> is a PolymorphicFunctionObject for lexically casting a parameter to a different type. /// \tparam T The type to which to lexically cast the parameter. template struct as { BOOST_PROTO_CALLABLE() typedef T result_type; /// \param val The value to lexically cast. /// \return boost::lexical_cast\(val) template T operator()(Value const &val) const { return boost::lexical_cast(val); } // Hack around some limitations in boost::lexical_cast /// INTERNAL ONLY T operator()(csub_match const &val) const { return val.matched ? boost::lexical_cast(boost::make_iterator_range(val.first, val.second)) : boost::lexical_cast(""); } #ifndef BOOST_XPRESSIVE_NO_WREGEX /// INTERNAL ONLY T operator()(wcsub_match const &val) const { return val.matched ? boost::lexical_cast(boost::make_iterator_range(val.first, val.second)) : boost::lexical_cast(""); } #endif /// INTERNAL ONLY template T operator()(sub_match const &val) const { // If this assert fires, you're trying to coerce a sequences of non-characters // to some other type. Xpressive doesn't know how to do that. typedef typename iterator_value::type char_type; BOOST_MPL_ASSERT_MSG( (xpressive::detail::is_char::value) , CAN_ONLY_CONVERT_FROM_CHARACTER_SEQUENCES , (char_type) ); return this->impl(val, xpressive::detail::is_string_iterator()); } private: /// INTERNAL ONLY template T impl(sub_match const &val, mpl::true_) const { return val.matched ? boost::lexical_cast(boost::make_iterator_range(&*val.first, &*val.first + (val.second - val.first))) : boost::lexical_cast(""); } /// INTERNAL ONLY template T impl(sub_match const &val, mpl::false_) const { return boost::lexical_cast(val.str()); } }; /// \brief \c static_cast_\<\> is a PolymorphicFunctionObject for statically casting a parameter to a different type. /// \tparam T The type to which to statically cast the parameter. template struct static_cast_ { BOOST_PROTO_CALLABLE() typedef T result_type; /// \param val The value to statically cast. /// \return static_cast\(val) template T operator()(Value const &val) const { return static_cast(val); } }; /// \brief \c dynamic_cast_\<\> is a PolymorphicFunctionObject for dynamically casting a parameter to a different type. /// \tparam T The type to which to dynamically cast the parameter. template struct dynamic_cast_ { BOOST_PROTO_CALLABLE() typedef T result_type; /// \param val The value to dynamically cast. /// \return dynamic_cast\(val) template T operator()(Value const &val) const { return dynamic_cast(val); } }; /// \brief \c const_cast_\<\> is a PolymorphicFunctionObject for const-casting a parameter to a cv qualification. /// \tparam T The type to which to const-cast the parameter. template struct const_cast_ { BOOST_PROTO_CALLABLE() typedef T result_type; /// \param val The value to const-cast. /// \pre Types \c T and \c Value differ only in cv-qualification. /// \return const_cast\(val) template T operator()(Value const &val) const { return const_cast(val); } }; /// \brief \c construct\<\> is a PolymorphicFunctionObject for constructing a new object. /// \tparam T The type of the object to construct. template struct construct { BOOST_PROTO_CALLABLE() typedef T result_type; /// \overload T operator()() const { return T(); } /// \overload template T operator()(A0 const &a0) const { return T(a0); } /// \overload template T operator()(A0 const &a0, A1 const &a1) const { return T(a0, a1); } /// \param a0 The first argument to the constructor /// \param a1 The second argument to the constructor /// \param a2 The third argument to the constructor /// \return T(a0,a1,...) template T operator()(A0 const &a0, A1 const &a1, A2 const &a2) const { return T(a0, a1, a2); } }; /// \brief \c throw_\<\> is a PolymorphicFunctionObject for throwing an exception. /// \tparam Except The type of the object to throw. template struct throw_ { BOOST_PROTO_CALLABLE() typedef void result_type; /// \overload void operator()() const { BOOST_THROW_EXCEPTION(Except()); } /// \overload template void operator()(A0 const &a0) const { BOOST_THROW_EXCEPTION(Except(a0)); } /// \overload template void operator()(A0 const &a0, A1 const &a1) const { BOOST_THROW_EXCEPTION(Except(a0, a1)); } /// \param a0 The first argument to the constructor /// \param a1 The second argument to the constructor /// \param a2 The third argument to the constructor /// \throw Except(a0,a1,...) /// \note This function makes use of the \c BOOST_THROW_EXCEPTION macro /// to actually throw the exception. See the documentation for the /// Boost.Exception library. template void operator()(A0 const &a0, A1 const &a1, A2 const &a2) const { BOOST_THROW_EXCEPTION(Except(a0, a1, a2)); } }; /// \brief \c unwrap_reference is a PolymorphicFunctionObject for unwrapping a boost::reference_wrapper\<\>. struct unwrap_reference { BOOST_PROTO_CALLABLE() template struct result {}; template struct result { typedef typename boost::unwrap_reference::type &type; }; template struct result { typedef typename boost::unwrap_reference::type &type; }; /// \param r The boost::reference_wrapper\ to unwrap. /// \return static_cast\(r) template T &operator()(boost::reference_wrapper r) const { return static_cast(r); } }; } /// \brief A unary metafunction that turns an ordinary function object type into the type of /// a deferred function object for use in xpressive semantic actions. /// /// Use \c xpressive::function\<\> to turn an ordinary polymorphic function object type /// into a type that can be used to declare an object for use in xpressive semantic actions. /// /// For example, the global object \c xpressive::push_back can be used to create deferred actions /// that have the effect of pushing a value into a container. It is defined with /// \c xpressive::function\<\> as follows: /// /** \code xpressive::function::type const push_back = {}; \endcode */ /// /// where \c op::push_back is an ordinary function object that pushes its second argument into /// its first. Thus defined, \c xpressive::push_back can be used in semantic actions as follows: /// /** \code namespace xp = boost::xpressive; using xp::_; std::list result; std::string str("1 23 456 7890"); xp::sregex rx = (+_d)[ xp::push_back(xp::ref(result), xp::as(_) ] >> *(' ' >> (+_d)[ xp::push_back(xp::ref(result), xp::as(_) ) ]); \endcode */ template struct function { typedef typename proto::terminal::type type; }; /// \brief \c at is a lazy PolymorphicFunctionObject for indexing into a sequence in an /// xpressive semantic action. function::type const at = {{}}; /// \brief \c push is a lazy PolymorphicFunctionObject for pushing a value into a container in an /// xpressive semantic action. function::type const push = {{}}; /// \brief \c push_back is a lazy PolymorphicFunctionObject for pushing a value into a container in an /// xpressive semantic action. function::type const push_back = {{}}; /// \brief \c push_front is a lazy PolymorphicFunctionObject for pushing a value into a container in an /// xpressive semantic action. function::type const push_front = {{}}; /// \brief \c pop is a lazy PolymorphicFunctionObject for popping the top element from a sequence in an /// xpressive semantic action. function::type const pop = {{}}; /// \brief \c pop_back is a lazy PolymorphicFunctionObject for popping the back element from a sequence in an /// xpressive semantic action. function::type const pop_back = {{}}; /// \brief \c pop_front is a lazy PolymorphicFunctionObject for popping the front element from a sequence in an /// xpressive semantic action. function::type const pop_front = {{}}; /// \brief \c top is a lazy PolymorphicFunctionObject for accessing the top element from a stack in an /// xpressive semantic action. function::type const top = {{}}; /// \brief \c back is a lazy PolymorphicFunctionObject for fetching the back element of a sequence in an /// xpressive semantic action. function::type const back = {{}}; /// \brief \c front is a lazy PolymorphicFunctionObject for fetching the front element of a sequence in an /// xpressive semantic action. function::type const front = {{}}; /// \brief \c first is a lazy PolymorphicFunctionObject for accessing the first element of a \c std::pair\<\> in an /// xpressive semantic action. function::type const first = {{}}; /// \brief \c second is a lazy PolymorphicFunctionObject for accessing the second element of a \c std::pair\<\> in an /// xpressive semantic action. function::type const second = {{}}; /// \brief \c matched is a lazy PolymorphicFunctionObject for accessing the \c matched member of a \c xpressive::sub_match\<\> in an /// xpressive semantic action. function::type const matched = {{}}; /// \brief \c length is a lazy PolymorphicFunctionObject for computing the length of a \c xpressive::sub_match\<\> in an /// xpressive semantic action. function::type const length = {{}}; /// \brief \c str is a lazy PolymorphicFunctionObject for converting a \c xpressive::sub_match\<\> to a \c std::basic_string\<\> in an /// xpressive semantic action. function::type const str = {{}}; /// \brief \c insert is a lazy PolymorphicFunctionObject for inserting a value or a range of values into a sequence in an /// xpressive semantic action. function::type const insert = {{}}; /// \brief \c make_pair is a lazy PolymorphicFunctionObject for making a \c std::pair\<\> in an /// xpressive semantic action. function::type const make_pair = {{}}; /// \brief \c unwrap_reference is a lazy PolymorphicFunctionObject for unwrapping a \c boost::reference_wrapper\<\> in an /// xpressive semantic action. function::type const unwrap_reference = {{}}; /// \brief \c value\<\> is a lazy wrapper for a value that can be used in xpressive semantic actions. /// \tparam T The type of the value to store. /// /// Below is an example that shows where \c value\<\> is useful. /// /** \code sregex good_voodoo(boost::shared_ptr pi) { using namespace boost::xpressive; // Use val() to hold the shared_ptr by value: sregex rex = +( _d [ ++*val(pi) ] >> '!' ); // OK, rex holds a reference count to the integer. return rex; } \endcode */ /// /// In the above code, \c xpressive::val() is a function that returns a \c value\<\> object. Had /// \c val() not been used here, the operation ++*pi would have been evaluated eagerly /// once, instead of lazily when the regex match happens. template struct value : proto::extends::type, value > { /// INTERNAL ONLY typedef proto::extends::type, value > base_type; /// \brief Store a default-constructed \c T value() : base_type() {} /// \param t The initial value. /// \brief Store a copy of \c t. explicit value(T const &t) : base_type(base_type::proto_base_expr::make(t)) {} using base_type::operator=; /// \overload T &get() { return proto::value(*this); } /// \brief Fetch the stored value T const &get() const { return proto::value(*this); } }; /// \brief \c reference\<\> is a lazy wrapper for a reference that can be used in /// xpressive semantic actions. /// /// \tparam T The type of the referent. /// /// Here is an example of how to use \c reference\<\> to create a lazy reference to /// an existing object so it can be read and written in an xpressive semantic action. /// /** \code using namespace boost::xpressive; std::map result; reference > result_ref(result); // Match a word and an integer, separated by =>, // and then stuff the result into a std::map<> sregex pair = ( (s1= +_w) >> "=>" >> (s2= +_d) ) [ result_ref[s1] = as(s2) ]; \endcode */ template struct reference : proto::extends >::type, reference > { /// INTERNAL ONLY typedef proto::extends >::type, reference > base_type; /// \param t Reference to object /// \brief Store a reference to \c t explicit reference(T &t) : base_type(base_type::proto_base_expr::make(boost::ref(t))) {} using base_type::operator=; /// \brief Fetch the stored value T &get() const { return proto::value(*this).get(); } }; /// \brief \c local\<\> is a lazy wrapper for a reference to a value that is stored within the local itself. /// It is for use within xpressive semantic actions. /// /// \tparam T The type of the local variable. /// /// Below is an example of how to use \c local\<\> in semantic actions. /// /** \code using namespace boost::xpressive; local i(0); std::string str("1!2!3?"); // count the exciting digits, but not the // questionable ones. sregex rex = +( _d [ ++i ] >> '!' ); regex_search(str, rex); assert( i.get() == 2 ); \endcode */ /// /// \note As the name "local" suggests, \c local\<\> objects and the regexes /// that refer to them should never leave the local scope. The value stored /// within the local object will be destroyed at the end of the \c local\<\>'s /// lifetime, and any regex objects still holding the \c local\<\> will be /// left with a dangling reference. template struct local : detail::value_wrapper , proto::terminal >::type { /// INTERNAL ONLY typedef typename proto::terminal >::type base_type; /// \brief Store a default-constructed value of type \c T local() : detail::value_wrapper() , base_type(base_type::make(boost::ref(detail::value_wrapper::value))) {} /// \param t The initial value. /// \brief Store a default-constructed value of type \c T explicit local(T const &t) : detail::value_wrapper(t) , base_type(base_type::make(boost::ref(detail::value_wrapper::value))) {} using base_type::operator=; /// Fetch the wrapped value. T &get() { return proto::value(*this); } /// \overload T const &get() const { return proto::value(*this); } }; /// \brief \c as() is a lazy funtion for lexically casting a parameter to a different type. /// \tparam T The type to which to lexically cast the parameter. /// \param a The lazy value to lexically cast. /// \return A lazy object that, when evaluated, lexically casts its argument to the desired type. template typename detail::make_function::impl const, A const &>::result_type const as(A const &a) { return detail::make_function::impl const, A const &>()((op::as()), a); } /// \brief \c static_cast_ is a lazy funtion for statically casting a parameter to a different type. /// \tparam T The type to which to statically cast the parameter. /// \param a The lazy value to statically cast. /// \return A lazy object that, when evaluated, statically casts its argument to the desired type. template typename detail::make_function::impl const, A const &>::result_type const static_cast_(A const &a) { return detail::make_function::impl const, A const &>()((op::static_cast_()), a); } /// \brief \c dynamic_cast_ is a lazy funtion for dynamically casting a parameter to a different type. /// \tparam T The type to which to dynamically cast the parameter. /// \param a The lazy value to dynamically cast. /// \return A lazy object that, when evaluated, dynamically casts its argument to the desired type. template typename detail::make_function::impl const, A const &>::result_type const dynamic_cast_(A const &a) { return detail::make_function::impl const, A const &>()((op::dynamic_cast_()), a); } /// \brief \c dynamic_cast_ is a lazy funtion for const-casting a parameter to a different type. /// \tparam T The type to which to const-cast the parameter. /// \param a The lazy value to const-cast. /// \return A lazy object that, when evaluated, const-casts its argument to the desired type. template typename detail::make_function::impl const, A const &>::result_type const const_cast_(A const &a) { return detail::make_function::impl const, A const &>()((op::const_cast_()), a); } /// \brief Helper for constructing \c value\<\> objects. /// \return value\(t) template value const val(T const &t) { return value(t); } /// \brief Helper for constructing \c reference\<\> objects. /// \return reference\(t) template reference const ref(T &t) { return reference(t); } /// \brief Helper for constructing \c reference\<\> objects that /// store a reference to const. /// \return reference\(t) template reference const cref(T const &t) { return reference(t); } /// \brief For adding user-defined assertions to your regular expressions. /// /// \param t The UnaryPredicate object or Boolean semantic action. /// /// A \RefSect{user_s_guide.semantic_actions_and_user_defined_assertions.user_defined_assertions,user-defined assertion} /// is a kind of semantic action that evaluates /// a Boolean lambda and, if it evaluates to false, causes the match to /// fail at that location in the string. This will cause backtracking, /// so the match may ultimately succeed. /// /// To use \c check() to specify a user-defined assertion in a regex, use the /// following syntax: /// /** \code sregex s = (_d >> _d)[check( XXX )]; // XXX is a custom assertion \endcode */ /// /// The assertion is evaluated with a \c sub_match\<\> object that delineates /// what part of the string matched the sub-expression to which the assertion /// was attached. /// /// \c check() can be used with an ordinary predicate that takes a /// \c sub_match\<\> object as follows: /// /** \code // A predicate that is true IFF a sub-match is // either 3 or 6 characters long. struct three_or_six { bool operator()(ssub_match const &sub) const { return sub.length() == 3 || sub.length() == 6; } }; // match words of 3 characters or 6 characters. sregex rx = (bow >> +_w >> eow)[ check(three_or_six()) ] ; \endcode */ /// /// Alternately, \c check() can be used to define inline custom /// assertions with the same syntax as is used to define semantic /// actions. The following code is equivalent to above: /// /** \code // match words of 3 characters or 6 characters. sregex rx = (bow >> +_w >> eow)[ check(length(_)==3 || length(_)==6) ] ; \endcode */ /// /// Within a custom assertion, \c _ is a placeholder for the \c sub_match\<\> /// That delineates the part of the string matched by the sub-expression to /// which the custom assertion was attached. #ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED // A hack so Doxygen emits something more meaningful. template detail::unspecified check(T const &t); #else proto::terminal::type const check = {{}}; #endif /// \brief For binding local variables to placeholders in semantic actions when /// constructing a \c regex_iterator or a \c regex_token_iterator. /// /// \param args A set of argument bindings, where each argument binding is an assignment /// expression, the left hand side of which must be an instance of \c placeholder\ /// for some \c X, and the right hand side is an lvalue of type \c X. /// /// \c xpressive::let() serves the same purpose as match_results::let(); /// that is, it binds a placeholder to a local value. The purpose is to allow a /// regex with semantic actions to be defined that refers to objects that do not yet exist. /// Rather than referring directly to an object, a semantic action can refer to a placeholder, /// and the value of the placeholder can be specified later with a let expression. /// The let expression created with \c let() is passed to the constructor of either /// \c regex_iterator or \c regex_token_iterator. /// /// See the section \RefSect{user_s_guide.semantic_actions_and_user_defined_assertions.referring_to_non_local_variables, "Referring to Non-Local Variables"} /// in the Users' Guide for more discussion. /// /// \em Example: /// /** \code // Define a placeholder for a map object: placeholder > _map; // Match a word and an integer, separated by =>, // and then stuff the result into a std::map<> sregex pair = ( (s1= +_w) >> "=>" >> (s2= +_d) ) [ _map[s1] = as(s2) ]; // The string to parse std::string str("aaa=>1 bbb=>23 ccc=>456"); // Here is the actual map to fill in: std::map result; // Create a regex_iterator to find all the matches sregex_iterator it(str.begin(), str.end(), pair, let(_map=result)); sregex_iterator end; // step through all the matches, and fill in // the result map while(it != end) ++it; std::cout << result["aaa"] << '\n'; std::cout << result["bbb"] << '\n'; std::cout << result["ccc"] << '\n'; \endcode */ /// /// The above code displays: /// /** \code{.txt} 1 23 456 \endcode */ #ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED // A hack so Doxygen emits something more meaningful. template detail::unspecified let(ArgBindings const &...args); #else detail::let_::type> const let = {{{}}}; #endif /// \brief For defining a placeholder to stand in for a variable a semantic action. /// /// Use \c placeholder\<\> to define a placeholder for use in semantic actions to stand /// in for real objects. The use of placeholders allows regular expressions with actions /// to be defined once and reused in many contexts to read and write from objects which /// were not available when the regex was defined. /// /// \tparam T The type of the object for which this placeholder stands in. /// \tparam I An optional identifier that can be used to distinguish this placeholder /// from others that may be used in the same semantic action that happen /// to have the same type. /// /// You can use \c placeholder\<\> by creating an object of type \c placeholder\ /// and using that object in a semantic action exactly as you intend an object of /// type \c T to be used. /// /** \code placeholder _i; placeholder _d; sregex rex = ( some >> regex >> here ) [ ++_i, _d *= _d ]; \endcode */ /// /// Then, when doing a pattern match with either \c regex_search(), /// \c regex_match() or \c regex_replace(), pass a \c match_results\<\> object that /// contains bindings for the placeholders used in the regex object's semantic actions. /// You can create the bindings by calling \c match_results::let as follows: /// /** \code int i = 0; double d = 3.14; smatch what; what.let(_i = i) .let(_d = d); if(regex_match("some string", rex, what)) // i and d mutated here \endcode */ /// /// If a semantic action executes that contains an unbound placeholder, a exception of /// type \c regex_error is thrown. /// /// See the discussion for \c xpressive::let() and the /// \RefSect{user_s_guide.semantic_actions_and_user_defined_assertions.referring_to_non_local_variables, "Referring to Non-Local Variables"} /// section in the Users' Guide for more information. /// /// Example: /// /** \code // Define a placeholder for a map object: placeholder > _map; // Match a word and an integer, separated by =>, // and then stuff the result into a std::map<> sregex pair = ( (s1= +_w) >> "=>" >> (s2= +_d) ) [ _map[s1] = as(s2) ]; // Match one or more word/integer pairs, separated // by whitespace. sregex rx = pair >> *(+_s >> pair); // The string to parse std::string str("aaa=>1 bbb=>23 ccc=>456"); // Here is the actual map to fill in: std::map result; // Bind the _map placeholder to the actual map smatch what; what.let( _map = result ); // Execute the match and fill in result map if(regex_match(str, what, rx)) { std::cout << result["aaa"] << '\n'; std::cout << result["bbb"] << '\n'; std::cout << result["ccc"] << '\n'; } \endcode */ #ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED // A hack so Doxygen emits something more meaningful. template struct placeholder { /// \param t The object to associate with this placeholder /// \return An object of unspecified type that records the association of \c t /// with \c *this. detail::unspecified operator=(T &t) const; /// \overload detail::unspecified operator=(T const &t) const; }; #else template struct placeholder { typedef placeholder this_type; typedef typename proto::terminal > >::type action_arg_type; BOOST_PROTO_EXTENDS(action_arg_type, this_type, proto::default_domain) }; #endif /// \brief A lazy funtion for constructing objects objects of the specified type. /// \tparam T The type of object to construct. /// \param args The arguments to the constructor. /// \return A lazy object that, when evaluated, returns T(xs...), where /// xs... is the result of evaluating the lazy arguments /// args.... #ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED // A hack so Doxygen emits something more meaningful. template detail::unspecified construct(Args const &...args); #else /// INTERNAL ONLY #define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, A_const_ref_a, a) \ template \ typename detail::make_function::impl< \ op::construct 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 const \ BOOST_PP_COMMA_IF(N) A_const_ref(N) \ >()((op::construct()) BOOST_PP_COMMA_IF(N) a(N)); \ } \ \ template \ typename detail::make_function::impl< \ op::throw_ 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_ const \ BOOST_PP_COMMA_IF(N) A_const_ref(N) \ >()((op::throw_()) BOOST_PP_COMMA_IF(N) a(N)); \ } \ /**/ #define BOOST_PROTO_LOCAL_a BOOST_PROTO_a ///< INTERNAL ONLY #define BOOST_PROTO_LOCAL_LIMITS (0, BOOST_PP_DEC(BOOST_PROTO_MAX_ARITY)) ///< INTERNAL ONLY #include BOOST_PROTO_LOCAL_ITERATE() #endif 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 , op::at(proto::_data, proto::call) > , proto::when< proto::terminal , op::at(proto::_data, proto::size_t<0>) > , proto::when< proto::terminal > , op::unwrap_reference(proto::_value) > , proto::_default > {}; } }} #if BOOST_MSVC #pragma warning(pop) #endif #endif // BOOST_XPRESSIVE_ACTIONS_HPP_EAN_03_22_2007