$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r63305 - in trunk: boost/xpressive/detail/core/matcher libs/xpressive/test
From: eric_at_[hidden]
Date: 2010-06-25 09:49:05
Author: eric_niebler
Date: 2010-06-25 09:49:03 EDT (Fri, 25 Jun 2010)
New Revision: 63305
URL: http://svn.boost.org/trac/boost/changeset/63305
Log:
support user-defined assertions with placeholders for non-local variables
Added:
   trunk/libs/xpressive/test/test_assert_with_placeholder.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/xpressive/detail/core/matcher/predicate_matcher.hpp |    32 ++++++++++++++++++++++++++++++--        
   trunk/libs/xpressive/test/Jamfile.v2                            |     1 +                                       
   2 files changed, 31 insertions(+), 2 deletions(-)
Modified: trunk/boost/xpressive/detail/core/matcher/predicate_matcher.hpp
==============================================================================
--- trunk/boost/xpressive/detail/core/matcher/predicate_matcher.hpp	(original)
+++ trunk/boost/xpressive/detail/core/matcher/predicate_matcher.hpp	2010-06-25 09:49:03 EDT (Fri, 25 Jun 2010)
@@ -29,11 +29,17 @@
     template<typename BidiIter>
     struct predicate_context
     {
-        explicit predicate_context(int sub, sub_match_impl<BidiIter> const *sub_matches)
+        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
@@ -70,6 +76,26 @@
             }
         };
 
+        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
@@ -88,8 +114,10 @@
         {};
         #endif
 
+    private:
         int sub_;
         sub_match_impl<BidiIter> const *sub_matches_;
+        action_args_type *action_args_;
     };
 
     ///////////////////////////////////////////////////////////////////////////////
@@ -137,7 +165,7 @@
         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_);
+            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);
         }
     };
Modified: trunk/libs/xpressive/test/Jamfile.v2
==============================================================================
--- trunk/libs/xpressive/test/Jamfile.v2	(original)
+++ trunk/libs/xpressive/test/Jamfile.v2	2010-06-25 09:49:03 EDT (Fri, 25 Jun 2010)
@@ -56,6 +56,7 @@
          [ run test_static.cpp ]
          [ run test_actions.cpp ]
          [ run test_assert.cpp ]
+         [ run test_assert_with_placeholder.cpp ]
          [ run test_symbols.cpp ]
          [ run test_dynamic.cpp ]
          [ run test_dynamic_grammar.cpp ]
Added: trunk/libs/xpressive/test/test_assert_with_placeholder.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/xpressive/test/test_assert_with_placeholder.cpp	2010-06-25 09:49:03 EDT (Fri, 25 Jun 2010)
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////////
+// test_assert_with_placeholder.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)
+
+#include <boost/xpressive/xpressive.hpp>
+#include <boost/xpressive/regex_actions.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace boost::xpressive;
+
+placeholder<int> const _cnt = {{}};
+
+struct count_a_impl
+{
+    typedef void result_type;
+
+    void operator()(int &cnt) const
+    {
+        ++cnt;
+    }
+};
+
+boost::xpressive::function<count_a_impl>::type const count_a = {{}};
+
+struct check_a_impl
+{
+    typedef bool result_type;
+
+    bool operator()(int &cnt, int val) const
+    {
+        if(cnt < val)
+        {
+            ++cnt;
+            return true;
+        }
+        return false;
+    }
+};
+
+boost::xpressive::function<check_a_impl>::type const check_a = {{}};
+
+void test_assert_with_placeholder()
+{
+    int cnt = 0;
+    std::string a_str("a_aaaaa___a_aa_aaa_");
+    const sregex expr1(*(as_xpr('a')[count_a(_cnt)] | '_'));
+    const sregex expr2(*(as_xpr('a')[check(check_a(_cnt, 5))] | '_'));
+
+    sregex_iterator iter1(a_str.begin(), a_str.end(), expr1,
+                  let(_cnt = cnt));
+    BOOST_CHECK_EQUAL(iter1->str(0), a_str);
+    BOOST_CHECK_EQUAL(cnt, 12);
+
+    cnt = 0;
+    sregex_iterator iter2(a_str.begin(), a_str.end(), expr2,
+                  let(_cnt = cnt));
+
+    BOOST_CHECK_EQUAL(iter2->str(0), std::string("a_aaaa"));
+    BOOST_CHECK_EQUAL(cnt, 5);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+    test_suite *test = BOOST_TEST_SUITE("test that custom assertions can use argument placeholders");
+
+    test->add(BOOST_TEST_CASE(&test_assert_with_placeholder));
+
+    return test;
+}