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