1 /*============================================================================== 2 Copyright (c) 2005-2010 Joel de Guzman 3 Copyright (c) 2010 Thomas Heller 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #ifndef BOOST_PHOENIX_CORE_TERMINAL_HPP 9 #define BOOST_PHOENIX_CORE_TERMINAL_HPP 10 11 #include <boost/phoenix/core/limits.hpp> 12 #include <boost/is_placeholder.hpp> 13 #include <boost/phoenix/core/actor.hpp> 14 #include <boost/phoenix/core/meta_grammar.hpp> 15 #include <boost/phoenix/core/terminal_fwd.hpp> 16 #include <boost/proto/matches.hpp> 17 #include <boost/proto/transform/lazy.hpp> 18 #include <boost/proto/functional/fusion/at.hpp> 19 #include <boost/type_traits/remove_pointer.hpp> 20 21 #define BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL(Template, Terminal, IsNullary, EvalFun)\ 22 namespace boost { namespace phoenix \ 23 { \ 24 namespace result_of \ 25 { \ 26 Template \ 27 struct is_nullary< \ 28 custom_terminal< \ 29 Terminal \ 30 > \ 31 > \ 32 : IsNullary \ 33 {}; \ 34 } \ 35 Template \ 36 struct is_custom_terminal<Terminal >: mpl::true_ {}; \ 37 \ 38 Template \ 39 struct custom_terminal<Terminal > : proto::call<EvalFun > {}; \ 40 }} \ 41 /**/ 42 43 namespace boost { namespace phoenix 44 { 45 template <typename T, typename Dummy> 46 struct is_custom_terminal 47 : mpl::false_ {}; 48 49 template <typename T, typename Dummy> 50 struct custom_terminal; 51 52 namespace tag { 53 struct terminal /*: public proto::tag::terminal */ {}; 54 } 55 56 namespace expression 57 { 58 template <typename T, template <typename> class Actor = actor> 59 struct terminal 60 : proto::terminal<T> 61 { 62 typedef 63 proto::basic_expr< 64 proto::tag::terminal 65 // tag::terminal //cannot change to use phoenix tag - breaks code. 66 , proto::term<T> 67 , 0 68 > 69 base_type; 70 typedef Actor<base_type> type; 71 makeboost::phoenix::expression::terminal72 static const type make(T const& t) 73 { 74 // ?? Should the next line be Actor not actor which is the default? 75 actor<base_type> const e = {base_type::make(t)}; 76 //Actor<base_type> const e = {base_type::make(t)}; 77 return e; 78 } 79 }; 80 } 81 82 namespace rule 83 { 84 struct argument 85 : proto::if_<boost::is_placeholder<proto::_value>()> 86 {}; 87 88 struct custom_terminal 89 : proto::if_<boost::phoenix::is_custom_terminal<proto::_value>()> 90 {}; 91 92 struct terminal 93 : proto::terminal<proto::_> 94 {}; 95 } 96 97 template <typename Dummy> 98 struct meta_grammar::case_<proto::tag::terminal, Dummy> 99 : proto::or_< 100 enable_rule<rule::argument , Dummy> 101 , enable_rule<rule::custom_terminal, Dummy> 102 , enable_rule<rule::terminal , Dummy> 103 > 104 {}; 105 106 template <typename Dummy> 107 struct default_actions::when<rule::custom_terminal, Dummy> 108 : proto::lazy< 109 custom_terminal<proto::_value>( 110 proto::_value 111 , _context 112 ) 113 > 114 {}; 115 116 namespace detail 117 { 118 template <typename N> 119 struct placeholder_idx 120 : mpl::int_<N::value> 121 {}; 122 } 123 124 template <typename Grammar> 125 struct default_actions::when<rule::argument, Grammar> 126 : proto::call< 127 proto::functional::at( 128 _env 129 , proto::make< 130 detail::placeholder_idx< 131 proto::make< 132 boost::is_placeholder<proto::_value>() 133 > 134 >() 135 > 136 ) 137 > 138 {}; 139 }} 140 141 #endif 142