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/home/support/attributes.hpp>
17 #include <boost/spirit/home/lex/lexer/pass_flags.hpp>
18 #include <boost/phoenix/core/argument.hpp>
19 #include <boost/phoenix/bind.hpp>
20 
21 ///////////////////////////////////////////////////////////////////////////////
22 namespace boost { namespace spirit { namespace lex { namespace lexertl
23 {
24     namespace detail
25     {
26         template <typename FunctionType, typename Iterator, typename Context
27           , typename IdType>
28         struct wrap_action
29         {
30             // plain functions with 5 arguments, function objects (including
31             // phoenix actors) are not touched at all
32             template <typename F>
callboost::spirit::lex::lexertl::detail::wrap_action33             static FunctionType call(F const& f)
34             {
35                 return f;
36             }
37 
38             // semantic actions with 4 arguments
39             template <typename F>
arg4_actionboost::spirit::lex::lexertl::detail::wrap_action40             static void arg4_action(F* f, Iterator& start, Iterator& end
41               , BOOST_SCOPED_ENUM(pass_flags)& pass, IdType& id
42               , Context const&)
43             {
44                 f(start, end, pass, id);
45             }
46 
47             template <typename A0, typename A1, typename A2, typename A3>
callboost::spirit::lex::lexertl::detail::wrap_action48             static FunctionType call(void (*f)(A0, A1, A2, A3))
49             {
50                 void (*pf)(void(*)(A0, A1, A2, A3)
51                   , Iterator&, Iterator&, BOOST_SCOPED_ENUM(pass_flags)&
52                   , IdType&, Context const&) = &wrap_action::arg4_action;
53 
54                 using phoenix::arg_names::_1;
55                 using phoenix::arg_names::_2;
56                 using phoenix::arg_names::_3;
57                 using phoenix::arg_names::_4;
58                 using phoenix::arg_names::_5;
59                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
60             }
61 
62             // semantic actions with 3 arguments
63             template <typename F>
arg3_actionboost::spirit::lex::lexertl::detail::wrap_action64             static void arg3_action(F* f, Iterator& start, Iterator& end
65               , BOOST_SCOPED_ENUM(pass_flags)& pass, IdType
66               , Context const&)
67             {
68                 f(start, end, pass);
69             }
70 
71             template <typename A0, typename A1, typename A2>
callboost::spirit::lex::lexertl::detail::wrap_action72             static FunctionType call(void (*f)(A0, A1, A2))
73             {
74                 void (*pf)(void(*)(A0, A1, A2), Iterator&, Iterator&
75                   , BOOST_SCOPED_ENUM(pass_flags)&, IdType
76                   , Context const&) = &wrap_action::arg3_action;
77 
78                 using phoenix::arg_names::_1;
79                 using phoenix::arg_names::_2;
80                 using phoenix::arg_names::_3;
81                 using phoenix::arg_names::_4;
82                 using phoenix::arg_names::_5;
83                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
84             }
85 
86             // semantic actions with 2 arguments
87             template <typename F>
arg2_actionboost::spirit::lex::lexertl::detail::wrap_action88             static void arg2_action(F* f, Iterator& start, Iterator& end
89               , BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
90             {
91                 f (start, end);
92             }
93 
94             template <typename A0, typename A1>
callboost::spirit::lex::lexertl::detail::wrap_action95             static FunctionType call(void (*f)(A0, A1))
96             {
97                 void (*pf)(void(*)(A0, A1), Iterator&, Iterator&
98                   , BOOST_SCOPED_ENUM(pass_flags)&
99                   , IdType, Context const&) = &wrap_action::arg2_action;
100 
101                 using phoenix::arg_names::_1;
102                 using phoenix::arg_names::_2;
103                 using phoenix::arg_names::_3;
104                 using phoenix::arg_names::_4;
105                 using phoenix::arg_names::_5;
106                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
107             }
108 
109             // we assume that either both iterators are to be passed to the
110             // semantic action or none iterator at all (i.e. it's not possible
111             // to have a lexer semantic action function taking one arguments).
112 
113             // semantic actions with 0 argument
114             template <typename F>
arg0_actionboost::spirit::lex::lexertl::detail::wrap_action115             static void arg0_action(F* f, Iterator&, Iterator&
116               , BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
117             {
118                 f();
119             }
120 
callboost::spirit::lex::lexertl::detail::wrap_action121             static FunctionType call(void (*f)())
122             {
123                 void (*pf)(void(*)(), Iterator&, Iterator&
124                   , BOOST_SCOPED_ENUM(pass_flags)&
125                   , IdType, Context const&) = &arg0_action;
126 
127                 using phoenix::arg_names::_1;
128                 using phoenix::arg_names::_2;
129                 using phoenix::arg_names::_3;
130                 using phoenix::arg_names::_4;
131                 using phoenix::arg_names::_5;
132                 return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
133             }
134         };
135 
136         // specialization allowing to skip wrapping for lexer types not
137         // supporting semantic actions
138         template <typename Iterator, typename Context, typename Idtype>
139         struct wrap_action<unused_type, Iterator, Context, Idtype>
140         {
141             // plain function objects are not touched at all
142             template <typename F>
callboost::spirit::lex::lexertl::detail::wrap_action143             static F const& call(F const& f)
144             {
145                 return f;
146             }
147         };
148     }
149 
150 }}}}
151 
152 #endif
153