]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/test/qi/terminal_ex.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / test / qi / terminal_ex.cpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2008 Francois Barel
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=============================================================================*/
7c673cae
FG
7#include <boost/type_traits/is_same.hpp>
8
9#include <boost/spirit/include/qi_operator.hpp>
10#include <boost/spirit/include/qi_char.hpp>
1e59de90
TL
11#include <boost/phoenix/core.hpp>
12#include <boost/phoenix/operator.hpp>
7c673cae
FG
13
14#include <iterator>
15#include "test.hpp"
16
17
18namespace testns
19{
20
21 BOOST_SPIRIT_TERMINAL_NAME_EX( ops, ops_type )
22
23
24 ///////////////////////////////////////////////////////////////////////////
25 // Parsers
26 ///////////////////////////////////////////////////////////////////////////
27
28 template <typename T1>
29 struct ops_1_parser
30 : boost::spirit::qi::primitive_parser<ops_1_parser<T1> >
31 {
32 ops_1_parser(T1 t1)
33 : t1(t1)
34 {}
35
36 template <typename Context, typename Iterator>
37 struct attribute
38 {
39 typedef int type; // Number of parsed chars.
40 };
41
42 template <typename Iterator, typename Context
43 , typename Skipper, typename Attribute>
44 bool parse(Iterator& first, Iterator const& last
45 , Context& /*context*/, Skipper const& skipper
46 , Attribute& attr) const
47 {
48 boost::spirit::qi::skip_over(first, last, skipper);
49
50 int count = 0;
51
52 Iterator it = first;
53 typedef typename std::iterator_traits<Iterator>::value_type Char;
54 for (T1 t = 0; t < t1; t++, count++)
55 if (it == last || *it++ != Char('+'))
56 return false;
57
58 boost::spirit::traits::assign_to(count, attr);
59 first = it;
60 return true;
61 }
62
63 template <typename Context>
64 boost::spirit::qi::info what(Context& /*context*/) const
65 {
66 return boost::spirit::qi::info("ops_1");
67 }
68
69 const T1 t1;
70
7c673cae 71 // silence MSVC warning C4512: assignment operator could not be generated
92f5a8d4 72 BOOST_DELETED_FUNCTION(ops_1_parser& operator= (ops_1_parser const&));
7c673cae
FG
73 };
74
75 template <typename T1, typename T2>
76 struct ops_2_parser
77 : boost::spirit::qi::primitive_parser<ops_2_parser<T1, T2> >
78 {
79 ops_2_parser(T1 t1, T2 t2)
80 : t1(t1)
81 , t2(t2)
82 {}
83
84 template <typename Context, typename Iterator>
85 struct attribute
86 {
87 typedef int type; // Number of parsed chars.
88 };
89
90 template <typename Iterator, typename Context
91 , typename Skipper, typename Attribute>
92 bool parse(Iterator& first, Iterator const& last
93 , Context& /*context*/, Skipper const& skipper
94 , Attribute& attr) const
95 {
96 boost::spirit::qi::skip_over(first, last, skipper);
97
98 int count = 0;
99
100 Iterator it = first;
101 typedef typename std::iterator_traits<Iterator>::value_type Char;
102 for (T1 t = 0; t < t1; t++, count++)
103 if (it == last || *it++ != Char('+'))
104 return false;
105 for (T2 t = 0; t < t2; t++, count++)
106 if (it == last || *it++ != Char('-'))
107 return false;
108
109 boost::spirit::traits::assign_to(count, attr);
110 first = it;
111 return true;
112 }
113
114 template <typename Context>
115 boost::spirit::qi::info what(Context& /*context*/) const
116 {
117 return boost::spirit::qi::info("ops_2");
118 }
119
120 const T1 t1;
121 const T2 t2;
122
7c673cae 123 // silence MSVC warning C4512: assignment operator could not be generated
92f5a8d4 124 BOOST_DELETED_FUNCTION(ops_2_parser& operator= (ops_2_parser const&));
7c673cae
FG
125 };
126
127 template <typename T1, typename T2, typename T3>
128 struct ops_3_parser
129 : boost::spirit::qi::primitive_parser<ops_3_parser<T1, T2, T3> >
130 {
131 ops_3_parser(T1 t1, T2 t2, T3 t3)
132 : t1(t1)
133 , t2(t2)
134 , t3(t3)
135 {}
136
137 template <typename Context, typename Iterator>
138 struct attribute
139 {
140 typedef int type; // Number of parsed chars.
141 };
142
143 template <typename Iterator, typename Context
144 , typename Skipper, typename Attribute>
145 bool parse(Iterator& first, Iterator const& last
146 , Context& /*context*/, Skipper const& skipper
147 , Attribute& attr) const
148 {
149 boost::spirit::qi::skip_over(first, last, skipper);
150
151 int count = 0;
152
153 Iterator it = first;
154 typedef typename std::iterator_traits<Iterator>::value_type Char;
155 for (T1 t = 0; t < t1; t++, count++)
156 if (it == last || *it++ != Char('+'))
157 return false;
158 for (T2 t = 0; t < t2; t++, count++)
159 if (it == last || *it++ != Char('-'))
160 return false;
161 for (T3 t = 0; t < t3; t++, count++)
162 if (it == last || *it++ != Char('*'))
163 return false;
164
165 boost::spirit::traits::assign_to(count, attr);
166 first = it;
167 return true;
168 }
169
170 template <typename Context>
171 boost::spirit::qi::info what(Context& /*context*/) const
172 {
173 return boost::spirit::qi::info("ops_3");
174 }
175
176 const T1 t1;
177 const T2 t2;
178 const T3 t3;
179
7c673cae 180 // silence MSVC warning C4512: assignment operator could not be generated
92f5a8d4 181 BOOST_DELETED_FUNCTION(ops_3_parser& operator= (ops_3_parser const&));
7c673cae
FG
182 };
183
184}
185
186
187namespace boost { namespace spirit
188{
189
190 ///////////////////////////////////////////////////////////////////////////
191 // Enablers
192 ///////////////////////////////////////////////////////////////////////////
193
194 template <typename T1>
195 struct use_terminal<qi::domain
196 , terminal_ex<testns::tag::ops, fusion::vector1<T1> > >
197 : mpl::true_ {};
198
199 template <typename T1, typename T2>
200 struct use_terminal<qi::domain
201 , terminal_ex<testns::tag::ops, fusion::vector2<T1, T2> > >
202 : mpl::true_ {};
203
204 template <typename T1, typename T2, typename T3>
205 struct use_terminal<qi::domain
206 , terminal_ex<testns::tag::ops, fusion::vector3<T1, T2, T3> > >
207 : mpl::true_ {};
208
209 template <>
210 struct use_lazy_terminal<qi::domain, testns::tag::ops, 1>
211 : mpl::true_ {};
212
213 template <>
214 struct use_lazy_terminal<qi::domain, testns::tag::ops, 2>
215 : mpl::true_ {};
216
217 template <>
218 struct use_lazy_terminal<qi::domain, testns::tag::ops, 3>
219 : mpl::true_ {};
220
221}}
222
223namespace boost { namespace spirit { namespace qi
224{
225
226 ///////////////////////////////////////////////////////////////////////////
227 // Parser generators: make_xxx function (objects)
228 ///////////////////////////////////////////////////////////////////////////
229
230 template <typename Modifiers, typename T1>
231 struct make_primitive<
232 terminal_ex<testns::tag::ops, fusion::vector1<T1> >
233 , Modifiers>
234 {
235 typedef testns::ops_1_parser<T1> result_type;
236 template <typename Terminal>
237 result_type operator()(const Terminal& term, unused_type) const
238 {
239 return result_type(
240 fusion::at_c<0>(term.args)
241 );
242 }
243 };
244
245 template <typename Modifiers, typename T1, typename T2>
246 struct make_primitive<
247 terminal_ex<testns::tag::ops, fusion::vector2<T1, T2> >
248 , Modifiers>
249 {
250 typedef testns::ops_2_parser<T1, T2> result_type;
251 template <typename Terminal>
252 result_type operator()(const Terminal& term, unused_type) const
253 {
254 return result_type(
255 fusion::at_c<0>(term.args)
256 , fusion::at_c<1>(term.args)
257 );
258 }
259 };
260
261 template <typename Modifiers, typename T1, typename T2, typename T3>
262 struct make_primitive<
263 terminal_ex<testns::tag::ops, fusion::vector3<T1, T2, T3> >
264 , Modifiers>
265 {
266 typedef testns::ops_3_parser<T1, T2, T3> result_type;
267 template <typename Terminal>
268 result_type operator()(const Terminal& term, unused_type) const
269 {
270 return result_type(
271 fusion::at_c<0>(term.args)
272 , fusion::at_c<1>(term.args)
273 , fusion::at_c<2>(term.args)
274 );
275 }
276 };
277
278}}}
279
280
281namespace testns
282{
283 template <typename T1, typename T>
284 void check_type_1(const T& /*t*/)
285 {
286 BOOST_STATIC_ASSERT(( boost::is_same<T
287 , typename boost::spirit::terminal<testns::tag::ops>::result<T1>::type >::value ));
288 }
289
290 template <typename T1, typename T2, typename T>
291 void check_type_2(const T& /*t*/)
292 {
293 BOOST_STATIC_ASSERT(( boost::is_same<T
294 , typename boost::spirit::terminal<testns::tag::ops>::result<T1, T2>::type >::value ));
295 }
296
297 template <typename T1, typename T2, typename T3, typename T>
298 void check_type_3(const T& /*t*/)
299 {
300 BOOST_STATIC_ASSERT(( boost::is_same<T
301 , typename boost::spirit::terminal<testns::tag::ops>::result<T1, T2, T3>::type >::value ));
302 }
303}
304
305
306int
307main()
308{
309 using spirit_test::test_attr;
310 using spirit_test::test;
311
312 using testns::ops;
313 using testns::check_type_1;
314 using testns::check_type_2;
315 using testns::check_type_3;
316
317 { // immediate args
318 int c = 0;
319#define IP1 ops(2)
320 check_type_1<int>(IP1);
321 BOOST_TEST(test_attr("++/", IP1 >> '/', c) && c == 2);
322
323 c = 0;
324#define IP2 ops(2, 3)
325 check_type_2<int, int>(IP2);
326 BOOST_TEST(test_attr("++---/", IP2 >> '/', c) && c == 5);
327
328 c = 0;
329#define IP3 ops(2, 3, 4)
330 check_type_3<int, int, int>(IP3);
331 BOOST_TEST(!test("++---***/", IP3 >> '/'));
332#define IP4 ops(2, 3, 4)
333 check_type_3<int, int, int>(IP4);
334 BOOST_TEST(test_attr("++---****/", IP4 >> '/', c) && c == 9);
335 }
336
337 using boost::phoenix::val;
338 using boost::phoenix::actor;
339 using boost::phoenix::expression::value;
340
341 { // all lazy args
342 int c = 0;
343#define LP1 ops(val(1))
344 check_type_1<value<int>::type>(LP1);
345 BOOST_TEST(test_attr("+/", LP1 >> '/', c) && c == 1);
346
347 c = 0;
348#define LP2 ops(val(1), val(4))
349 check_type_2<value<int>::type, value<int>::type>(LP2);
350 BOOST_TEST(test_attr("+----/", LP2 >> '/', c) && c == 5);
351
352 c = 0;
353#define LP3 ops(val((char)2), val(3.), val(4))
354 check_type_3<value<char>::type, value<double>::type, value<int>::type>(LP3);
355 BOOST_TEST(!test("++---***/", LP3 >> '/'));
356#define LP4 ops(val(1), val(2), val(3))
357 check_type_3<value<int>::type, value<int>::type, value<int>::type>(LP4);
358 BOOST_TEST(test_attr("+--***/", LP4 >> '/', c) && c == 6);
359 }
360
361 { // mixed immediate and lazy args
362 namespace fusion = boost::fusion;
363 namespace phx = boost::phoenix;
364
365 int c = 0;
366#define MP1 ops(val(3), 2)
367 check_type_2<value<int>::type, int>(MP1);
368 BOOST_TEST(test_attr("+++--/", MP1 >> '/', c) && c == 5);
369
370 c = 0;
371#define MP2 ops(4, val(1))
372 check_type_2<int, value<int>::type>(MP2);
373 BOOST_TEST(test_attr("++++-/", MP2 >> '/', c) && c == 5);
374
375 c = 0;
376#define MP3 ops(2, val(2), val(2))
377 check_type_3<int, value<int>::type, value<int>::type>(MP3);
378 BOOST_TEST(!test("++-**/", MP3 >> '/'));
379#define MP4 ops(2, val(2), 2)
380 check_type_3<int, value<int>::type, int>(MP4);
381 BOOST_TEST(test_attr("++--**/", MP4 >> '/', c) && c == 6);
382
383 c = 0;
384#define MP5 ops(val(5) - val(3), 2, val(2))
385 check_type_3<phx::expression::minus<value<int>::type, value<int>::type>::type, int, value<int>::type>(MP5);
386 BOOST_TEST(test_attr("++--**/", MP5 >> '/', c) && c == 6);
387 }
388
389 return boost::report_errors();
390}
391