$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: hartmut.kaiser_at_[hidden]
Date: 2008-04-19 21:42:28
Author: hkaiser
Date: 2008-04-19 21:42:27 EDT (Sat, 19 Apr 2008)
New Revision: 44608
URL: http://svn.boost.org/trac/boost/changeset/44608
Log:
Spirit.Lex: First version of wrapped semantic actions.
Added:
   trunk/boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp   (contents, props changed)
Text files modified: 
   trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_functor.hpp        |    21 +++++++++++++++++----                   
   trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_lexer.hpp          |     4 +++-                                    
   trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_static_functor.hpp |    20 ++++++++++++++++----                    
   trunk/libs/spirit/example/lex/word_count_lexer.cpp                   |     3 ++-                                     
   4 files changed, 38 insertions(+), 10 deletions(-)
Modified: trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_functor.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_functor.hpp	(original)
+++ trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_functor.hpp	2008-04-19 21:42:27 EDT (Sat, 19 Apr 2008)
@@ -20,6 +20,7 @@
 #include <boost/spirit/home/support/detail/lexer/rules.hpp>
 #include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
 #include <boost/spirit/home/lex/lexer/lexertl/iterator_tokenizer.hpp>
+#include <boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp>
 
 #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
 #define BOOST_SPIRIT_EOF_PREFIX static
@@ -47,6 +48,10 @@
 
             typedef unused_type semantic_actions_type;
 
+            typedef 
+                detail::wrap_action<unused_type, iterpair_type, Data>
+            wrap_action_type;
+
             // initialize the shared data 
             template <typename IterData>
             Data (IterData const& data_, Iterator& first_, Iterator const& last_)
