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