• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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