]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 <string> | |
22 | ||
23 | #if !defined(BOOST_SPIRIT_X3_NO_RTTI) | |
24 | #include <typeinfo> | |
25 | #endif | |
26 | ||
27 | namespace boost { namespace spirit { namespace x3 | |
28 | { | |
29 | template <typename Subject, typename Action> | |
30 | struct action; | |
31 | ||
32 | template <typename Subject, typename Handler> | |
33 | struct guard; | |
34 | ||
35 | struct parser_base {}; | |
36 | struct parser_id; | |
37 | ||
38 | template <typename Derived> | |
39 | struct parser : parser_base | |
40 | { | |
41 | typedef Derived derived_type; | |
42 | static bool const handles_container = false; | |
43 | static bool const is_pass_through_unary = false; | |
44 | static bool const has_action = false; | |
45 | ||
46 | Derived const& derived() const | |
47 | { | |
48 | return *static_cast<Derived const*>(this); | |
49 | } | |
50 | ||
51 | template <typename Action> | |
52 | action<Derived, Action> | |
53 | operator[](Action f) const | |
54 | { | |
55 | return action<Derived, Action>(this->derived(), f); | |
56 | } | |
57 | ||
58 | template <typename Handler> | |
59 | guard<Derived, Handler> | |
60 | on_error(Handler f) const | |
61 | { | |
62 | return guard<Derived, Handler>(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 | ||
76 | unary_parser(Subject const& subject) | |
77 | : subject(subject) {} | |
78 | ||
79 | 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 | ||
93 | binary_parser(Left const& left, Right const& right) | |
94 | : left(left), right(right) {} | |
95 | ||
96 | 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 | ||
124 | 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; | |
144 | static 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; | |
156 | static 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; | |
167 | static type call(parser<Derived> const& p) | |
168 | { | |
169 | return p.derived(); | |
170 | } | |
171 | }; | |
172 | } | |
173 | ||
174 | template <typename T> | |
175 | inline typename extension::as_parser<T>::type | |
176 | as_parser(T const& x) | |
177 | { | |
178 | return extension::as_parser<T>::call(x); | |
179 | } | |
180 | ||
181 | template <typename Derived> | |
182 | inline Derived const& | |
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; | |
202 | 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> | |
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 |