1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3 
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #if !defined(BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_0347PM)
8 #define BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_0347PM
9 
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13 
14 #include <boost/spirit/home/support/meta_compiler.hpp>
15 #include <boost/spirit/home/qi/domain.hpp>
16 #include <boost/spirit/home/qi/parser.hpp>
17 #include <boost/spirit/home/support/string_traits.hpp>
18 #include <boost/type_traits/remove_reference.hpp>
19 #include <boost/utility/enable_if.hpp>
20 #include <boost/fusion/include/at.hpp>
21 
22 namespace boost { namespace spirit
23 {
24     template <typename T>
25     struct use_terminal<qi::domain, T
26       , typename enable_if<traits::is_parser<T> >::type> // enables parsers
27       : mpl::true_ {};
28 
29     namespace qi
30     {
31         template <typename T, typename Modifiers, typename Enable = void>
32         struct make_primitive // by default, return it as-is
33         {
34             typedef T result_type;
35 
36             template <typename T_>
operator ()boost::spirit::qi::make_primitive37             T_& operator()(T_& val, unused_type) const
38             {
39                 return val;
40             }
41 
42             template <typename T_>
operator ()boost::spirit::qi::make_primitive43             T_ const& operator()(T_ const& val, unused_type) const
44             {
45                 return val;
46             }
47         };
48 
49         template <typename Tag, typename Elements
50           , typename Modifiers, typename Enable = void>
51         struct make_composite;
52 
53         template <typename Directive, typename Body
54           , typename Modifiers, typename Enable = void>
55         struct make_directive
56         {
57             typedef Body result_type;
operator ()boost::spirit::qi::make_directive58             result_type operator()(unused_type, Body const& body, unused_type) const
59             {
60                 return body; // By default, a directive simply returns its subject
61             }
62         };
63     }
64 
65     // Qi primitive meta-compiler
66     template <>
67     struct make_component<qi::domain, proto::tag::terminal>
68     {
69         template <typename Sig>
70         struct result;
71 
72         template <typename This, typename Elements, typename Modifiers>
73         struct result<This(Elements, Modifiers)>
74         {
75             typedef typename qi::make_primitive<
76                 typename remove_const<typename Elements::car_type>::type,
77                 typename remove_reference<Modifiers>::type>::result_type
78             type;
79         };
80 
81         template <typename Elements, typename Modifiers>
82         typename result<make_component(Elements, Modifiers)>::type
operator ()boost::spirit::make_component83         operator()(Elements const& elements, Modifiers const& modifiers) const
84         {
85             typedef typename remove_const<typename Elements::car_type>::type term;
86             return qi::make_primitive<term, Modifiers>()(elements.car, modifiers);
87         }
88     };
89 
90     // Qi composite meta-compiler
91     template <typename Tag>
92     struct make_component<qi::domain, Tag>
93     {
94         template <typename Sig>
95         struct result;
96 
97         template <typename This, typename Elements, typename Modifiers>
98         struct result<This(Elements, Modifiers)>
99         {
100             typedef typename
101                 qi::make_composite<Tag, Elements,
102                 typename remove_reference<Modifiers>::type>::result_type
103             type;
104         };
105 
106         template <typename Elements, typename Modifiers>
107         typename result<make_component(Elements, Modifiers)>::type
operator ()boost::spirit::make_component108         operator()(Elements const& elements, Modifiers const& modifiers) const
109         {
110             return qi::make_composite<Tag, Elements, Modifiers>()(
111                 elements, modifiers);
112         }
113     };
114 
115     // Qi function meta-compiler
116     template <>
117     struct make_component<qi::domain, proto::tag::function>
118     {
119         template <typename Sig>
120         struct result;
121 
122         template <typename This, typename Elements, typename Modifiers>
123         struct result<This(Elements, Modifiers)>
124         {
125             typedef typename
126                 qi::make_composite<
127                     typename remove_const<typename Elements::car_type>::type,
128                     typename Elements::cdr_type,
129                     typename remove_reference<Modifiers>::type
130                 >::result_type
131             type;
132         };
133 
134         template <typename Elements, typename Modifiers>
135         typename result<make_component(Elements, Modifiers)>::type
operator ()boost::spirit::make_component136         operator()(Elements const& elements, Modifiers const& modifiers) const
137         {
138             return qi::make_composite<
139                 typename remove_const<typename Elements::car_type>::type,
140                 typename Elements::cdr_type,
141                 Modifiers>()(elements.cdr, modifiers);
142         }
143     };
144 
145     // Qi directive meta-compiler
146     template <>
147     struct make_component<qi::domain, tag::directive>
148     {
149         template <typename Sig>
150         struct result;
151 
152         template <typename This, typename Elements, typename Modifiers>
153         struct result<This(Elements, Modifiers)>
154         {
155             typedef typename
156                 qi::make_directive<
157                     typename remove_const<typename Elements::car_type>::type,
158                     typename remove_const<typename Elements::cdr_type::car_type>::type,
159                     typename remove_reference<Modifiers>::type
160                 >::result_type
161             type;
162         };
163 
164         template <typename Elements, typename Modifiers>
165         typename result<make_component(Elements, Modifiers)>::type
operator ()boost::spirit::make_component166         operator()(Elements const& elements, Modifiers const& modifiers) const
167         {
168             return qi::make_directive<
169                 typename remove_const<typename Elements::car_type>::type,
170                 typename remove_const<typename Elements::cdr_type::car_type>::type,
171                 Modifiers>()(elements.car, elements.cdr.car, modifiers);
172         }
173     };
174 
175 }}
176 
177 #endif
178