1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
4     http://spirit.sourceforge.net/
5 
6     Distributed under the Boost Software License, Version 1.0. (See accompanying
7     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_SPIRIT_WRAP_ACTION_APR_19_2008_0103PM)
10 #define BOOST_SPIRIT_WRAP_ACTION_APR_19_2008_0103PM
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
16 #include <boost/spirit/include/phoenix_core.hpp>
17 #include <boost/spirit/include/phoenix_bind.hpp>
18 #include <boost/spirit/include/phoenix_scope.hpp>
19 
20 #include <boost/spirit/home/support/attributes.hpp>
21 #include <boost/spirit/home/lex/lexer/pass_flags.hpp>
22 
23 ///////////////////////////////////////////////////////////////////////////////
24 namespace boost { namespace spirit { namespace lex { namespace lexertl
25 {
26     namespace detail
27     {
28         template <typename FunctionType, typename Iterator, typename Context
29           , typename IdType>
30         struct wrap_action
31         {
32             // plain functions with 5 arguments, function objects (including
33             // phoenix actors) are not touched at all
34             template <typename F>
callboost::spirit::lex::lexertl::detail::wrap_action35             static FunctionType call(F const& f)
36             {
37                 return f;
38             }
39 
40             // semantic actions with 4 arguments
41             template <typename F>
arg4_actionboost::spirit::lex::lexertl::detail::wrap_action42             static void arg4_action(F* f, Iterator& start, Iterator& end
43               , BOOST_SCOPED_ENUM(pass_flags)& pass, IdType& id
44               , Context const&)
45             {
46                 f(start, end, pass, id);
47             }
48 
49             template <typename A0, typename A1, typename A2, typename A3>
callboost::spirit::lex::lexertl::detail::wrap_action50             static FunctionType call(void (*f)(A0, A1, A2, A3))
51             {
52                 void (*pf)(void(*)(A0, A1, A2, A3)
53                   , Iterator&, Iterator&, BOOST_SCOPED_ENUM(pass_flags)&
54                   , IdType&, Context const&) = &wrap_action::arg4_action;
55 
56                 using phoenix::arg_names::_1;
57                 using phoenix::arg_names::_2;
58                 using phoenix::arg_names::_3;
59                 using phoenix::arg_names::_4;
60                 using phoenix::arg_names::_5;
61                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
62             }
63 
64             // semantic actions with 3 arguments
65             template <typename F>
arg3_actionboost::spirit::lex::lexertl::detail::wrap_action66             static void arg3_action(F* f, Iterator& start, Iterator& end
67               , BOOST_SCOPED_ENUM(pass_flags)& pass, IdType
68               , Context const&)
69             {
70                 f(start, end, pass);
71             }
72 
73             template <typename A0, typename A1, typename A2>
callboost::spirit::lex::lexertl::detail::wrap_action74             static FunctionType call(void (*f)(A0, A1, A2))
75             {
76                 void (*pf)(void(*)(A0, A1, A2), Iterator&, Iterator&
77                   , BOOST_SCOPED_ENUM(pass_flags)&, IdType
78                   , Context const&) = &wrap_action::arg3_action;
79 
80                 using phoenix::arg_names::_1;
81                 using phoenix::arg_names::_2;
82                 using phoenix::arg_names::_3;
83                 using phoenix::arg_names::_4;
84                 using phoenix::arg_names::_5;
85                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
86             }
87 
88             // semantic actions with 2 arguments
89             template <typename F>
arg2_actionboost::spirit::lex::lexertl::detail::wrap_action90             static void arg2_action(F* f, Iterator& start, Iterator& end
91               , BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
92             {
93                 f (start, end);
94             }
95 
96             template <typename A0, typename A1>
callboost::spirit::lex::lexertl::detail::wrap_action97             static FunctionType call(void (*f)(A0, A1))
98             {
99                 void (*pf)(void(*)(A0, A1), Iterator&, Iterator&
100                   , BOOST_SCOPED_ENUM(pass_flags)&
101                   , IdType, Context const&) = &wrap_action::arg2_action;
102 
103                 using phoenix::arg_names::_1;
104                 using phoenix::arg_names::_2;
105                 using phoenix::arg_names::_3;
106                 using phoenix::arg_names::_4;
107                 using phoenix::arg_names::_5;
108                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
109             }
110 
111             // we assume that either both iterators are to be passed to the
112             // semantic action or none iterator at all (i.e. it's not possible
113             // to have a lexer semantic action function taking one arguments).
114 
115             // semantic actions with 0 argument
116             template <typename F>
arg0_actionboost::spirit::lex::lexertl::detail::wrap_action117             static void arg0_action(F* f, Iterator&, Iterator&
118               , BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
119             {
120                 f();
121             }
122 
callboost::spirit::lex::lexertl::detail::wrap_action123             static FunctionType call(void (*f)())
124             {
125                 void (*pf)(void(*)(), Iterator&, Iterator&
126                   , BOOST_SCOPED_ENUM(pass_flags)&
127                   , IdType, Context const&) = &arg0_action;
128 
129                 using phoenix::arg_names::_1;
130                 using phoenix::arg_names::_2;
131                 using phoenix::arg_names::_3;
132                 using phoenix::arg_names::_4;
133                 using phoenix::arg_names::_5;
134                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
135             }
136         };
137 
138         // specialization allowing to skip wrapping for lexer types not
139         // supporting semantic actions
140         template <typename Iterator, typename Context, typename Idtype>
141         struct wrap_action<unused_type, Iterator, Context, Idtype>
142         {
143             // plain function objects are not touched at all
144             template <typename F>
callboost::spirit::lex::lexertl::detail::wrap_action145             static F const& call(F const& f)
146             {
147                 return f;
148             }
149         };
150     }
151 
152 }}}}
153 
154 #endif
155