]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/test/qi/alternative.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / test / qi / alternative.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 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/mpl/print.hpp>
10 #include <boost/spirit/include/qi_operator.hpp>
11 #include <boost/spirit/include/qi_char.hpp>
12 #include <boost/spirit/include/qi_string.hpp>
13 #include <boost/spirit/include/qi_numeric.hpp>
14 #include <boost/spirit/include/qi_directive.hpp>
15 #include <boost/spirit/include/qi_action.hpp>
16 #include <boost/spirit/include/qi_nonterminal.hpp>
17 #include <boost/spirit/include/qi_auxiliary.hpp>
18 #include <boost/spirit/include/qi_rule.hpp>
19 #include <boost/spirit/include/support_argument.hpp>
20 #include <boost/spirit/include/phoenix_core.hpp>
21 #include <boost/spirit/include/phoenix_operator.hpp>
22 #include <boost/fusion/include/adapt_struct.hpp>
23 #include <boost/variant.hpp>
24 #include <boost/assert.hpp>
25
26 #include <string>
27 #include <iostream>
28 #include <vector>
29 #include "test.hpp"
30
31 struct test_action
32 {
33 test_action(char last)
34 : last_(last) {}
35
36 template<typename Context>
37 void operator()(std::vector<char> const& v, Context const&, bool&) const
38 {
39 BOOST_TEST(v.size() == 4 &&
40 v[0] == 'a' && v[1] == 'b' && v[2] == '1' && v[3] == last_);
41 }
42
43 char last_;
44 };
45
46 struct test_action_2
47 {
48 typedef std::vector<boost::optional<char> > result_type;
49
50 template<typename Context>
51 void operator()(result_type const& v, Context const&, bool&) const
52 {
53 BOOST_TEST(v.size() == 5 &&
54 !v[0] && v[1] == 'a' && v[2] == 'b' && v[3] == '1' && v[4] == '2');
55 }
56 };
57
58 struct DIgnore
59 {
60 std::string text;
61 };
62
63 struct DInclude
64 {
65 std::string FileName;
66 };
67
68 BOOST_FUSION_ADAPT_STRUCT(
69 DIgnore,
70 (std::string, text)
71 )
72
73 BOOST_FUSION_ADAPT_STRUCT(
74 DInclude,
75 (std::string, FileName)
76 )
77
78 int
79 main()
80 {
81 using spirit_test::test;
82 using spirit_test::test_attr;
83
84 using boost::spirit::ascii::char_;
85 using boost::spirit::qi::int_;
86 using boost::spirit::qi::lit;
87 using boost::spirit::qi::unused_type;
88 using boost::spirit::qi::_1;
89 using boost::spirit::qi::omit;
90
91 {
92 BOOST_TEST((test("a", char_ | char_)));
93 BOOST_TEST((test("x", lit('x') | lit('i'))));
94 BOOST_TEST((test("i", lit('x') | lit('i'))));
95 BOOST_TEST((!test("z", lit('x') | lit('o'))));
96 BOOST_TEST((test("rock", lit("rock") | lit("roll"))));
97 BOOST_TEST((test("roll", lit("rock") | lit("roll"))));
98 BOOST_TEST((test("rock", lit("rock") | int_)));
99 BOOST_TEST((test("12345", lit("rock") | int_)));
100 }
101
102 {
103 boost::variant<unused_type, int, char> v;
104
105 BOOST_TEST((test_attr("12345", lit("rock") | int_ | char_, v)));
106 BOOST_TEST(boost::get<int>(v) == 12345);
107
108 BOOST_TEST((test_attr("rock", lit("rock") | int_ | char_, v)));
109 BOOST_TEST(v.which() == 1);
110
111 BOOST_TEST((test_attr("x", lit("rock") | int_ | char_, v)));
112 BOOST_TEST(boost::get<char>(v) == 'x');
113 }
114
115 { // Make sure that we are using the actual supplied attribute types
116 // from the variant and not the expected type.
117 // $$$ Fixed: <2/19/2011> JDG $$$
118 boost::variant<int, std::string> v;
119 BOOST_TEST((test_attr("12345", int_ | +char_, v)));
120 BOOST_TEST(boost::get<int>(v) == 12345);
121
122 BOOST_TEST((test_attr("abc", int_ | +char_, v)));
123 BOOST_TEST(boost::get<std::string>(v) == "abc");
124
125 BOOST_TEST((test_attr("12345", +char_ | int_, v)));
126 BOOST_TEST(boost::get<std::string>(v) == "12345");
127 }
128
129 { // test action
130
131 namespace phx = boost::phoenix;
132 boost::optional<boost::variant<int, char> > v;
133
134 BOOST_TEST((test("12345", (lit("rock") | int_ | char_)[phx::ref(v) = _1])));
135 BOOST_TEST(boost::get<int>(boost::get(v)) == 12345);
136 BOOST_TEST((test("rock", (lit("rock") | int_ | char_)[phx::ref(v) = _1])));
137 BOOST_TEST(!v);
138 }
139
140 {
141 unused_type x;
142 BOOST_TEST((test_attr("rock", lit("rock") | lit('x'), x)));
143 }
144
145 {
146 // test if alternatives with all components having unused
147 // attributes have an unused attribute
148
149 using boost::fusion::vector;
150 using boost::fusion::at_c;
151
152 vector<char, char> v;
153 BOOST_TEST((test_attr("abc",
154 char_ >> (omit[char_] | omit[char_]) >> char_, v)));
155 BOOST_TEST((at_c<0>(v) == 'a'));
156 BOOST_TEST((at_c<1>(v) == 'c'));
157 }
158
159 {
160 // Test that we can still pass a "compatible" attribute to
161 // an alternate even if its "expected" attribute is unused type.
162
163 std::string s;
164 BOOST_TEST((test_attr("...", *(char_('.') | char_(',')), s)));
165 BOOST_TEST(s == "...");
166 }
167
168 { // make sure collapsing eps works as expected
169 // (compile check only)
170
171 using boost::spirit::qi::rule;
172 using boost::spirit::qi::_val;
173 using boost::spirit::qi::_1;
174 using boost::spirit::eps;
175 rule<const wchar_t*, wchar_t()> r1, r2, r3;
176
177 r3 = ((eps >> r1))[_val += _1];
178 r3 = ((r1 ) | r2)[_val += _1];
179
180 r3 %= ((eps >> r1) | r2);
181 r3 = ((eps >> r1) | r2)[_val += _1];
182 }
183
184 // make sure the attribute of an alternative gets properly collapsed
185 {
186 using boost::spirit::qi::lexeme;
187 using boost::spirit::ascii::alnum;
188 using boost::spirit::ascii::alpha;
189 using boost::spirit::ascii::digit;
190 using boost::spirit::ascii::string;
191 namespace phx = boost::phoenix;
192
193
194 BOOST_TEST( (test("ab1_", (*(alnum | char_('_')))[test_action('_')])) );
195 BOOST_TEST( (test("ab12", (*(alpha | digit))[test_action('2')])) );
196
197 BOOST_TEST( (test("abcab12", (*("abc" | alnum))[test_action_2()])) );
198
199 std::vector<boost::optional<char> > v;
200 BOOST_TEST( (test("x,y,z", (*(',' | char_))[phx::ref(v) = _1])) );
201 BOOST_ASSERT(v[0] == 'x');
202 BOOST_ASSERT(!v[1]);
203 BOOST_ASSERT(v[2] == 'y');
204 BOOST_ASSERT(!v[3]);
205 BOOST_ASSERT(v[4] == 'z');
206 }
207
208 {
209 using boost::spirit::qi::eps;
210
211 // testing a sequence taking a container as attribute
212 std::string s;
213 BOOST_TEST( (test_attr("abc,a,b,c",
214 char_ >> char_ >> (char_ % ','), s )) );
215 BOOST_TEST(s == "abcabc");
216
217 // test having an optional<container> inside a sequence
218 s.erase();
219 BOOST_TEST( (test_attr("ab",
220 char_ >> char_ >> -(char_ % ','), s )) );
221 BOOST_TEST(s == "ab");
222
223 // test having a variant<container, ...> inside a sequence
224 s.erase();
225 BOOST_TEST( (test_attr("ab",
226 char_ >> char_ >> ((char_ % ',') | eps), s )) );
227 BOOST_TEST(s == "ab");
228 s.erase();
229 BOOST_TEST( (test_attr("abc",
230 char_ >> char_ >> ((char_ % ',') | eps), s )) );
231 BOOST_TEST(s == "abc");
232 }
233
234 {
235 using boost::spirit::qi::int_;
236
237 int i = 0;
238 BOOST_TEST( (test_attr("10", int_(5) | int_(10), i)) );
239 BOOST_TEST(i == 10);
240 }
241
242 {
243 //compile test only (bug_march_10_2011_8_35_am)
244 typedef boost::variant<double, std::string> value_type;
245
246 using boost::spirit::qi::rule;
247 using boost::spirit::qi::eps;
248 rule<std::string::const_iterator, value_type()> r1 = r1 | eps;
249 }
250
251 {
252 using boost::spirit::qi::rule;
253 typedef boost::variant<DIgnore, DInclude> DLine;
254
255 rule<char*, DIgnore()> ignore;
256 rule<char*, DInclude()> include;
257 rule<char*, DLine()> line = include | ignore;
258 }
259
260 return boost::report_errors();
261 }
262