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
15namespace lex = boost::spirit::lex;
16
17typedef lex::lexertl::token<std::string::iterator> token_type;
18typedef lex::lexertl::actor_lexer<token_type> lexer_type;
19
20///////////////////////////////////////////////////////////////////////////////
21static bool found_identifier_flag = false;
22
23///////////////////////////////////////////////////////////////////////////////
24void found_identifier_sa0()
25{
26 found_identifier_flag = true;
27}
28
29template <typename Lexer>
30struct 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///////////////////////////////////////////////////////////////////////////////
41static std::string found_identifier_str;
42
43void 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
50template <typename Lexer>
51struct 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///////////////////////////////////////////////////////////////////////////////
62void 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
71template <typename Lexer>
72struct 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
82void 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
88template <typename Lexer>
89struct 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
99void 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
105template <typename Lexer>
106struct 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///////////////////////////////////////////////////////////////////////////////
117static std::size_t found_identifier_id = 0;
118
119void 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
130template <typename Lexer>
131struct 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
141void 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
153template <typename Lexer>
154struct 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
164static std::size_t found_identifier_id2 = 0;
165
166bool identifier_token(token_type const& t)
167{
168 found_identifier_id2 = t.id();
169 return true;
170}
171
172///////////////////////////////////////////////////////////////////////////////
173struct 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
187template <typename Lexer>
188struct 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///////////////////////////////////////////////////////////////////////////////
199int 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

source code of boost/libs/spirit/test/lex/semantic_actions.cpp