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_repeat.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/support_argument.hpp> |
16 | #include <boost/phoenix/core.hpp> |
17 | #include <boost/phoenix/operator.hpp> |
18 | |
19 | #include <string> |
20 | #include <vector> |
21 | #include <iostream> |
22 | #include "test.hpp" |
23 | |
24 | struct x_attr |
25 | { |
26 | }; |
27 | |
28 | namespace boost { namespace spirit { namespace traits |
29 | { |
30 | template <> |
31 | struct container_value<x_attr> |
32 | { |
33 | typedef char type; // value type of container |
34 | }; |
35 | |
36 | template <> |
37 | struct push_back_container<x_attr, char> |
38 | { |
39 | static bool call(x_attr& /*c*/, char /*val*/) |
40 | { |
41 | // push back value type into container |
42 | return true; |
43 | } |
44 | }; |
45 | }}} |
46 | |
47 | int |
48 | main() |
49 | { |
50 | using spirit_test::test_attr; |
51 | using spirit_test::test; |
52 | |
53 | using namespace boost::spirit::ascii; |
54 | using boost::spirit::qi::repeat; |
55 | using boost::spirit::qi::inf; |
56 | using boost::spirit::qi::omit; |
57 | using boost::spirit::qi::int_; |
58 | using boost::spirit::qi::_1; |
59 | using boost::spirit::qi::lexeme; |
60 | |
61 | { |
62 | BOOST_TEST(test("aaaaaaaa" , repeat[char_])); // kleene synonym |
63 | BOOST_TEST(test("aaaaaaaa" , repeat(8)[char_])); |
64 | BOOST_TEST(!test("aa" , repeat(3)[char_])); |
65 | |
66 | BOOST_TEST(test("aaa" , repeat(3, 5)[char_])); |
67 | BOOST_TEST(test("aaaaa" , repeat(3, 5)[char_])); |
68 | BOOST_TEST(!test("aaaaaa" , repeat(3, 5)[char_])); |
69 | BOOST_TEST(!test("aa" , repeat(3, 5)[char_])); |
70 | |
71 | BOOST_TEST(test("aaa" , repeat(3, inf)[char_])); |
72 | BOOST_TEST(test("aaaaa" , repeat(3, inf)[char_])); |
73 | BOOST_TEST(test("aaaaaa" , repeat(3, inf)[char_])); |
74 | BOOST_TEST(!test("aa" , repeat(3, inf)[char_])); |
75 | } |
76 | |
77 | { |
78 | std::string s; |
79 | BOOST_TEST(test_attr("aaaaaaaa" , repeat[char_ >> char_], s)); // kleene synonym |
80 | BOOST_TEST(s == "aaaaaaaa" ); |
81 | |
82 | s.clear(); |
83 | BOOST_TEST(test_attr("aaaaaaaa" , repeat(4)[char_ >> char_], s)); |
84 | BOOST_TEST(s == "aaaaaaaa" ); |
85 | |
86 | BOOST_TEST(!test("aa" , repeat(3)[char_ >> char_])); |
87 | BOOST_TEST(!test("a" , repeat(1)[char_ >> char_])); |
88 | |
89 | s.clear(); |
90 | BOOST_TEST(test_attr("aa" , repeat(1, 3)[char_ >> char_], s)); |
91 | BOOST_TEST(s == "aa" ); |
92 | |
93 | s.clear(); |
94 | BOOST_TEST(test_attr("aaaaaa" , repeat(1, 3)[char_ >> char_], s)); |
95 | BOOST_TEST(s == "aaaaaa" ); |
96 | |
97 | BOOST_TEST(!test("aaaaaaa" , repeat(1, 3)[char_ >> char_])); |
98 | BOOST_TEST(!test("a" , repeat(1, 3)[char_ >> char_])); |
99 | |
100 | s.clear(); |
101 | BOOST_TEST(test_attr("aaaa" , repeat(2, inf)[char_ >> char_], s)); |
102 | BOOST_TEST(s == "aaaa" ); |
103 | |
104 | s.clear(); |
105 | BOOST_TEST(test_attr("aaaaaa" , repeat(2, inf)[char_ >> char_], s)); |
106 | BOOST_TEST(s == "aaaaaa" ); |
107 | |
108 | BOOST_TEST(!test("aa" , repeat(2, inf)[char_ >> char_])); |
109 | } |
110 | |
111 | { // from classic spirit tests |
112 | BOOST_TEST(test("" , repeat(0, inf)['x'])); |
113 | |
114 | // repeat exact 8 |
115 | #define rep8 repeat(8)[alpha] >> 'X' |
116 | BOOST_TEST(!test("abcdefgX" , rep8, false)); |
117 | BOOST_TEST(test("abcdefghX" , rep8)); |
118 | BOOST_TEST(!test("abcdefghiX" , rep8, false)); |
119 | BOOST_TEST(!test("abcdefgX" , rep8, false)); |
120 | BOOST_TEST(!test("aX" , rep8, false)); |
121 | |
122 | // repeat 2 to 8 |
123 | #define rep28 repeat(2, 8)[alpha] >> '*' |
124 | BOOST_TEST(test("abcdefg*" , rep28)); |
125 | BOOST_TEST(test("abcdefgh*" , rep28)); |
126 | BOOST_TEST(!test("abcdefghi*" , rep28, false)); |
127 | BOOST_TEST(!test("a*" , rep28, false)); |
128 | |
129 | // repeat 2 or more |
130 | #define rep2_ repeat(2, inf)[alpha] >> '+' |
131 | BOOST_TEST(test("abcdefg+" , rep2_)); |
132 | BOOST_TEST(test("abcdefgh+" , rep2_)); |
133 | BOOST_TEST(test("abcdefghi+" , rep2_)); |
134 | BOOST_TEST(test("abcdefg+" , rep2_)); |
135 | BOOST_TEST(!test("a+" , rep2_, false)); |
136 | |
137 | // repeat 0 |
138 | #define rep0 repeat(0)[alpha] >> '/' |
139 | BOOST_TEST(test("/" , rep0)); |
140 | BOOST_TEST(!test("a/" , rep0, false)); |
141 | |
142 | // repeat 0 or 1 |
143 | #define rep01 repeat(0, 1)[alpha >> digit] >> '?' |
144 | BOOST_TEST(!test("abcdefg?" , rep01, false)); |
145 | BOOST_TEST(!test("a?" , rep01, false)); |
146 | BOOST_TEST(!test("1?" , rep01, false)); |
147 | BOOST_TEST(!test("11?" , rep01, false)); |
148 | BOOST_TEST(!test("aa?" , rep01, false)); |
149 | BOOST_TEST(test("?" , rep01)); |
150 | BOOST_TEST(test("a1?" , rep01)); |
151 | } |
152 | |
153 | { |
154 | BOOST_TEST(test(" a a aaa aa" , repeat(7)[char_], space)); |
155 | BOOST_TEST(test("12345 678 9" , repeat(9)[digit], space)); |
156 | } |
157 | |
158 | { |
159 | BOOST_TEST(test("aBcdeFGH" , no_case[repeat(8)[lower]])); |
160 | BOOST_TEST(test("a B cde FGH" , no_case[repeat(8)[lower]], space)); |
161 | } |
162 | |
163 | { |
164 | std::vector<std::string> v; |
165 | BOOST_TEST(test_attr("a b c d" , repeat(4)[lexeme[+alpha]], v, space) && 4 == v.size() && |
166 | v[0] == "a" && v[1] == "b" && v[2] == "c" && v[3] == "d" ); |
167 | } |
168 | |
169 | { |
170 | std::string s; |
171 | BOOST_TEST(test_attr("bbbb" , repeat(4)[char_], s) && s == "bbbb" ); |
172 | |
173 | s.clear(); |
174 | BOOST_TEST(test_attr("b b b b" , repeat(4)[char_], s, space) && s == "bbbb" ); |
175 | |
176 | // The following 2 tests show that omit does not inhibit explicit attributes |
177 | s.clear(); |
178 | BOOST_TEST(test_attr("bbbb" , omit[repeat(4)[char_('b')]], s) && s == "bbbb" ); |
179 | |
180 | s.clear(); |
181 | BOOST_TEST(test_attr("b b b b" , omit[repeat(4)[char_('b')]], s, space) && s == "bbbb" ); |
182 | } |
183 | |
184 | { |
185 | BOOST_TEST(test("1 2 3" , int_ >> repeat(2)[int_], space)); |
186 | BOOST_TEST(!test("1 2" , int_ >> repeat(2)[int_], space)); |
187 | } |
188 | |
189 | { |
190 | std::vector<char> v; |
191 | BOOST_TEST(test_attr("1 2 3" , int_ >> repeat(2)[int_], v, space)); |
192 | BOOST_TEST(v.size() == 3 && v[0] == 1 && v[1] == 2 && v[2] == 3); |
193 | |
194 | BOOST_TEST(!test("1 2" , int_ >> repeat(2)[int_], space)); |
195 | } |
196 | |
197 | { // actions |
198 | namespace phx = boost::phoenix; |
199 | |
200 | std::vector<char> v; |
201 | BOOST_TEST(test("bbbb" , repeat(4)[char_][phx::ref(v) = _1]) && 4 == v.size() && |
202 | v[0] == 'b' && v[1] == 'b' && v[2] == 'b' && v[3] == 'b'); |
203 | } |
204 | |
205 | { // more actions |
206 | namespace phx = boost::phoenix; |
207 | |
208 | std::vector<int> v; |
209 | BOOST_TEST(test("123 456 789" , repeat(3)[int_][phx::ref(v) = _1], space) && 3 == v.size() && |
210 | v[0] == 123 && v[1] == 456 && v[2] == 789); |
211 | } |
212 | |
213 | { // lazy repeats |
214 | using boost::phoenix::val; |
215 | |
216 | BOOST_TEST(test("aaaaaaaa" , repeat(val(8))[char_])); |
217 | BOOST_TEST(!test("aa" , repeat(val(3))[char_])); |
218 | |
219 | BOOST_TEST(test("aaa" , repeat(val(3), val(5))[char_])); |
220 | BOOST_TEST(test("aaaaa" , repeat(val(3), val(5))[char_])); |
221 | BOOST_TEST(!test("aaaaaa" , repeat(val(3), val(5))[char_])); |
222 | BOOST_TEST(!test("aa" , repeat(val(3), val(5))[char_])); |
223 | |
224 | BOOST_TEST(test("aaa" , repeat(val(3), val(inf))[char_])); |
225 | BOOST_TEST(test("aaaaa" , repeat(val(3), val(inf))[char_])); |
226 | BOOST_TEST(test("aaaaaa" , repeat(val(3), val(inf))[char_])); |
227 | BOOST_TEST(!test("aa" , repeat(val(3), val(inf))[char_])); |
228 | } |
229 | |
230 | { // more lazy repeats |
231 | using boost::phoenix::val; |
232 | |
233 | BOOST_TEST(test("aaa" , repeat(3, val(5))[char_])); |
234 | BOOST_TEST(test("aaaaa" , repeat(val(3), 5)[char_])); |
235 | BOOST_TEST(!test("aaaaaa" , repeat(3, val(5))[char_])); |
236 | BOOST_TEST(!test("aa" , repeat(val(3), 5)[char_])); |
237 | |
238 | //#warning "testcase commented out" |
239 | BOOST_TEST(test("aaa" , repeat(val(3), inf)[char_])); |
240 | BOOST_TEST(test("aaaaa" , repeat(3, val(inf))[char_])); |
241 | BOOST_TEST(test("aaaaaa" , repeat(val(3), inf)[char_])); |
242 | BOOST_TEST(!test("aa" , repeat(3, val(inf))[char_])); |
243 | } |
244 | |
245 | { // attribute customization |
246 | |
247 | x_attr x; |
248 | test_attr(in: "abcde" , p: repeat[char_], attr&: x); |
249 | test_attr(in: "abcde" , p: repeat(5)[char_], attr&: x); |
250 | test_attr(in: "abcde" , p: repeat(1, 5)[char_], attr&: x); |
251 | test_attr(in: "abcde" , p: repeat(1, inf)[char_], attr&: x); |
252 | } |
253 | |
254 | return boost::report_errors(); |
255 | } |
256 | |
257 | |