]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/test/x3/alternative.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / spirit / test / x3 / alternative.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2015 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
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 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/spirit/home/x3.hpp>
10 #include <boost/fusion/include/adapt_struct.hpp>
11 #include <boost/variant.hpp>
12 #include <boost/fusion/include/vector.hpp>
13 #include <boost/fusion/include/at.hpp>
14
15 #include <string>
16 #include <iostream>
17 #include <vector>
18 #include "test.hpp"
19
20 struct di_ignore
21 {
22 std::string text;
23 };
24
25 struct di_include
26 {
27 std::string FileName;
28 };
29
30 BOOST_FUSION_ADAPT_STRUCT(di_ignore,
31 text
32 )
33
34 BOOST_FUSION_ADAPT_STRUCT(di_include,
35 FileName
36 )
37
38 struct undefined {};
39
40
41 struct stationary : boost::noncopyable
42 {
43 explicit stationary(int i) : val{i} {}
44 stationary& operator=(int i) { val = i; return *this; }
45
46 int val;
47 };
48
49
50 int
51 main()
52 {
53 using spirit_test::test;
54 using spirit_test::test_attr;
55
56 using boost::spirit::x3::attr;
57 using boost::spirit::x3::char_;
58 using boost::spirit::x3::int_;
59 using boost::spirit::x3::lit;
60 using boost::spirit::x3::unused_type;
61 using boost::spirit::x3::unused;
62 using boost::spirit::x3::omit;
63 using boost::spirit::x3::eps;
64
65 BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(char_ | char_);
66
67 {
68 BOOST_TEST((test("a", char_ | char_)));
69 BOOST_TEST((test("x", lit('x') | lit('i'))));
70 BOOST_TEST((test("i", lit('x') | lit('i'))));
71 BOOST_TEST((!test("z", lit('x') | lit('o'))));
72 BOOST_TEST((test("rock", lit("rock") | lit("roll"))));
73 BOOST_TEST((test("roll", lit("rock") | lit("roll"))));
74 BOOST_TEST((test("rock", lit("rock") | int_)));
75 BOOST_TEST((test("12345", lit("rock") | int_)));
76 }
77
78 {
79 typedef boost::variant<undefined, int, char> attr_type;
80 attr_type v;
81
82 BOOST_TEST((test_attr("12345", int_ | char_, v)));
83 BOOST_TEST(boost::get<int>(v) == 12345);
84
85 BOOST_TEST((test_attr("12345", lit("rock") | int_ | char_, v)));
86 BOOST_TEST(boost::get<int>(v) == 12345);
87
88 v = attr_type();
89 BOOST_TEST((test_attr("rock", lit("rock") | int_ | char_, v)));
90 BOOST_TEST(v.which() == 0);
91
92 BOOST_TEST((test_attr("x", lit("rock") | int_ | char_, v)));
93 BOOST_TEST(boost::get<char>(v) == 'x');
94 }
95
96 { // Make sure that we are using the actual supplied attribute types
97 // from the variant and not the expected type.
98 boost::variant<int, std::string> v;
99 BOOST_TEST((test_attr("12345", int_ | +char_, v)));
100 BOOST_TEST(boost::get<int>(v) == 12345);
101
102 BOOST_TEST((test_attr("abc", int_ | +char_, v)));
103 BOOST_TEST(boost::get<std::string>(v) == "abc");
104
105 BOOST_TEST((test_attr("12345", +char_ | int_, v)));
106 BOOST_TEST(boost::get<std::string>(v) == "12345");
107 }
108
109 {
110 unused_type x;
111 BOOST_TEST((test_attr("rock", lit("rock") | lit('x'), x)));
112 }
113
114 {
115 // test if alternatives with all components having unused
116 // attributes have an unused attribute
117
118 using boost::fusion::vector;
119 using boost::fusion::at_c;
120
121 vector<char, char> v;
122 BOOST_TEST((test_attr("abc",
123 char_ >> (omit[char_] | omit[char_]) >> char_, v)));
124 BOOST_TEST((at_c<0>(v) == 'a'));
125 BOOST_TEST((at_c<1>(v) == 'c'));
126 }
127
128 {
129 // Test that we can still pass a "compatible" attribute to
130 // an alternate even if its "expected" attribute is unused type.
131
132 std::string s;
133 BOOST_TEST((test_attr("...", *(char_('.') | char_(',')), s)));
134 BOOST_TEST(s == "...");
135 }
136
137 { // make sure collapsing eps works as expected
138 // (compile check only)
139
140 using boost::spirit::x3::rule;
141 using boost::spirit::x3::eps;
142 using boost::spirit::x3::_attr;
143 using boost::spirit::x3::_val;
144
145 rule<class r1, wchar_t> r1;
146 rule<class r2, wchar_t> r2;
147 rule<class r3, wchar_t> r3;
148
149 auto f = [&](auto& ctx){ _val(ctx) = _attr(ctx); };
150
151 r3 = ((eps >> r1))[f];
152 r3 = ((r1) | r2)[f];
153 r3 = ((eps >> r1) | r2);
154 }
155
156 {
157 std::string s;
158 using boost::spirit::x3::eps;
159
160 // test having a variant<container, ...>
161 BOOST_TEST( (test_attr("a,b", (char_ % ',') | eps, s )) );
162 BOOST_TEST(s == "ab");
163 }
164
165 {
166 using boost::spirit::x3::eps;
167
168 // testing a sequence taking a container as attribute
169 std::string s;
170 BOOST_TEST( (test_attr("abc,a,b,c",
171 char_ >> char_ >> (char_ % ','), s )) );
172 BOOST_TEST(s == "abcabc");
173
174 // test having an optional<container> inside a sequence
175 s.erase();
176 BOOST_TEST( (test_attr("ab",
177 char_ >> char_ >> -(char_ % ','), s )) );
178 BOOST_TEST(s == "ab");
179
180 // test having a variant<container, ...> inside a sequence
181 s.erase();
182 BOOST_TEST( (test_attr("ab",
183 char_ >> char_ >> ((char_ % ',') | eps), s )) );
184 BOOST_TEST(s == "ab");
185 s.erase();
186 BOOST_TEST( (test_attr("abc",
187 char_ >> char_ >> ((char_ % ',') | eps), s )) );
188 BOOST_TEST(s == "abc");
189 }
190
191 {
192 //compile test only (bug_march_10_2011_8_35_am)
193 typedef boost::variant<double, std::string> value_type;
194
195 using boost::spirit::x3::rule;
196 using boost::spirit::x3::eps;
197
198 rule<class r1, value_type> r1;
199 auto r1_ = r1 = r1 | eps; // left recursive!
200
201 unused = r1_; // silence unused local warning
202 }
203
204 {
205 using boost::spirit::x3::rule;
206 typedef boost::variant<di_ignore, di_include> d_line;
207
208 rule<class ignore, di_ignore> ignore;
209 rule<class include, di_include> include;
210 rule<class line, d_line> line;
211
212 auto start =
213 line = include | ignore;
214
215 unused = start; // silence unused local warning
216 }
217
218 // single-element fusion vector tests
219 {
220 boost::fusion::vector<boost::variant<int, std::string>> fv;
221 BOOST_TEST((test_attr("12345", int_ | +char_, fv)));
222 BOOST_TEST(boost::get<int>(boost::fusion::at_c<0>(fv)) == 12345);
223
224 boost::fusion::vector<boost::variant<int, std::string>> fvi;
225 BOOST_TEST((test_attr("12345", int_ | int_, fvi)));
226 BOOST_TEST(boost::get<int>(boost::fusion::at_c<0>(fvi)) == 12345);
227 }
228
229 // alternative over single element sequences as part of another sequence
230 {
231 auto key1 = lit("long") >> attr(long());
232 auto key2 = lit("char") >> attr(char());
233 auto keys = key1 | key2;
234 auto pair = keys >> lit("=") >> +char_;
235
236 boost::fusion::deque<boost::variant<long, char>, std::string> attr_;
237
238 BOOST_TEST(test_attr("long=ABC", pair, attr_));
239 BOOST_TEST(boost::get<long>(&boost::fusion::front(attr_)) != nullptr);
240 BOOST_TEST(boost::get<char>(&boost::fusion::front(attr_)) == nullptr);
241 }
242
243 { // ensure no unneeded synthesization, copying and moving occurred
244 auto p = '{' >> int_ >> '}';
245
246 stationary st { 0 };
247 BOOST_TEST(test_attr("{42}", p | eps | p, st));
248 BOOST_TEST_EQ(st.val, 42);
249 }
250
251 { // attributeless parsers must not insert values
252 std::vector<int> v;
253 BOOST_TEST(test_attr("1 2 3 - 5 - - 7 -", (int_ | '-') % ' ', v));
254 BOOST_TEST_EQ(v.size(), 5)
255 && BOOST_TEST_EQ(v[0], 1)
256 && BOOST_TEST_EQ(v[1], 2)
257 && BOOST_TEST_EQ(v[2], 3)
258 && BOOST_TEST_EQ(v[3], 5)
259 && BOOST_TEST_EQ(v[4], 7)
260 ;
261 }
262
263 { // regressing test for #603
264 using boost::spirit::x3::attr;
265 struct X {};
266 std::vector<boost::variant<std::string, int, X>> v;
267 BOOST_TEST(test_attr("xx42x9y", *(int_ | +char_('x') | 'y' >> attr(X{})), v));
268 BOOST_TEST_EQ(v.size(), 5);
269 }
270
271 { // sequence parser in alternative into container
272 std::string s;
273 BOOST_TEST(test_attr("abcbbcd",
274 *(char_('a') >> *(*char_('b') >> char_('c')) | char_('d')), s));
275 BOOST_TEST_EQ(s, "abcbbcd");
276 }
277
278 return boost::report_errors();
279 }