1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 Copyright (c) 2001-2011 Hartmut Kaiser 4 Copyright (c) 2011 Thomas Heller 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_ARGUMENT_FEBRUARY_17_2007_0339PM) 10 #define BOOST_SPIRIT_ARGUMENT_FEBRUARY_17_2007_0339PM 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/preprocessor/repetition/repeat_from_to.hpp> 17 #include <boost/preprocessor/arithmetic/inc.hpp> 18 #include <boost/spirit/home/support/assert_msg.hpp> 19 #include <boost/spirit/home/support/limits.hpp> 20 #include <boost/fusion/include/at.hpp> 21 #include <boost/fusion/include/size.hpp> 22 #include <boost/mpl/size.hpp> 23 #include <boost/mpl/at.hpp> 24 #include <boost/phoenix/core/actor.hpp> 25 #include <boost/phoenix/core/argument.hpp> 26 #include <boost/phoenix/core/terminal.hpp> 27 #include <boost/phoenix/core/v2_eval.hpp> 28 #include <boost/proto/proto_fwd.hpp> // for transform placeholders 29 30 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 31 32 #define SPIRIT_DECLARE_ARG(z, n, data) \ 33 typedef phoenix::actor<argument<n> > \ 34 BOOST_PP_CAT(BOOST_PP_CAT(_, BOOST_PP_INC(n)), _type); \ 35 phoenix::actor<argument<n> > const \ 36 BOOST_PP_CAT(_, BOOST_PP_INC(n)) = \ 37 BOOST_PP_CAT(BOOST_PP_CAT(_, BOOST_PP_INC(n)), _type)(); \ 38 /***/ 39 40 #define SPIRIT_USING_ARGUMENT(z, n, data) \ 41 using spirit::BOOST_PP_CAT(BOOST_PP_CAT(_, n), _type); \ 42 using spirit::BOOST_PP_CAT(_, n); \ 43 /***/ 44 45 #else 46 47 #define SPIRIT_DECLARE_ARG(z, n, data) \ 48 typedef phoenix::actor<argument<n> > \ 49 BOOST_PP_CAT(BOOST_PP_CAT(_, BOOST_PP_INC(n)), _type); \ 50 /***/ 51 52 #define SPIRIT_USING_ARGUMENT(z, n, data) \ 53 using spirit::BOOST_PP_CAT(BOOST_PP_CAT(_, n), _type); \ 54 /***/ 55 56 #endif 57 58 namespace boost { namespace spirit 59 { 60 template <int N> 61 struct argument; 62 63 template <typename Dummy> 64 struct attribute_context; 65 }} 66 67 BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL( 68 template <int N> 69 , boost::spirit::argument<N> 70 , mpl::false_ // is not nullary 71 , v2_eval( 72 proto::make< 73 boost::spirit::argument<N>() 74 > 75 , proto::call< 76 functional::env(proto::_state) 77 > 78 ) 79 ) 80 81 BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL( 82 template <typename Dummy> 83 , boost::spirit::attribute_context<Dummy> 84 , mpl::false_ // is not nullary 85 , v2_eval( 86 proto::make< 87 boost::spirit::attribute_context<Dummy>() 88 > 89 , proto::call< 90 functional::env(proto::_state) 91 > 92 ) 93 ) 94 95 namespace boost { namespace spirit 96 { 97 namespace result_of 98 { 99 template <typename Sequence, int N> 100 struct get_arg 101 { 102 typedef typename 103 fusion::result_of::size<Sequence>::type 104 sequence_size; 105 106 // report invalid argument not found (N is out of bounds) 107 BOOST_SPIRIT_ASSERT_MSG( 108 (N < sequence_size::value), 109 index_is_out_of_bounds, ()); 110 111 typedef typename 112 fusion::result_of::at_c<Sequence, N>::type 113 type; 114 callboost::spirit::result_of::get_arg115 static type call(Sequence& seq) 116 { 117 return fusion::at_c<N>(seq); 118 } 119 }; 120 121 template <typename Sequence, int N> 122 struct get_arg<Sequence&, N> : get_arg<Sequence, N> 123 { 124 }; 125 } 126 127 template <int N, typename T> 128 typename result_of::get_arg<T, N>::type get_arg(T & val)129 get_arg(T& val) 130 { 131 return result_of::get_arg<T, N>::call(val); 132 } 133 134 template <typename> 135 struct attribute_context 136 { 137 typedef mpl::true_ no_nullary; 138 139 template <typename Env> 140 struct result 141 { 142 // FIXME: is this remove_const really necessary? 143 typedef typename 144 remove_const< 145 typename mpl::at_c<typename Env::args_type, 0>::type 146 >::type 147 type; 148 }; 149 150 template <typename Env> 151 typename result<Env>::type evalboost::spirit::attribute_context152 eval(Env const& env) const 153 { 154 return fusion::at_c<0>(env.args()); 155 } 156 }; 157 158 template <int N> 159 struct argument 160 { 161 typedef mpl::true_ no_nullary; 162 163 template <typename Env> 164 struct result 165 { 166 typedef typename 167 mpl::at_c<typename Env::args_type, 0>::type 168 arg_type; 169 170 typedef typename result_of::get_arg<arg_type, N>::type type; 171 }; 172 173 template <typename Env> 174 typename result<Env>::type evalboost::spirit::argument175 eval(Env const& env) const 176 { 177 return get_arg<N>(fusion::at_c<0>(env.args())); 178 } 179 }; 180 181 // _0 refers to the whole attribute as generated by the lhs parser 182 typedef phoenix::actor<attribute_context<void> > _0_type; 183 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 184 _0_type const _0 = _0_type(); 185 #endif 186 187 // _1, _2, ... refer to the attributes of the single components the lhs 188 // parser is composed of 189 typedef phoenix::actor<argument<0> > _1_type; 190 typedef phoenix::actor<argument<1> > _2_type; 191 typedef phoenix::actor<argument<2> > _3_type; 192 193 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 194 _1_type const _1 = _1_type(); 195 _2_type const _2 = _2_type(); 196 _3_type const _3 = _3_type(); 197 #endif 198 199 // '_pass' may be used to make a match fail in retrospective 200 typedef phoenix::arg_names::_3_type _pass_type; 201 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 202 _pass_type const _pass = _pass_type(); 203 #endif 204 205 // Bring in the rest of the arguments and attributes (_4 .. _N+1), using PP 206 BOOST_PP_REPEAT_FROM_TO( 207 3, SPIRIT_ARGUMENTS_LIMIT, SPIRIT_DECLARE_ARG, _) 208 209 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 210 // You can bring these in with the using directive 211 // without worrying about bringing in too much. 212 namespace labels 213 { 214 BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _) 215 } 216 #endif 217 218 }} 219 220 #undef SPIRIT_DECLARE_ARG 221 #endif 222