| 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 | |