1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #include <boost/spirit/include/lex_lexertl.hpp> |
7 | |
8 | #include <boost/core/lightweight_test.hpp> |
9 | |
10 | #ifdef _MSC_VER |
11 | // bogus https://developercommunity.visualstudio.com/t/buggy-warning-c4709/471956 |
12 | # pragma warning(disable: 4709) // comma operator within array index expression |
13 | #endif |
14 | |
15 | namespace lex = boost::spirit::lex; |
16 | |
17 | typedef lex::lexertl::token<std::string::iterator> token_type; |
18 | typedef lex::lexertl::actor_lexer<token_type> lexer_type; |
19 | |
20 | /////////////////////////////////////////////////////////////////////////////// |
21 | static bool found_identifier_flag = false; |
22 | |
23 | /////////////////////////////////////////////////////////////////////////////// |
24 | void found_identifier_sa0() |
25 | { |
26 | found_identifier_flag = true; |
27 | } |
28 | |
29 | template <typename Lexer> |
30 | struct lexer_sa0 : lex::lexer<Lexer> |
31 | { |
32 | lexer_sa0() |
33 | { |
34 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
35 | this->self += identifier [&found_identifier_sa0]; |
36 | } |
37 | lex::token_def<> identifier; |
38 | }; |
39 | |
40 | /////////////////////////////////////////////////////////////////////////////// |
41 | static std::string found_identifier_str; |
42 | |
43 | void found_identifier_sa2(std::string::iterator& start |
44 | , std::string::iterator& end) |
45 | { |
46 | found_identifier_flag = true; |
47 | found_identifier_str = std::string(start, end); |
48 | } |
49 | |
50 | template <typename Lexer> |
51 | struct lexer_sa2 : lex::lexer<Lexer> |
52 | { |
53 | lexer_sa2() |
54 | { |
55 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
56 | this->self += identifier [&found_identifier_sa2]; |
57 | } |
58 | lex::token_def<> identifier; |
59 | }; |
60 | |
61 | /////////////////////////////////////////////////////////////////////////////// |
62 | void found_identifier_sa3_normal(std::string::iterator& start |
63 | , std::string::iterator& end, BOOST_SCOPED_ENUM(lex::pass_flags)& pass) |
64 | { |
65 | BOOST_TEST(pass == lex::pass_flags::pass_normal); |
66 | |
67 | found_identifier_flag = true; |
68 | found_identifier_str = std::string(start, end); |
69 | } |
70 | |
71 | template <typename Lexer> |
72 | struct lexer_sa3_normal : lex::lexer<Lexer> |
73 | { |
74 | lexer_sa3_normal() |
75 | { |
76 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
77 | this->self += identifier [&found_identifier_sa3_normal]; |
78 | } |
79 | lex::token_def<> identifier; |
80 | }; |
81 | |
82 | void found_identifier_sa3_fail(std::string::iterator&, std::string::iterator& |
83 | , BOOST_SCOPED_ENUM(lex::pass_flags)& pass) |
84 | { |
85 | pass = lex::pass_flags::pass_fail; |
86 | } |
87 | |
88 | template <typename Lexer> |
89 | struct lexer_sa3_fail : lex::lexer<Lexer> |
90 | { |
91 | lexer_sa3_fail() |
92 | { |
93 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
94 | this->self += identifier [&found_identifier_sa3_fail]; |
95 | } |
96 | lex::token_def<> identifier; |
97 | }; |
98 | |
99 | void found_identifier_sa3_ignore(std::string::iterator&, std::string::iterator& |
100 | , BOOST_SCOPED_ENUM(lex::pass_flags)& pass) |
101 | { |
102 | pass = lex::pass_flags::pass_ignore; |
103 | } |
104 | |
105 | template <typename Lexer> |
106 | struct lexer_sa3_ignore : lex::lexer<Lexer> |
107 | { |
108 | lexer_sa3_ignore() |
109 | { |
110 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
111 | this->self += identifier [&found_identifier_sa3_ignore]; |
112 | } |
113 | lex::token_def<> identifier; |
114 | }; |
115 | |
116 | /////////////////////////////////////////////////////////////////////////////// |
117 | static std::size_t found_identifier_id = 0; |
118 | |
119 | void found_identifier_sa4(std::string::iterator& start |
120 | , std::string::iterator& end, BOOST_SCOPED_ENUM(lex::pass_flags)& pass |
121 | , std::size_t id) |
122 | { |
123 | BOOST_TEST(pass == lex::pass_flags::pass_normal); |
124 | |
125 | found_identifier_flag = true; |
126 | found_identifier_str = std::string(start, end); |
127 | found_identifier_id = id; |
128 | } |
129 | |
130 | template <typename Lexer> |
131 | struct lexer_sa4 : lex::lexer<Lexer> |
132 | { |
133 | lexer_sa4() |
134 | { |
135 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
136 | this->self += identifier [&found_identifier_sa4]; |
137 | } |
138 | lex::token_def<> identifier; |
139 | }; |
140 | |
141 | void found_identifier_sa4_id(std::string::iterator& start |
142 | , std::string::iterator& end, BOOST_SCOPED_ENUM(lex::pass_flags)& pass |
143 | , std::size_t& id) |
144 | { |
145 | BOOST_TEST(pass == lex::pass_flags::pass_normal); |
146 | |
147 | found_identifier_flag = true; |
148 | found_identifier_str = std::string(start, end); |
149 | found_identifier_id = id; |
150 | id = 1; |
151 | } |
152 | |
153 | template <typename Lexer> |
154 | struct lexer_sa4_id : lex::lexer<Lexer> |
155 | { |
156 | lexer_sa4_id() |
157 | { |
158 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
159 | this->self += identifier [&found_identifier_sa4_id]; |
160 | } |
161 | lex::token_def<> identifier; |
162 | }; |
163 | |
164 | static std::size_t found_identifier_id2 = 0; |
165 | |
166 | bool identifier_token(token_type const& t) |
167 | { |
168 | found_identifier_id2 = t.id(); |
169 | return true; |
170 | } |
171 | |
172 | /////////////////////////////////////////////////////////////////////////////// |
173 | struct found_identifier_sa5 |
174 | { |
175 | template <typename Context> |
176 | void operator()(std::string::iterator& /*start*/ |
177 | , std::string::iterator& /*end*/, BOOST_SCOPED_ENUM(lex::pass_flags)& pass |
178 | , std::size_t& /*id*/, Context& ctx) |
179 | { |
180 | BOOST_TEST(pass == lex::pass_flags::pass_normal); |
181 | |
182 | found_identifier_flag = true; |
183 | found_identifier_str = std::string(ctx.get_value().begin(), ctx.get_value().end()); |
184 | } |
185 | }; |
186 | |
187 | template <typename Lexer> |
188 | struct lexer_sa5 : lex::lexer<Lexer> |
189 | { |
190 | lexer_sa5() |
191 | { |
192 | identifier = "[a-zA-Z][_a-zA-Z0-9]*" ; |
193 | this->self += identifier [found_identifier_sa5()]; |
194 | } |
195 | lex::token_def<> identifier; |
196 | }; |
197 | |
198 | /////////////////////////////////////////////////////////////////////////////// |
199 | int main() |
200 | { |
201 | std::string identifier ("id_1234" ); |
202 | std::string::iterator first = identifier.begin(); |
203 | std::string::iterator last = identifier.end(); |
204 | |
205 | // test semantic action taking no arguments |
206 | found_identifier_flag = false; |
207 | { |
208 | lexer_sa0<lexer_type> sa0; |
209 | BOOST_TEST(lex::tokenize(first, last, sa0)); |
210 | BOOST_TEST(first == last); |
211 | BOOST_TEST(found_identifier_flag); |
212 | } |
213 | |
214 | // test semantic action taking two arguments (iterator pair for matched |
215 | // sequence) |
216 | found_identifier_flag = false; |
217 | found_identifier_str.clear(); |
218 | first = identifier.begin(); |
219 | { |
220 | lexer_sa2<lexer_type> sa2; |
221 | BOOST_TEST(lex::tokenize(first, last, sa2)); |
222 | BOOST_TEST(first == last); |
223 | BOOST_TEST(found_identifier_flag); |
224 | BOOST_TEST(found_identifier_str == identifier); |
225 | } |
226 | |
227 | // test semantic action taking three arguments (iterator pair for matched |
228 | // sequence and pass_flags) - pass_flags::pass_normal |
229 | found_identifier_flag = false; |
230 | found_identifier_str.clear(); |
231 | first = identifier.begin(); |
232 | { |
233 | lexer_sa3_normal<lexer_type> sa3; |
234 | BOOST_TEST(lex::tokenize(first, last, sa3)); |
235 | BOOST_TEST(first == last); |
236 | BOOST_TEST(found_identifier_flag); |
237 | BOOST_TEST(found_identifier_str == identifier); |
238 | } |
239 | |
240 | // test semantic action taking three arguments (iterator pair for matched |
241 | // sequence and pass_flags) - pass_flags::pass_fail |
242 | first = identifier.begin(); |
243 | { |
244 | lexer_sa3_fail<lexer_type> sa3; |
245 | BOOST_TEST(!lex::tokenize(first, last, sa3)); |
246 | BOOST_TEST(first != last); |
247 | } |
248 | |
249 | // test semantic action taking three arguments (iterator pair for matched |
250 | // sequence and pass_flags) - pass_flags::pass_ignore |
251 | first = identifier.begin(); |
252 | { |
253 | lexer_sa3_ignore<lexer_type> sa3; |
254 | BOOST_TEST(lex::tokenize(first, last, sa3)); |
255 | BOOST_TEST(first == last); |
256 | } |
257 | |
258 | // test semantic action taking four arguments (iterator pair for matched |
259 | // sequence and pass_flags, and token id) |
260 | found_identifier_flag = false; |
261 | found_identifier_str.clear(); |
262 | first = identifier.begin(); |
263 | found_identifier_id = 0; |
264 | { |
265 | lexer_sa4<lexer_type> sa4; |
266 | BOOST_TEST(lex::tokenize(first, last, sa4)); |
267 | BOOST_TEST(first == last); |
268 | BOOST_TEST(found_identifier_flag); |
269 | BOOST_TEST(found_identifier_str == identifier); |
270 | BOOST_TEST(found_identifier_id == lex::min_token_id); |
271 | } |
272 | |
273 | found_identifier_flag = false; |
274 | found_identifier_str.clear(); |
275 | first = identifier.begin(); |
276 | found_identifier_id = 0; |
277 | found_identifier_id2 = 0; |
278 | { |
279 | lexer_sa4_id<lexer_type> sa4; |
280 | BOOST_TEST(lex::tokenize(first, last, sa4, identifier_token)); |
281 | BOOST_TEST(first == last); |
282 | BOOST_TEST(found_identifier_flag); |
283 | BOOST_TEST(found_identifier_str == identifier); |
284 | BOOST_TEST(found_identifier_id == lex::min_token_id); |
285 | BOOST_TEST(found_identifier_id2 == 1); |
286 | } |
287 | |
288 | // test semantic action taking four arguments (iterator pair for matched |
289 | // sequence and pass_flags, token id, and context) |
290 | found_identifier_flag = false; |
291 | found_identifier_str.clear(); |
292 | first = identifier.begin(); |
293 | found_identifier_id = 0; |
294 | found_identifier_id2 = 0; |
295 | { |
296 | lexer_sa5<lexer_type> sa5; |
297 | BOOST_TEST(lex::tokenize(first, last, sa5)); |
298 | BOOST_TEST(first == last); |
299 | BOOST_TEST(found_identifier_flag); |
300 | BOOST_TEST(found_identifier_str == identifier); |
301 | } |
302 | |
303 | return boost::report_errors(); |
304 | } |
305 | |