• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2014 Joel de Guzman
3     Copyright (c) 2013 Agustin Berge
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 #if !defined(BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM)
9 #define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM
10 
11 #include <boost/mpl/bool.hpp>
12 #include <boost/type_traits/is_base_of.hpp>
13 #include <boost/type_traits/remove_cv.hpp>
14 #include <boost/type_traits/remove_reference.hpp>
15 #include <boost/utility/declval.hpp>
16 #include <boost/utility/enable_if.hpp>
17 #include <boost/spirit/home/x3/support/unused.hpp>
18 #include <boost/spirit/home/x3/support/context.hpp>
19 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
20 #include <boost/spirit/home/x3/support/utility/sfinae.hpp>
21 #include <boost/core/ignore_unused.hpp>
22 #include <boost/assert.hpp>
23 #include <string>
24 
25 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
26 #include <typeinfo>
27 #endif
28 
29 namespace boost { namespace spirit { namespace x3
30 {
31     template <typename Subject, typename Action>
32     struct action;
33 
34     template <typename Subject, typename Handler>
35     struct guard;
36 
37     struct parser_base {};
38     struct parser_id;
39 
40     template <typename Derived>
41     struct parser : parser_base
42     {
43         typedef Derived derived_type;
44         static bool const handles_container = false;
45         static bool const is_pass_through_unary = false;
46         static bool const has_action = false;
47 
derivedboost::spirit::x3::parser48         constexpr Derived const& derived() const
49         {
50             return *static_cast<Derived const*>(this);
51         }
52 
53         template <typename Action>
operator []boost::spirit::x3::parser54         constexpr action<Derived, Action> operator[](Action f) const
55         {
56             return { this->derived(), f };
57         }
58 
59         template <typename Handler>
on_errorboost::spirit::x3::parser60         constexpr guard<Derived, Handler> on_error(Handler f) const
61         {
62             return { this->derived(), f };
63         }
64     };
65 
66     struct unary_category;
67     struct binary_category;
68 
69     template <typename Subject, typename Derived>
70     struct unary_parser : parser<Derived>
71     {
72         typedef unary_category category;
73         typedef Subject subject_type;
74         static bool const has_action = Subject::has_action;
75 
unary_parserboost::spirit::x3::unary_parser76         constexpr unary_parser(Subject const& subject)
77             : subject(subject) {}
78 
get_unaryboost::spirit::x3::unary_parser79         unary_parser const& get_unary() const { return *this; }
80 
81         Subject subject;
82     };
83 
84     template <typename Left, typename Right, typename Derived>
85     struct binary_parser : parser<Derived>
86     {
87         typedef binary_category category;
88         typedef Left left_type;
89         typedef Right right_type;
90         static bool const has_action =
91             left_type::has_action || right_type::has_action;
92 
binary_parserboost::spirit::x3::binary_parser93         constexpr binary_parser(Left const& left, Right const& right)
94             : left(left), right(right) {}
95 
get_binaryboost::spirit::x3::binary_parser96         binary_parser const& get_binary() const { return *this; }
97 
98         Left left;
99         Right right;
100     };
101 
102     ///////////////////////////////////////////////////////////////////////////
103     // as_parser: convert a type, T, into a parser.
104     ///////////////////////////////////////////////////////////////////////////
105     namespace extension
106     {
107         namespace detail
108         {
109             namespace as_parser_guard
110             {
111                 void as_spirit_parser(...);
112 
113                 template<typename T, typename R =
114                     decltype(as_spirit_parser(boost::declval<T const&>()))>
115                 struct deduce_as_parser
116                 {
117                     typedef R type;
118                     typedef typename
119                         boost::remove_cv<
120                             typename boost::remove_reference<R>::type
121                         >::type
122                     value_type;
123 
callboost::spirit::x3::extension::detail::as_parser_guard::deduce_as_parser124                     static type call(T const& v)
125                     {
126                         return as_spirit_parser(v);
127                     }
128                 };
129                 template<typename T>
130                 struct deduce_as_parser<T, void>
131                 {};
132             }
133             using as_parser_guard::deduce_as_parser;
134         }
135 
136         template <typename T, typename Enable = void>
137         struct as_parser : detail::deduce_as_parser<T> {};
138 
139         template <>
140         struct as_parser<unused_type>
141         {
142             typedef unused_type type;
143             typedef unused_type value_type;
callboost::spirit::x3::extension::as_parser144             static constexpr type call(unused_type)
145             {
146                 return unused;
147             }
148         };
149 
150         template <typename Derived>
151         struct as_parser<Derived
152             , typename enable_if<is_base_of<parser_base, Derived>>::type>
153         {
154             typedef Derived const& type;
155             typedef Derived value_type;
callboost::spirit::x3::extension::as_parser156             static constexpr type call(Derived const& p)
157             {
158                 return p;
159             }
160         };
161 
162         template <typename Derived>
163         struct as_parser<parser<Derived>>
164         {
165             typedef Derived const& type;
166             typedef Derived value_type;
callboost::spirit::x3::extension::as_parser167             static constexpr type call(parser<Derived> const& p)
168             {
169                 return p.derived();
170             }
171         };
172     }
173 
174     template <typename T>
175     constexpr typename extension::as_parser<T>::type
as_parser(T const & x)176     as_parser(T const& x)
177     {
178         return extension::as_parser<T>::call(x);
179     }
180 
181     template <typename Derived>
182     constexpr Derived const&
as_parser(parser<Derived> const & p)183     as_parser(parser<Derived> const& p)
184     {
185         return p.derived();
186     }
187 
188     ///////////////////////////////////////////////////////////////////////////
189     // The main what function
190     //
191     // Note: unlike Spirit2, spirit parsers are no longer required to have a
192     // "what" member function. In X3, we specialize the get_info struct
193     // below where needed. If a specialization is not provided, the default
194     // below will be used. The default "what" result will be the typeid
195     // name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise
196     // "undefined"
197     ///////////////////////////////////////////////////////////////////////////
198     template <typename Parser, typename Enable = void>
199     struct get_info
200     {
201         typedef std::string result_type;
operator ()boost::spirit::x3::get_info202         std::string operator()(Parser const&) const
203         {
204 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
205             return typeid(Parser).name();
206 #else
207             return "undefined";
208 #endif
209         }
210     };
211 
212     template <typename Parser>
what(Parser const & p)213     std::string what(Parser const& p)
214     {
215         return get_info<Parser>()(p);
216     }
217 }}}
218 
219 namespace boost { namespace spirit { namespace x3 { namespace traits
220 {
221     template <typename Subject, typename Derived, typename Context>
222     struct has_attribute<x3::unary_parser<Subject, Derived>, Context>
223         : has_attribute<Subject, Context> {};
224 
225     template <typename Left, typename Right, typename Derived, typename Context>
226     struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context>
227         : mpl::bool_<has_attribute<Left, Context>::value ||
228                 has_attribute<Right, Context>::value> {};
229 }}}}
230 
231 #endif
232