@@ -83,7 +88,7 @@
           : Data<Iterator, mpl::false_, mpl::false_>
         {
             typedef Data<Iterator, mpl::false_, mpl::false_> base_type;
-            
+
             // initialize the shared data 
             template <typename IterData>
             Data (IterData const& data_, Iterator& first_, Iterator const& last_)
@@ -127,11 +132,15 @@
                 boost::detail::iterator_traits<Iterator>::value_type 
             char_type;
 
-            typedef void functor_type(iterpair_type, std::size_t, Data&, bool&);
+            typedef void functor_type(iterpair_type, std::size_t, bool&, Data&);
             typedef boost::function<functor_type> functor_wrapper_type;
             typedef std::multimap<std::size_t, functor_wrapper_type> 
                 semantic_actions_type;
 
+            typedef 
+                detail::wrap_action<functor_wrapper_type, iterpair_type, Data>
+            wrap_action_type;
+
             template <typename IterData>
             Data (IterData const& data_, Iterator& first_, Iterator const& last_)
               : base_type(data_, first_, last_),
@@ -154,7 +163,7 @@
                 std::pair<iterator_type, iterator_type> p = actions.equal_range(id);
                 while (p.first != p.second)
                 {
-                    ((*p.first).second)(itp, id, *this, match);
+                    ((*p.first).second)(itp, id, match, *this);
                     if (!match)
                         return false;   // return a 'no-match'
                     ++p.first;
@@ -230,7 +239,7 @@
         
     public:
         lexertl_functor()
-#if 0 != __DECCXX_VER || BOOST_INTEL_CXX_VERSION > 900 || defined(__PGI)
+#if /*0 != __DECCXX_VER || BOOST_INTEL_CXX_VERSION > 900 || */defined(__PGI)
           : eof()
 #endif // 0 != __DECCXX_VER
         {}
@@ -247,6 +256,10 @@
         typedef Iterator iterator_type;
         typedef typename shared::semantic_actions_type semantic_actions_type;
 
+        // this is needed to wrap the semantic actions in a proper way
+        typedef typename shared::wrap_action_type wrap_action_type;
+
+        ///////////////////////////////////////////////////////////////////////
         template <typename MultiPass>
         static result_type& get_next(MultiPass& mp, result_type& result)
         {
Modified: trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_lexer.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_lexer.hpp	(original)
+++ trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_lexer.hpp	2008-04-19 21:42:27 EDT (Sat, 19 Apr 2008)
@@ -293,7 +293,9 @@
                 typename Functor::semantic_actions_type::value_type
             value_type;
             
-            actions.insert(value_type(id, act));
+            typedef typename Functor::wrap_action_type wrapper_type;
+
+            actions.insert(value_type(id, wrapper_type::call(act)));
         }
                 
         bool init_dfa() const
Modified: trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_static_functor.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_static_functor.hpp	(original)
+++ trunk/boost/spirit/home/lex/lexer/lexertl/lexertl_static_functor.hpp	2008-04-19 21:42:27 EDT (Sat, 19 Apr 2008)
@@ -50,6 +50,10 @@
 
             typedef unused_type semantic_actions_type;
 
+            typedef 
+                detail::wrap_action<unused_type, iterpair_type, Data>
+            wrap_action_type;
+
             // initialize the shared data 
             template <typename IterData>
             Data (IterData const& data_, Iterator& first_, Iterator const& last_)
@@ -121,11 +125,15 @@
                 boost::detail::iterator_traits<Iterator>::value_type 
             char_type;
 
-            typedef void functor_type(iterpair_type, std::size_t, Data&, bool&);
+            typedef void functor_type(iterpair_type, std::size_t, bool&, Data&);
             typedef boost::function<functor_type> functor_wrapper_type;
             typedef std::multimap<std::size_t, functor_wrapper_type> 
                 semantic_actions_type;
 
+            typedef 
+                detail::wrap_action<functor_wrapper_type, iterpair_type, Data>
+            wrap_action_type;
+
             template <typename IterData>
             Data (IterData const& data_, Iterator& first_, Iterator const& last_)
               : base_type(data_, first_, last_),
@@ -148,7 +156,7 @@
                 std::pair<iterator_type, iterator_type> p = actions.equal_range(id);
                 while (p.first != p.second)
                 {
-                    ((*p.first).second)(itp, id, *this, match);
+                    ((*p.first).second)(itp, id, match, *this);
                     if (!match)
                         return false;   // return a 'no-match'
                     ++p.first;
@@ -224,8 +232,8 @@
         
     public:
         lexertl_static_functor()
-#if 0 != __DECCXX_VER || BOOST_INTEL_CXX_VERSION > 900
-          , eof()
+#if /*0 != __DECCXX_VER || BOOST_INTEL_CXX_VERSION > 900 || */defined(__PGI)
+          : eof()
 #endif // 0 != __DECCXX_VER
         {}
         
@@ -242,6 +250,10 @@
         typedef typename shared::semantic_actions_type semantic_actions_type;
         typedef typename shared::next_token_functor next_token_functor;
 
+        // this is needed to wrap the semantic actions in a proper way
+        typedef typename shared::wrap_action_type wrap_action_type;
+
+        ///////////////////////////////////////////////////////////////////////
         template <typename MultiPass>
         result_type& operator()(MultiPass& mp, result_type& result)
         {
Added: trunk/boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp	2008-04-19 21:42:27 EDT (Sat, 19 Apr 2008)
@@ -0,0 +1,123 @@
+/*=============================================================================
+    Copyright (c) 2001-2008 Joel de Guzman
+    Copyright (c) 2001-2008 Hartmut Kaiser
+    http://spirit.sourceforge.net/
+
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_WRAP_ACTION_APR_19_2008_0103PM)
+#define BOOST_SPIRIT_WRAP_ACTION_APR_19_2008_0103PM
+
+#include <boost/spirit/home/support/detail/values.hpp>
+#include <boost/spirit/home/phoenix/core/actor.hpp>
+#include <boost/spirit/home/phoenix/core/argument.hpp>
+#include <boost/spirit/home/phoenix/bind.hpp>
+
+#include <boost/bind.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace lex { namespace detail
+{
+    template <typename FunctionType, typename Attribute, typename Context>
+    struct wrap_action
+    {
+        // plain functors are not touched at all
+        template <typename F>
+        static FunctionType call(F const& f)
+        {
+            return f;
+        }
+
+        // wrap phoenix actor, make sure first argument is a fusion sequence
+        template <typename Eval>
+        static void phoenix_action(phoenix::actor<Eval> const& f, 
+            Attribute const& attr, std::size_t id, bool& pass, Context& ctx)
+        {
+            f(spirit::detail::pass_value<Attribute const>::call(attr), id, pass, ctx);
+        }
+        
+        template <typename Eval>
+        static FunctionType call(phoenix::actor<Eval> const& f)
+        {
+//             using phoenix::arg_names::arg1;
+//             using phoenix::arg_names::arg2;
+//             using phoenix::arg_names::arg3;
+//             using phoenix::arg_names::arg4;
+// 
+//             return phoenix::bind(
+//                 &wrap_action::phoenix_action<Eval>, f, arg1, arg2, arg3, arg4);
+
+            return boost::bind(
+                &wrap_action::phoenix_action<Eval>, f, _1, _2, _3, _4);
+        }
+
+        // semantic actions with 3 arguments
+        template <typename F>
+        static void arg3_action(F* f, Attribute const& attr, 
+            std::size_t id, bool& pass, Context&)
+        {
+            f(attr, id, pass);
+        }
+
+        template <typename A0, typename A1, typename A2>
+        static FunctionType call(void(*f)(A0, A1, A2))
+        {
+            using phoenix::arg_names::arg1;
+            using phoenix::arg_names::arg2;
+            using phoenix::arg_names::arg3;
+
+            return phoenix::bind(
+                &wrap_action::arg3_action<void(A0, A1, A2)>, f, arg1, arg2, arg3);
+        }
+
+        // semantic actions with 2 arguments
+        template <typename F>
+        static void arg2_action(F* f, Attribute const& attr, 
+            std::size_t id, bool&, Context&)
+        {
+            f(attr, id);
+        }
+
+        template <typename A0, typename A1>
+        static FunctionType call(void(*f)(A0, A1))
+        {
+            using phoenix::arg_names::arg1;
+            using phoenix::arg_names::arg2;
+
+            return phoenix::bind(
+                &wrap_action::arg2_action<void(A0, A1)>, f, arg1, arg2);
+        }
+
+        // semantic actions with 1 argument
+        template <typename F>
+        static void arg1_action(F* f, Attribute const& attr, 
+            std::size_t, bool&, Context&)
+        {
+            f(attr);
+        }
+
+        template <typename A0>
+        static FunctionType call(void(*f)(A0))
+        {
+            using phoenix::arg_names::arg1;
+            return phoenix::bind(&wrap_action::arg1_action<void(A0)>, f, arg1);
+        }
+    };
+
+    // specialization allowing to skip wrapping for lexer types not supporting
+    // semantic actions
+    template <typename Attribute, typename Context>
+    struct wrap_action<unused_type, Attribute, Context>
+    {
+        // plain functors are not touched at all
+        template <typename F>
+        static F const& call(F const& f)
+        {
+            return f;
+        }
+    };
+
+}}}}
+
+#endif
Modified: trunk/libs/spirit/example/lex/word_count_lexer.cpp
==============================================================================
--- trunk/libs/spirit/example/lex/word_count_lexer.cpp	(original)
+++ trunk/libs/spirit/example/lex/word_count_lexer.cpp	2008-04-19 21:42:27 EDT (Sat, 19 Apr 2008)
@@ -33,6 +33,7 @@
 // #define BOOST_SPIRIT_LEXERTL_DEBUG
 
 //[wcl_includes
+#include <boost/spirit/include/support_argument.hpp>
 #include <boost/spirit/include/lex_lexer_lexertl.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
 #include <boost/spirit/include/phoenix_statement.hpp>
@@ -77,7 +78,7 @@
         // the namespace boost::phoenix::arg_names (not spirit::arg_names). 
         // Using the wrong placeholders leads to subtle compilation errors 
         // which are difficult to backtrack to their cause.
-        using boost::phoenix::arg_names::_1;
+        using boost::spirit::arg_names::_1;
 
         // associate tokens with the lexer
         self =  word  [++ref(w), ref(c) += distance(_1)]