1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
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=============================================================================*/
7#include <boost/spirit/include/qi_sequence.hpp>
8
9#include <boost/spirit/include/qi_operator.hpp>
10#include <boost/spirit/include/qi_char.hpp>
11#include <boost/spirit/include/qi_string.hpp>
12#include <boost/spirit/include/qi_numeric.hpp>
13#include <boost/spirit/include/qi_directive.hpp>
14#include <boost/spirit/include/qi_action.hpp>
15#include <boost/spirit/include/qi_nonterminal.hpp>
16#include <boost/spirit/include/support_argument.hpp>
17#include <boost/phoenix/core.hpp>
18#include <boost/phoenix/operator.hpp>
19
20#include <string>
21#include <iostream>
22#include "test.hpp"
23
24int
25main()
26{
27 using namespace boost::spirit::ascii;
28 using boost::spirit::qi::lit;
29 using boost::spirit::qi::unused;
30 using boost::spirit::qi::int_;
31 using boost::spirit::qi::double_;
32 using boost::spirit::qi::what;
33 using boost::spirit::qi::rule;
34 using boost::spirit::qi::_1;
35 using boost::spirit::qi::_2;
36
37 using boost::fusion::vector;
38 using boost::fusion::at_c;
39
40 using spirit_test::test;
41 using spirit_test::test_attr;
42 using spirit_test::print_info;
43
44 {
45 BOOST_TEST((test("aa", char_ >> char_)));
46 BOOST_TEST((test("aaa", char_ >> char_ >> char_('a'))));
47 BOOST_TEST((test("xi", char_('x') >> char_('i'))));
48 BOOST_TEST((!test("xi", char_('x') >> char_('o'))));
49 BOOST_TEST((test("xin", char_('x') >> char_('i') >> char_('n'))));
50 }
51
52 {
53 BOOST_TEST((test(" a a", char_ >> char_, space)));
54 BOOST_TEST((test(" x i", char_('x') >> char_('i'), space)));
55 BOOST_TEST((!test(" x i", char_('x') >> char_('o'), space)));
56 }
57
58 {
59 BOOST_TEST((test(" Hello, World", lit("Hello") >> ',' >> "World", space)));
60 }
61
62 {
63 vector<char, char> attr;
64 BOOST_TEST((test_attr("abcdefg", char_ >> char_ >> "cdefg", attr)));
65 BOOST_TEST((at_c<0>(attr) == 'a'));
66 BOOST_TEST((at_c<1>(attr) == 'b'));
67 }
68
69 {
70 vector<char, char, char> attr;
71 BOOST_TEST((test_attr(" a\n b\n c", char_ >> char_ >> char_, attr, space)));
72 BOOST_TEST((at_c<0>(attr) == 'a'));
73 BOOST_TEST((at_c<1>(attr) == 'b'));
74 BOOST_TEST((at_c<2>(attr) == 'c'));
75 }
76
77 {
78 // unused_type means we don't care about the attribute
79 vector<char, char> attr;
80 BOOST_TEST((test_attr("abc", char_ >> 'b' >> char_, attr)));
81 BOOST_TEST((at_c<0>(attr) == 'a'));
82 BOOST_TEST((at_c<1>(attr) == 'c'));
83 }
84
85 {
86 // unused_type means we don't care about the attribute, even at the end
87 vector<char, char> attr;
88 BOOST_TEST((test_attr("acb", char_ >> char_ >> 'b', attr)));
89 BOOST_TEST((at_c<0>(attr) == 'a'));
90 BOOST_TEST((at_c<1>(attr) == 'c'));
91 }
92
93 {
94 // "hello" has an unused_type. unused attributes are not part of the sequence
95 vector<char, char> attr;
96 BOOST_TEST((test_attr("a hello c", char_ >> "hello" >> char_, attr, space)));
97 BOOST_TEST((at_c<0>(attr) == 'a'));
98 BOOST_TEST((at_c<1>(attr) == 'c'));
99 }
100
101 {
102 // a single element
103 char attr;
104 BOOST_TEST((test_attr("ab", char_ >> 'b', attr)));
105 BOOST_TEST((attr == 'a'));
106 }
107
108 {
109 // a single element fusion sequence
110 vector<char> attr;
111 BOOST_TEST((test_attr("ab", char_ >> 'b', attr)));
112 BOOST_TEST((at_c<0>(attr) == 'a'));
113 }
114
115 {
116 // make sure single element tuples get passed through if the rhs
117 // has a single element tuple as its attribute
118 vector<double, int> fv;
119 rule<char const*, vector<double, int>()> r;
120 r %= double_ >> ',' >> int_;
121 BOOST_TEST((test_attr("test:2.0,1", "test:" >> r, fv) &&
122 fv == vector<double, int>(2.0, 1)));
123 }
124
125 {
126 // unused means we don't care about the attribute
127 BOOST_TEST((test_attr("abc", char_ >> 'b' >> char_, unused)));
128 }
129
130 {
131 BOOST_TEST((test("aA", no_case[char_('a') >> 'a'])));
132 BOOST_TEST((test("BEGIN END", no_case[lit("begin") >> "end"], space)));
133 BOOST_TEST((!test("BEGIN END", no_case[lit("begin") >> "nend"], space)));
134 }
135
136 {
137#ifdef SPIRIT_NO_COMPILE_CHECK
138 char_ >> char_ = char_ >> char_; // disallow this!
139#endif
140 }
141
142 { // alternative forms of attributes. Allow sequences to take in
143 // stl containers.
144
145 std::vector<char> v;
146 BOOST_TEST(test_attr("abc", char_ >> char_ >> char_, v));
147 BOOST_TEST(v.size() == 3);
148 BOOST_TEST(v[0] == 'a');
149 BOOST_TEST(v[1] == 'b');
150 BOOST_TEST(v[2] == 'c');
151 }
152
153 { // alternative forms of attributes. Allow sequences to take in
154 // stl containers.
155
156 std::vector<char> v;
157 BOOST_TEST(test_attr("a,b,c", char_ >> *(',' >> char_), v));
158 BOOST_TEST(v.size() == 3);
159 BOOST_TEST(v[0] == 'a');
160 BOOST_TEST(v[1] == 'b');
161 BOOST_TEST(v[2] == 'c');
162 }
163
164 { // alternative forms of attributes. Allow sequences to take in
165 // stl containers.
166
167 std::vector<char> v;
168 BOOST_TEST(test_attr("abc", char_ >> *char_, v));
169 BOOST_TEST(v.size() == 3);
170 BOOST_TEST(v[0] == 'a');
171 BOOST_TEST(v[1] == 'b');
172 BOOST_TEST(v[2] == 'c');
173 }
174
175 { // alternative forms of attributes. Allow sequences to take in
176 // stl containers.
177 using boost::spirit::qi::hold;
178
179 std::vector<char> v;
180 BOOST_TEST(test_attr("abc", char_ >> *(char_ >> char_), v));
181 BOOST_TEST(v.size() == 3);
182 BOOST_TEST(v[0] == 'a');
183 BOOST_TEST(v[1] == 'b');
184 BOOST_TEST(v[2] == 'c');
185
186 v.clear();
187 BOOST_TEST(!test_attr("abcd", char_ >> *(char_ >> char_), v));
188
189 v.clear();
190 BOOST_TEST(test_attr("abcdef", char_ >> *hold[char_ >> char_] >> char_, v));
191 BOOST_TEST(v.size() == 6);
192 BOOST_TEST(v[0] == 'a');
193 BOOST_TEST(v[1] == 'b');
194 BOOST_TEST(v[2] == 'c');
195 BOOST_TEST(v[3] == 'd');
196 BOOST_TEST(v[4] == 'e');
197 BOOST_TEST(v[5] == 'f');
198
199 v.clear();
200 BOOST_TEST(test_attr("abc", char_ >> +(char_ >> char_), v));
201 BOOST_TEST(v.size() == 3);
202 BOOST_TEST(v[0] == 'a');
203 BOOST_TEST(v[1] == 'b');
204 BOOST_TEST(v[2] == 'c');
205 }
206
207 { // alternative forms of attributes. Allow sequences to take in
208 // stl containers.
209
210 std::vector<char> v;
211 BOOST_TEST(test_attr("abc", char_ >> -(+char_), v));
212 BOOST_TEST(v.size() == 3);
213 BOOST_TEST(v[0] == 'a');
214 BOOST_TEST(v[1] == 'b');
215 BOOST_TEST(v[2] == 'c');
216 }
217
218 { // alternative forms of attributes. Allow sequences to take in
219 // stl containers.
220
221 std::string s;
222 BOOST_TEST(test_attr("foobar", string("foo") >> string("bar"), s));
223 BOOST_TEST(s == "foobar");
224
225 s.clear();
226
227 using boost::spirit::qi::hold;
228
229 rule<char const*, std::string()> word = +char_("abc");
230 BOOST_TEST(test_attr("ab.bc.ca", *hold[word >> string(".")] >> word, s));
231 BOOST_TEST(s == "ab.bc.ca");
232 }
233
234 // alternative forms of attributes. Allow sequences to take in
235 // stl containers of stl containers.
236 {
237 std::vector<std::string> v;
238 BOOST_TEST(test_attr("abc1,abc2",
239 *~char_(',') >> *(',' >> *~char_(',')), v));
240 BOOST_TEST(v.size() == 2 && v[0] == "abc1" && v[1] == "abc2");
241 }
242
243 {
244 std::vector<std::string> v;
245 rule<char const*, std::string()> e = *~char_(',');
246 rule<char const*, std::vector<std::string>()> l = e >> *(',' >> e);
247
248 BOOST_TEST(test_attr("abc1,abc2,abc3", l, v));
249 BOOST_TEST(v.size() == 3);
250 BOOST_TEST(v[0] == "abc1");
251 BOOST_TEST(v[1] == "abc2");
252 BOOST_TEST(v[2] == "abc3");
253 }
254
255 // do the same with a plain string object
256 {
257 std::string s;
258 BOOST_TEST(test_attr("abc1,abc2",
259 *~char_(',') >> *(',' >> *~char_(',')), s));
260 BOOST_TEST(s == "abc1abc2");
261 }
262
263 {
264 std::string s;
265 rule<char const*, std::string()> e = *~char_(',');
266 rule<char const*, std::string()> l = e >> *(',' >> e);
267
268 BOOST_TEST(test_attr("abc1,abc2,abc3", l, s));
269 BOOST_TEST(s == "abc1abc2abc3");
270 }
271
272 {
273 std::vector<char> v;
274 BOOST_TEST(test_attr("ab", char_ >> -char_, v));
275 BOOST_TEST(v.size() == 2 && v[0] == 'a' && v[1] == 'b');
276
277 v.clear();
278 BOOST_TEST(test_attr("a", char_ >> -char_, v));
279 BOOST_TEST(v.size() == 1 && v[0] == 'a');
280
281 v.clear();
282 BOOST_TEST(test_attr("a", char_, v));
283 BOOST_TEST(v.size() == 1 && v[0] == 'a');
284 }
285
286 {
287 std::vector<boost::optional<char> > v;
288 BOOST_TEST(test_attr("ab", char_ >> -char_, v));
289 BOOST_TEST(v.size() == 2 && v[0] == 'a' && v[1] == 'b');
290
291 v.clear();
292 BOOST_TEST(test_attr("a", char_ >> -char_, v));
293 BOOST_TEST(v.size() == 2 && v[0] == 'a' && !v[1]);
294
295 v.clear();
296 BOOST_TEST(test_attr("a", char_, v));
297 BOOST_TEST(v.size() == 1 && v[0] == 'a');
298 }
299
300 { // test action
301 using boost::phoenix::ref;
302 char c = 0;
303 int n = 0;
304
305 BOOST_TEST(test("x123\"a string\"", (char_ >> int_ >> "\"a string\"")
306 [(ref(c) = _1, ref(n) = _2)]));
307 BOOST_TEST(c == 'x');
308 BOOST_TEST(n == 123);
309 }
310
311 { // test action
312 using boost::phoenix::ref;
313 char c = 0;
314 int n = 0;
315
316 BOOST_TEST(test("x 123 \"a string\"", (char_ >> int_ >> "\"a string\"")
317 [(ref(c) = _1, ref(n) = _2)], space));
318 BOOST_TEST(c == 'x');
319 BOOST_TEST(n == 123);
320 }
321
322 { // testing "what"
323 print_info(what: what(expr: alpha | char_('x') >> lit("hello") >> int_));
324 }
325
326// { // compile check only
327// using boost::spirit::qi::rule;
328// typedef boost::fusion::vector<int, double> tuple_type;
329// typedef std::vector<boost::fusion::vector<int, double> > attr_type;
330//
331// rule<char const*, tuple_type()> r = int_ >> ',' >> double_;
332// rule<char const*, attr_type()> r2 = r >> *(',' >> r);
333// //~ rule<char const*, attr_type()> r2 = r % ',';
334// }
335
336 return boost::report_errors();
337}
338
339

source code of boost/libs/spirit/test/qi/sequence.cpp