1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // misc1.hpp |
3 | // |
4 | // Copyright 2008 Eric Niebler. Distributed under the Boost |
5 | // Software License, Version 1.0. (See accompanying file |
6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | #include <iostream> |
9 | #include <boost/xpressive/xpressive.hpp> |
10 | #include <boost/xpressive/traits/cpp_regex_traits.hpp> |
11 | #include <boost/test/unit_test.hpp> |
12 | |
13 | using namespace boost::unit_test; |
14 | using namespace boost::xpressive; |
15 | |
16 | void test1() |
17 | { |
18 | // make sure the following compiles: |
19 | sregex a = _; |
20 | sregex b = _; |
21 | sregex c = a >> b; |
22 | c = 'a' >> b; |
23 | c = a >> 'b'; |
24 | c = a | b; |
25 | c = 'a' | b; |
26 | c = a | 'b'; |
27 | c = !a; |
28 | c = *a; |
29 | c = +a; |
30 | } |
31 | |
32 | /////////////////////////////////////////////////////////////////////////////// |
33 | // test for basic_regex in a keep |
34 | // |
35 | void test2() |
36 | { |
37 | std::locale loc; |
38 | std::string str("Its a mad Mad mAd maD world" ); |
39 | sregex word = +_w; |
40 | sregex sentence = imbue(loc)(*(keep(expr: word) >> +_s) >> word); |
41 | smatch what; |
42 | |
43 | BOOST_REQUIRE(regex_match(str, what, sentence)); |
44 | BOOST_REQUIRE(7 == what.nested_results().size()); |
45 | smatch::nested_results_type::const_iterator pword = what.nested_results().begin(); |
46 | BOOST_CHECK((*pword++)[0] == "Its" ); |
47 | BOOST_CHECK((*pword++)[0] == "a" ); |
48 | BOOST_CHECK((*pword++)[0] == "mad" ); |
49 | BOOST_CHECK((*pword++)[0] == "Mad" ); |
50 | BOOST_CHECK((*pword++)[0] == "mAd" ); |
51 | BOOST_CHECK((*pword++)[0] == "maD" ); |
52 | BOOST_CHECK((*pword++)[0] == "world" ); |
53 | BOOST_CHECK(pword == what.nested_results().end()); |
54 | } |
55 | |
56 | /////////////////////////////////////////////////////////////////////////////// |
57 | // test for a simple non-recursive grammar |
58 | // |
59 | void test3() |
60 | { |
61 | // test for a simple regex grammar |
62 | std::string buffer = |
63 | "FROGGIE\r\n" |
64 | "Volume = 1\r\n" |
65 | "Other1= 2\r\n" |
66 | "Channel=3\r\n" |
67 | "Other =4\r\n" |
68 | "\r\n" |
69 | "FROGGIE\r\n" |
70 | "Volume = 5\r\n" |
71 | "Other1= 6\r\n" |
72 | "Channel=7\r\n" |
73 | "Other =8\r\n" |
74 | "\r\n" |
75 | "FROGGIE\r\n" |
76 | "Volume = 9\r\n" |
77 | "Other1= 0\r\n" |
78 | "Channel=10\r\n" |
79 | "\r\n" ; |
80 | |
81 | mark_tag name(1), value(2); |
82 | |
83 | sregex name_value_pair_ = |
84 | (name= +alnum) >> *_s >> "=" >> *_s >> |
85 | (value= +_d) >> *_s >> _ln; |
86 | |
87 | sregex message_ = |
88 | *_s >> "FROGGIE" >> _ln >> +name_value_pair_ >> _ln; |
89 | |
90 | sregex re_ = +message_; |
91 | |
92 | smatch::nested_results_type::const_iterator msg, nvp; |
93 | smatch tmpwhat; |
94 | |
95 | BOOST_REQUIRE(regex_search(buffer, tmpwhat, re_)); |
96 | // for giggles, make a deep-copy of the tree of results |
97 | smatch what = tmpwhat; |
98 | BOOST_REQUIRE(3 == what.nested_results().size()); |
99 | |
100 | msg = what.nested_results().begin(); |
101 | BOOST_REQUIRE(4 == msg->nested_results().size()); |
102 | |
103 | nvp = msg->nested_results().begin(); |
104 | BOOST_REQUIRE(3 == nvp->size()); |
105 | BOOST_CHECK("Volume" == (*nvp)[name]); |
106 | BOOST_CHECK("1" == (*nvp)[value]); |
107 | ++nvp; |
108 | BOOST_REQUIRE(3 == nvp->size()); |
109 | BOOST_CHECK("Other1" == (*nvp)[name]); |
110 | BOOST_CHECK("2" == (*nvp)[value]); |
111 | ++nvp; |
112 | BOOST_REQUIRE(3 == nvp->size()); |
113 | BOOST_CHECK("Channel" == (*nvp)[name]); |
114 | BOOST_CHECK("3" == (*nvp)[value]); |
115 | ++nvp; |
116 | BOOST_REQUIRE(3 == nvp->size()); |
117 | BOOST_CHECK("Other" == (*nvp)[name]); |
118 | BOOST_CHECK("4" == (*nvp)[value]); |
119 | |
120 | ++msg; |
121 | BOOST_REQUIRE(4 == msg->nested_results().size()); |
122 | |
123 | nvp = msg->nested_results().begin(); |
124 | BOOST_REQUIRE(3 == nvp->size()); |
125 | BOOST_CHECK("Volume" == (*nvp)[name]); |
126 | BOOST_CHECK("5" == (*nvp)[value]); |
127 | ++nvp; |
128 | BOOST_REQUIRE(3 == nvp->size()); |
129 | BOOST_CHECK("Other1" == (*nvp)[name]); |
130 | BOOST_CHECK("6" == (*nvp)[value]); |
131 | ++nvp; |
132 | BOOST_REQUIRE(3 == nvp->size()); |
133 | BOOST_CHECK("Channel" == (*nvp)[name]); |
134 | BOOST_CHECK("7" == (*nvp)[value]); |
135 | ++nvp; |
136 | BOOST_REQUIRE(3 == nvp->size()); |
137 | BOOST_CHECK("Other" == (*nvp)[name]); |
138 | BOOST_CHECK("8" == (*nvp)[value]); |
139 | |
140 | ++msg; |
141 | BOOST_REQUIRE(3 == msg->nested_results().size()); |
142 | |
143 | nvp = msg->nested_results().begin(); |
144 | BOOST_REQUIRE(3 == nvp->size()); |
145 | BOOST_CHECK("Volume" == (*nvp)[name]); |
146 | BOOST_CHECK("9" == (*nvp)[value]); |
147 | ++nvp; |
148 | BOOST_REQUIRE(3 == nvp->size()); |
149 | BOOST_CHECK("Other1" == (*nvp)[name]); |
150 | BOOST_CHECK("0" == (*nvp)[value]); |
151 | ++nvp; |
152 | BOOST_REQUIRE(3 == nvp->size()); |
153 | BOOST_CHECK("Channel" == (*nvp)[name]); |
154 | BOOST_CHECK("10" == (*nvp)[value]); |
155 | } |
156 | |
157 | /////////////////////////////////////////////////////////////////////////////// |
158 | // test for a self-recursive regex |
159 | // |
160 | void test4() |
161 | { |
162 | sregex parentheses; |
163 | parentheses // A balanced set of parentheses ... |
164 | = '(' // is an opening parenthesis ... |
165 | >> // followed by ... |
166 | *( // zero or more ... |
167 | keep( expr: +~(set='(',')') ) // of a bunch of things that are not parentheses ... |
168 | | // or ... |
169 | by_ref(rex: parentheses) // a balanced set of parentheses |
170 | ) // (ooh, recursion!) ... |
171 | >> // followed by ... |
172 | ')' // a closing parenthesis |
173 | ; |
174 | |
175 | smatch what; |
176 | smatch::nested_results_type::const_iterator pwhat, pwhat2; |
177 | std::string str( "blah blah( a(b)c (c(e)f (g)h )i (j)6 )blah" ); |
178 | |
179 | BOOST_REQUIRE(regex_search(str, what, parentheses)); |
180 | BOOST_REQUIRE(1 == what.size()); |
181 | BOOST_CHECK("( a(b)c (c(e)f (g)h )i (j)6 )" == what[0]); |
182 | |
183 | BOOST_REQUIRE(3 == what.nested_results().size()); |
184 | pwhat = what.nested_results().begin(); |
185 | BOOST_REQUIRE(1 == pwhat->size()); |
186 | BOOST_CHECK("(b)" == (*pwhat)[0]); |
187 | |
188 | ++pwhat; |
189 | BOOST_REQUIRE(1 == pwhat->size()); |
190 | BOOST_CHECK("(c(e)f (g)h )" == (*pwhat)[0]); |
191 | |
192 | BOOST_REQUIRE(2 == pwhat->nested_results().size()); |
193 | pwhat2 = pwhat->nested_results().begin(); |
194 | BOOST_REQUIRE(1 == pwhat2->size()); |
195 | BOOST_CHECK("(e)" == (*pwhat2)[0]); |
196 | |
197 | ++pwhat2; |
198 | BOOST_REQUIRE(1 == pwhat2->size()); |
199 | BOOST_CHECK("(g)" == (*pwhat2)[0]); |
200 | |
201 | ++pwhat; |
202 | BOOST_REQUIRE(1 == pwhat->size()); |
203 | BOOST_CHECK("(j)" == (*pwhat)[0]); |
204 | } |
205 | |
206 | /////////////////////////////////////////////////////////////////////////////// |
207 | // test for a sub-match scoping |
208 | // |
209 | void test5() |
210 | { |
211 | sregex inner = sregex::compile( begin: "(.)\\1" ); |
212 | sregex outer = (s1= _) >> inner >> s1; |
213 | std::string abba("ABBA" ); |
214 | |
215 | BOOST_CHECK(regex_match(abba, outer)); |
216 | } |
217 | |
218 | /////////////////////////////////////////////////////////////////////////////// |
219 | // Ye olde calculator. Test recursive grammar. |
220 | // |
221 | void test6() |
222 | { |
223 | sregex group, factor, term, expression; |
224 | |
225 | group = '(' >> by_ref(rex: expression) >> ')'; |
226 | factor = +_d | group; |
227 | term = factor >> *(('*' >> factor) | ('/' >> factor)); |
228 | expression = term >> *(('+' >> term) | ('-' >> term)); |
229 | |
230 | smatch what; |
231 | std::string str("foo 9*(10+3) bar" ); |
232 | |
233 | BOOST_REQUIRE(regex_search(str, what, expression)); |
234 | BOOST_CHECK("9*(10+3)" == what[0]); |
235 | } |
236 | |
237 | /////////////////////////////////////////////////////////////////////////////// |
238 | // init_unit_test_suite |
239 | // |
240 | test_suite* init_unit_test_suite( int argc, char* argv[] ) |
241 | { |
242 | test_suite *test = BOOST_TEST_SUITE("miscelaneous tests and examples from the docs" ); |
243 | |
244 | test->add(BOOST_TEST_CASE(&test1)); |
245 | test->add(BOOST_TEST_CASE(&test2)); |
246 | test->add(BOOST_TEST_CASE(&test3)); |
247 | test->add(BOOST_TEST_CASE(&test4)); |
248 | test->add(BOOST_TEST_CASE(&test5)); |
249 | test->add(BOOST_TEST_CASE(&test6)); |
250 | |
251 | return test; |
252 | } |
253 | |