Boost logo

Boost-Commit :

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)]


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk