| 1 | /*============================================================================= |
| 2 | Copyright (c) 2001-2011 Hartmut Kaiser |
| 3 | http://spirit.sourceforge.net/ |
| 4 | |
| 5 | Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 6 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 7 | =============================================================================*/ |
| 8 | |
| 9 | //[reference_karma_includes |
| 10 | #include <boost/spirit/include/karma.hpp> |
| 11 | #include <boost/spirit/include/support_utree.hpp> |
| 12 | #include <boost/phoenix/core.hpp> |
| 13 | #include <boost/phoenix/operator.hpp> |
| 14 | #include <boost/fusion/include/std_pair.hpp> |
| 15 | #include <boost/proto/deep_copy.hpp> |
| 16 | #include <iostream> |
| 17 | #include <string> |
| 18 | //] |
| 19 | |
| 20 | //[reference_karma_includes_simple |
| 21 | #include <boost/spirit/include/karma.hpp> |
| 22 | #include <iostream> |
| 23 | #include <string> |
| 24 | //] |
| 25 | |
| 26 | //[reference_karma_output_iterator |
| 27 | typedef std::back_insert_iterator<std::string> output_iterator_type; |
| 28 | //] |
| 29 | |
| 30 | //[reference_karma_test |
| 31 | template <typename G> |
| 32 | void test_generator(char const* expected, G const& g) |
| 33 | { |
| 34 | std::string s; |
| 35 | std::back_insert_iterator<std::string> out(s); |
| 36 | if (boost::spirit::karma::generate(out, g) && s == expected) |
| 37 | std::cout << "ok" << std::endl; |
| 38 | else |
| 39 | std::cout << "fail" << std::endl; |
| 40 | } |
| 41 | //] |
| 42 | |
| 43 | //[reference_karma_test_attr |
| 44 | template <typename G, typename T> |
| 45 | void test_generator_attr(char const* expected, G const& g, T const& attr) |
| 46 | { |
| 47 | std::string s; |
| 48 | std::back_insert_iterator<std::string> out(s); |
| 49 | if (boost::spirit::karma::generate(out, g, attr) && s == expected) |
| 50 | std::cout << "ok" << std::endl; |
| 51 | else |
| 52 | std::cout << "fail" << std::endl; |
| 53 | } |
| 54 | //] |
| 55 | |
| 56 | //[reference_karma_test_attr2 |
| 57 | template <typename G, typename T1, typename T2> |
| 58 | void test_generator_attr(char const* expected, G const& g, T1 const& attr1, |
| 59 | T2 const& attr2) |
| 60 | { |
| 61 | std::string s; |
| 62 | std::back_insert_iterator<std::string> out(s); |
| 63 | if (boost::spirit::karma::generate(out, g, attr1, attr2) && s == expected) |
| 64 | std::cout << "ok" << std::endl; |
| 65 | else |
| 66 | std::cout << "fail" << std::endl; |
| 67 | } |
| 68 | //] |
| 69 | |
| 70 | //[reference_karma_test_attr_delim |
| 71 | template <typename G, typename Delimiter, typename T> |
| 72 | void test_generator_attr_delim(char const* expected, G const& g, Delimiter const& d, T const& attr) |
| 73 | { |
| 74 | std::string s; |
| 75 | std::back_insert_iterator<std::string> out(s); |
| 76 | if (boost::spirit::karma::generate_delimited(out, g, d, attr) && s == expected) |
| 77 | std::cout << "ok" << std::endl; |
| 78 | else |
| 79 | std::cout << "fail" << std::endl; |
| 80 | } |
| 81 | //] |
| 82 | |
| 83 | //[reference_karma_binary_test |
| 84 | template <typename G> |
| 85 | void test_binary_generator(char const* expected, std::size_t size, G const& g) |
| 86 | { |
| 87 | std::string s; |
| 88 | std::back_insert_iterator<std::string> out(s); |
| 89 | if (boost::spirit::karma::generate(out, g) && !std::memcmp(s1: s.c_str(), s2: expected, n: size)) |
| 90 | std::cout << "ok" << std::endl; |
| 91 | else |
| 92 | std::cout << "fail" << std::endl; |
| 93 | } |
| 94 | //] |
| 95 | |
| 96 | //[reference_karma_binary_test_attr |
| 97 | template <typename G, typename T> |
| 98 | void test_binary_generator_attr(char const* expected, std::size_t size, G const& g, T const& attr) |
| 99 | { |
| 100 | std::string s; |
| 101 | std::back_insert_iterator<std::string> out(s); |
| 102 | if (boost::spirit::karma::generate(out, g, attr) && !std::memcmp(s1: s.c_str(), s2: expected, n: size)) |
| 103 | std::cout << "ok" << std::endl; |
| 104 | else |
| 105 | std::cout << "fail" << std::endl; |
| 106 | } |
| 107 | //] |
| 108 | |
| 109 | //[reference_karma_complex |
| 110 | // a simple complex number representation z = a + bi |
| 111 | struct complex |
| 112 | { |
| 113 | complex (double a, double b) |
| 114 | : a(a), b(b) |
| 115 | {} |
| 116 | |
| 117 | double a; |
| 118 | double b; |
| 119 | }; |
| 120 | //] |
| 121 | |
| 122 | //[reference_karma_stream_complex |
| 123 | // define streaming operator for the type complex |
| 124 | std::ostream& |
| 125 | operator<< (std::ostream& os, complex const& z) |
| 126 | { |
| 127 | os << "{" << z.a << "," << z.b << "}" ; |
| 128 | return os; |
| 129 | } |
| 130 | //] |
| 131 | |
| 132 | //[reference_karma_auto_complex |
| 133 | /*`The following construct is required to allow the `complex` data structure |
| 134 | to be utilized as a __fusion__ sequence. This is required as we will |
| 135 | emit output for this data structure with a __karma__ sequence: |
| 136 | `'{' << karma::double_ << ',' << karma::double_ << '}'`. |
| 137 | */ |
| 138 | BOOST_FUSION_ADAPT_STRUCT( |
| 139 | complex, |
| 140 | (double, a) |
| 141 | (double, b) |
| 142 | ) |
| 143 | |
| 144 | /*`We add a specialization for the create_generator customization point |
| 145 | defining a custom output format for the complex type. Generally, any |
| 146 | specialization for create_generator is expected to return the proto |
| 147 | expression to be used to generate output for the type the customization |
| 148 | point has been specialized for. |
| 149 | */ |
| 150 | /*`We need to utilize `proto::deep_copy` as the expression contains literals |
| 151 | (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto |
| 152 | expression by reference only. The deep copy converts the proto tree to |
| 153 | hold this by value. The deep copy operation can be left out for simpler |
| 154 | proto expressions (not containing references to temporaries). Alternatively |
| 155 | you could use the `proto::make_expr` facility to build the required |
| 156 | proto expression. |
| 157 | */ |
| 158 | namespace boost { namespace spirit { namespace traits |
| 159 | { |
| 160 | template <> |
| 161 | struct create_generator<complex> |
| 162 | { |
| 163 | typedef proto::result_of::deep_copy< |
| 164 | BOOST_TYPEOF('{' << karma::double_ << ',' << karma::double_ << '}') |
| 165 | >::type type; |
| 166 | |
| 167 | static type call() |
| 168 | { |
| 169 | return proto::deep_copy( |
| 170 | e: '{' << karma::double_ << ',' << karma::double_ << '}'); |
| 171 | } |
| 172 | }; |
| 173 | }}} |
| 174 | //] |
| 175 | |
| 176 | //[reference_karma_auxiliary_attr_cast_data1 |
| 177 | // this is just a test structure we want to use in place of an int |
| 178 | struct int_data |
| 179 | { |
| 180 | int i; |
| 181 | }; |
| 182 | |
| 183 | // we provide a custom attribute transformation to allow its use as an int |
| 184 | namespace boost { namespace spirit { namespace traits |
| 185 | { |
| 186 | template <> |
| 187 | struct transform_attribute<int_data const, int, karma::domain> |
| 188 | { |
| 189 | typedef int type; |
| 190 | static int pre(int_data const& d) { return d.i; } |
| 191 | }; |
| 192 | }}} |
| 193 | //] |
| 194 | |
| 195 | namespace client |
| 196 | { |
| 197 | using boost::spirit::karma::grammar; |
| 198 | using boost::spirit::karma::rule; |
| 199 | using boost::spirit::ascii::space_type; |
| 200 | |
| 201 | //[karma_reference_grammar_definition |
| 202 | /*`Basic grammar usage: |
| 203 | */ |
| 204 | struct num_list : grammar<output_iterator_type, space_type, std::vector<int>()> |
| 205 | { |
| 206 | num_list() : base_type(start) |
| 207 | { |
| 208 | using boost::spirit::int_; |
| 209 | num = int_; |
| 210 | start = num << *(',' << num); |
| 211 | } |
| 212 | |
| 213 | rule<output_iterator_type, space_type, std::vector<int>()> start; |
| 214 | rule<output_iterator_type, space_type, int()> num; |
| 215 | }; |
| 216 | //] |
| 217 | } |
| 218 | |
| 219 | int main() |
| 220 | { |
| 221 | /////////////////////////////////////////////////////////////////////////// |
| 222 | // Operators |
| 223 | /////////////////////////////////////////////////////////////////////////// |
| 224 | { |
| 225 | //[reference_karma_using_declarations_sequence |
| 226 | using boost::spirit::karma::double_; |
| 227 | //] |
| 228 | |
| 229 | //[reference_karma_sequence |
| 230 | test_generator_attr(expected: "1.0,2.0" , g: double_ << ',' << double_, attr: std::make_pair(x: 1.0, y: 2.0)); |
| 231 | //] |
| 232 | } |
| 233 | |
| 234 | { |
| 235 | //[reference_karma_using_declarations_alternative |
| 236 | using boost::spirit::karma::double_; |
| 237 | using boost::spirit::karma::ascii::string; |
| 238 | //] |
| 239 | |
| 240 | //[reference_karma_alternative1 |
| 241 | boost::variant<std::string, double> v1(1.0); |
| 242 | test_generator_attr(expected: "1.0" , g: string | double_, attr: v1); |
| 243 | test_generator_attr(expected: "2.0" , g: string | double_, attr: 2.0); |
| 244 | //] |
| 245 | |
| 246 | //[reference_karma_alternative2 |
| 247 | boost::variant<std::string, double> v2("example" ); |
| 248 | test_generator_attr(expected: "example" , g: string | double_, attr: v2); |
| 249 | test_generator_attr(expected: "example" , g: string | double_, attr: "example" ); |
| 250 | //] |
| 251 | } |
| 252 | |
| 253 | { |
| 254 | //[reference_karma_using_declarations_kleene |
| 255 | using boost::spirit::karma::double_; |
| 256 | using boost::spirit::karma::space; |
| 257 | //] |
| 258 | |
| 259 | //[reference_karma_kleene |
| 260 | std::vector<double> v; |
| 261 | v.push_back(x: 1.0); |
| 262 | v.push_back(x: 2.0); |
| 263 | v.push_back(x: 3.0); |
| 264 | test_generator_attr_delim(expected: "1.0 2.0 3.0 " , g: *double_, d: space, attr: v); |
| 265 | //] |
| 266 | } |
| 267 | |
| 268 | { |
| 269 | //[reference_karma_using_declarations_plus |
| 270 | using boost::spirit::karma::double_; |
| 271 | using boost::spirit::karma::space; |
| 272 | //] |
| 273 | |
| 274 | //[reference_karma_plus1 |
| 275 | std::vector<double> v1; |
| 276 | v1.push_back(x: 1.0); |
| 277 | v1.push_back(x: 2.0); |
| 278 | v1.push_back(x: 3.0); |
| 279 | test_generator_attr_delim(expected: "1.0 2.0 3.0 " , g: +double_, d: space, attr: v1); |
| 280 | //] |
| 281 | |
| 282 | //[reference_karma_plus2 |
| 283 | std::vector<double> v2; // empty container |
| 284 | test_generator_attr(expected: "empty" , g: +double_ | "empty" , attr: v2); |
| 285 | //] |
| 286 | } |
| 287 | |
| 288 | { |
| 289 | //[reference_karma_using_declarations_list |
| 290 | using boost::spirit::karma::double_; |
| 291 | //] |
| 292 | |
| 293 | //[reference_karma_list |
| 294 | std::vector<double> v1; |
| 295 | v1.push_back(x: 1.0); |
| 296 | test_generator_attr(expected: "1.0" , g: double_ % ',', attr: v1); |
| 297 | |
| 298 | v1.push_back(x: 2.0); |
| 299 | test_generator_attr(expected: "1.0,2.0" , g: double_ % ',', attr: v1); |
| 300 | //] |
| 301 | } |
| 302 | |
| 303 | { |
| 304 | //[reference_karma_using_declarations_optional |
| 305 | using boost::spirit::karma::double_; |
| 306 | //] |
| 307 | |
| 308 | //[reference_karma_optional1 |
| 309 | boost::optional<double> val(1.0); |
| 310 | test_generator_attr(expected: "1.0" , g: -double_, attr: val); |
| 311 | test_generator_attr(expected: "2.0" , g: -double_, attr: 2.0); |
| 312 | //] |
| 313 | } |
| 314 | { |
| 315 | using boost::spirit::karma::double_; |
| 316 | |
| 317 | //[reference_karma_optional2 |
| 318 | boost::optional<double> val; // empty optional |
| 319 | test_generator_attr(expected: "" , g: -double_, attr: val); |
| 320 | //] |
| 321 | } |
| 322 | |
| 323 | { |
| 324 | //[reference_karma_using_declarations_and_predicate |
| 325 | using boost::spirit::karma::double_; |
| 326 | using boost::spirit::karma::ascii::char_; |
| 327 | using boost::spirit::karma::ascii::string; |
| 328 | using boost::phoenix::ref; |
| 329 | //] |
| 330 | |
| 331 | //[reference_karma_and_predicate |
| 332 | test_generator_attr(expected: "b" , g: &char_('a') << 'b' | 'c', attr: 'a'); |
| 333 | test_generator_attr(expected: "c" , g: &char_('a') << 'b' | 'c', attr: 'x'); |
| 334 | |
| 335 | test_generator_attr(expected: "abc" , g: &string("123" ) << "abc" | "def" , attr: "123" ); |
| 336 | test_generator_attr(expected: "def" , g: &string("123" ) << "abc" | "def" , attr: "456" ); |
| 337 | //] |
| 338 | } |
| 339 | |
| 340 | { |
| 341 | //[reference_karma_using_declarations_not_predicate |
| 342 | using boost::spirit::karma::double_; |
| 343 | using boost::spirit::karma::ascii::char_; |
| 344 | using boost::spirit::karma::ascii::string; |
| 345 | using boost::phoenix::ref; |
| 346 | //] |
| 347 | |
| 348 | //[reference_karma_not_predicate |
| 349 | test_generator_attr(expected: "c" , g: !char_('a') << 'b' | 'c', attr: 'a'); |
| 350 | test_generator_attr(expected: "b" , g: !char_('a') << 'b' | 'c', attr: 'x'); |
| 351 | |
| 352 | test_generator_attr(expected: "def" , g: !string("123" ) << "abc" | "def" , attr: "123" ); |
| 353 | test_generator_attr(expected: "abc" , g: !string("123" ) << "abc" | "def" , attr: "456" ); |
| 354 | //] |
| 355 | } |
| 356 | |
| 357 | /////////////////////////////////////////////////////////////////////////// |
| 358 | // Directives |
| 359 | /////////////////////////////////////////////////////////////////////////// |
| 360 | { |
| 361 | //[reference_karma_using_declarations_alignment |
| 362 | using boost::spirit::karma::double_; |
| 363 | using boost::spirit::karma::left_align; |
| 364 | using boost::spirit::karma::center; |
| 365 | using boost::spirit::karma::right_align; |
| 366 | //] |
| 367 | |
| 368 | //[reference_karma_alignment |
| 369 | std::pair<double, double> p (1.0, 2.0); |
| 370 | test_generator_attr(expected: "1.0 |2.0" , g: left_align(8)[double_] << '|' << double_, attr: p); |
| 371 | test_generator_attr(expected: " 1.0 |2.0" , g: center(8)[double_] << '|' << double_, attr: p); |
| 372 | test_generator_attr(expected: " 1.0|2.0" , g: right_align(8)[double_] << '|' << double_, attr: p); |
| 373 | //] |
| 374 | } |
| 375 | |
| 376 | { |
| 377 | //[reference_karma_using_declarations_repeat |
| 378 | using boost::spirit::karma::double_; |
| 379 | using boost::spirit::karma::repeat; |
| 380 | //] |
| 381 | |
| 382 | //[reference_karma_repeat |
| 383 | std::vector<double> v; |
| 384 | v.push_back(x: 1.0); |
| 385 | v.push_back(x: 2.0); |
| 386 | v.push_back(x: 3.0); |
| 387 | |
| 388 | test_generator_attr(expected: "[1.0][2.0][3.0]" , g: repeat['[' << double_ << ']'], attr: v); |
| 389 | test_generator_attr(expected: "[1.0][2.0]" , g: repeat(2)['[' << double_ << ']'], attr: v); |
| 390 | |
| 391 | // fails because of insufficient number of items |
| 392 | test_generator_attr(expected: "" , g: repeat(4)['[' << double_ << ']'], attr: v); |
| 393 | //] |
| 394 | } |
| 395 | |
| 396 | { |
| 397 | //[reference_karma_using_declarations_delimit |
| 398 | using boost::spirit::karma::double_; |
| 399 | using boost::spirit::karma::delimit; |
| 400 | using boost::spirit::karma::verbatim; |
| 401 | //] |
| 402 | |
| 403 | //[reference_karma_delimit |
| 404 | test_generator_attr(expected: "[ 2.0 , 4.3 ] " , |
| 405 | g: delimit['[' << double_ << ',' << double_ << ']'], attr1: 2.0, attr2: 4.3); |
| 406 | test_generator_attr(expected: "[*2.0*,*4.3*]*" , |
| 407 | g: delimit('*')['[' << double_ << ',' << double_ << ']'], attr1: 2.0, attr2: 4.3); |
| 408 | test_generator_attr(expected: "[2.0, 4.3 ] " , |
| 409 | g: delimit[verbatim['[' << double_ << ','] << double_ << ']'], attr1: 2.0, attr2: 4.3); |
| 410 | //] |
| 411 | } |
| 412 | |
| 413 | { |
| 414 | //[reference_karma_using_declarations_upperlower |
| 415 | using boost::spirit::karma::double_; |
| 416 | using boost::spirit::ascii::upper; |
| 417 | using boost::spirit::ascii::lower; |
| 418 | //] |
| 419 | |
| 420 | //[reference_karma_upperlower |
| 421 | test_generator_attr(expected: "abc:2.0e-06" , g: lower["ABC:" << double_], attr: 2e-6); |
| 422 | test_generator_attr(expected: "ABC:2.0E-06" , g: upper["abc:" << double_], attr: 2e-6); |
| 423 | //] |
| 424 | } |
| 425 | |
| 426 | { |
| 427 | //[reference_karma_using_declarations_maxwidth |
| 428 | using boost::spirit::karma::double_; |
| 429 | using boost::spirit::karma::maxwidth; |
| 430 | using boost::spirit::karma::left_align; |
| 431 | using boost::spirit::karma::right_align; |
| 432 | //] |
| 433 | |
| 434 | //[reference_karma_maxwidth |
| 435 | test_generator(expected: "01234" , g: maxwidth(5)["0123456789" ]); |
| 436 | test_generator(expected: " 012" , g: maxwidth(5)[right_align(12)["0123456789" ]]); |
| 437 | test_generator(expected: "0123 " , g: maxwidth(8)[left_align(8)["0123" ]]); |
| 438 | //] |
| 439 | } |
| 440 | |
| 441 | { |
| 442 | //[reference_karma_using_declarations_buffer |
| 443 | using boost::spirit::karma::double_; |
| 444 | using boost::spirit::karma::buffer; |
| 445 | //] |
| 446 | |
| 447 | //[reference_karma_buffer |
| 448 | std::vector<double> v; // empty container |
| 449 | test_generator_attr(expected: "" , g: -buffer['[' << +double_ << ']'], attr: v); |
| 450 | |
| 451 | v.push_back(x: 1.0); // now, fill the container |
| 452 | v.push_back(x: 2.0); |
| 453 | test_generator_attr(expected: "[1.02.0]" , g: buffer['[' << +double_ << ']'], attr: v); |
| 454 | //] |
| 455 | } |
| 456 | |
| 457 | { |
| 458 | //[reference_karma_using_declarations_omit |
| 459 | using boost::spirit::karma::double_; |
| 460 | using boost::spirit::karma::omit; |
| 461 | //] |
| 462 | |
| 463 | //[reference_karma_omit |
| 464 | std::pair<double, double> p (1.0, 2.0); |
| 465 | test_generator_attr(expected: "2.0" , g: omit[double_] << double_, attr: p); |
| 466 | //] |
| 467 | } |
| 468 | |
| 469 | { |
| 470 | //[reference_karma_using_declarations_duplicate |
| 471 | using boost::spirit::karma::double_; |
| 472 | using boost::spirit::karma::duplicate; |
| 473 | using boost::spirit::karma::space; |
| 474 | //] |
| 475 | |
| 476 | //[reference_karma_duplicate |
| 477 | test_generator_attr(expected: "2.02.0" , g: duplicate[double_ << double_], attr: 2.0); |
| 478 | test_generator_attr_delim(expected: "2.0 2.0 " , g: duplicate[double_ << double_], d: space, attr: 2.0); |
| 479 | //] |
| 480 | } |
| 481 | |
| 482 | { |
| 483 | //[reference_karma_using_declarations_columns |
| 484 | using boost::spirit::karma::double_; |
| 485 | using boost::spirit::karma::columns; |
| 486 | using boost::spirit::karma::space; |
| 487 | //] |
| 488 | |
| 489 | //[reference_karma_columns |
| 490 | std::vector<double> v; |
| 491 | v.push_back(x: 1.0); |
| 492 | v.push_back(x: 2.0); |
| 493 | v.push_back(x: 3.0); |
| 494 | test_generator_attr(expected: "1.0\n2.0\n3.0\n" , g: columns(1)[*double_], attr: v); |
| 495 | test_generator_attr_delim(expected: "1.0 2.0 \n3.0 \n" , g: columns(2)[*double_], d: space, attr: v); |
| 496 | //] |
| 497 | } |
| 498 | |
| 499 | { |
| 500 | //[reference_karma_using_declarations_bool |
| 501 | using boost::spirit::karma::bool_; |
| 502 | using boost::spirit::karma::lit; |
| 503 | //] |
| 504 | |
| 505 | //[reference_karma_bool |
| 506 | test_generator(expected: "true" , g: lit(true)); |
| 507 | test_generator(expected: "false" , g: bool_(false)); |
| 508 | test_generator_attr(expected: "true" , g: bool_(true), attr: true); |
| 509 | test_generator_attr(expected: "" , g: bool_(true), attr: false); // fails (as true != false)! |
| 510 | test_generator_attr(expected: "false" , g: bool_, attr: false); |
| 511 | //] |
| 512 | } |
| 513 | |
| 514 | { |
| 515 | //[reference_karma_using_declarations_int |
| 516 | using boost::spirit::karma::int_; |
| 517 | using boost::spirit::karma::lit; |
| 518 | //] |
| 519 | |
| 520 | //[reference_karma_int |
| 521 | test_generator(expected: "-2" , g: lit(-2)); |
| 522 | test_generator(expected: "-2" , g: int_(-2)); |
| 523 | test_generator_attr(expected: "-2" , g: int_(-2), attr: -2); |
| 524 | test_generator_attr(expected: "" , g: int_(-2), attr: 3); // fails (as -2 != 3)! |
| 525 | test_generator_attr(expected: "-2" , g: int_, attr: -2); |
| 526 | //] |
| 527 | } |
| 528 | |
| 529 | { |
| 530 | //[reference_karma_using_declarations_uint |
| 531 | using boost::spirit::karma::uint_; |
| 532 | using boost::spirit::karma::lit; |
| 533 | //] |
| 534 | |
| 535 | //[reference_karma_uint |
| 536 | test_generator(expected: "2" , g: lit(2U)); |
| 537 | test_generator(expected: "2" , g: uint_(2)); |
| 538 | test_generator_attr(expected: "2" , g: uint_(2), attr: 2); |
| 539 | test_generator_attr(expected: "" , g: uint_(2), attr: 3); // fails (as 2 != 3)! |
| 540 | test_generator_attr(expected: "2" , g: uint_, attr: 2); |
| 541 | //] |
| 542 | } |
| 543 | |
| 544 | { |
| 545 | //[reference_karma_using_declarations_real |
| 546 | using boost::spirit::karma::double_; |
| 547 | using boost::spirit::karma::lit; |
| 548 | //] |
| 549 | |
| 550 | //[reference_karma_real |
| 551 | test_generator(expected: "2.0" , g: lit(2.0)); |
| 552 | test_generator(expected: "2.0" , g: double_(2)); |
| 553 | test_generator_attr(expected: "2.0" , g: double_(2.0), attr: 2.0); |
| 554 | test_generator_attr(expected: "" , g: double_(2.0), attr: 3.0); // fails (as 2.0 != 3.0)! |
| 555 | test_generator_attr(expected: "-2.0" , g: double_, attr: -2.0); |
| 556 | |
| 557 | test_generator_attr(expected: "1.234e05" , g: double_, attr: 1234.0e2); |
| 558 | test_generator_attr(expected: "1.234e-06" , g: double_, attr: 0.000001234); |
| 559 | //] |
| 560 | } |
| 561 | |
| 562 | { |
| 563 | //[reference_karma_using_declarations_char |
| 564 | using boost::spirit::karma::lit; |
| 565 | using boost::spirit::ascii::char_; |
| 566 | //] |
| 567 | |
| 568 | //[reference_karma_char |
| 569 | test_generator(expected: "A" , g: 'A'); |
| 570 | test_generator(expected: "A" , g: lit('A')); |
| 571 | |
| 572 | test_generator_attr(expected: "a" , g: char_, attr: 'a'); |
| 573 | test_generator(expected: "A" , g: char_('A')); |
| 574 | test_generator_attr(expected: "A" , g: char_('A'), attr: 'A'); |
| 575 | test_generator_attr(expected: "" , g: char_('A'), attr: 'B'); // fails (as 'A' != 'B') |
| 576 | |
| 577 | test_generator_attr(expected: "A" , g: char_('A', 'Z'), attr: 'A'); |
| 578 | test_generator_attr(expected: "" , g: char_('A', 'Z'), attr: 'a'); // fails (as 'a' does not belong to 'A'...'Z') |
| 579 | |
| 580 | test_generator_attr(expected: "k" , g: char_("a-z0-9" ), attr: 'k'); |
| 581 | test_generator_attr(expected: "" , g: char_("a-z0-9" ), attr: 'A'); // fails (as 'A' does not belong to "a-z0-9") |
| 582 | //] |
| 583 | } |
| 584 | |
| 585 | { |
| 586 | //[reference_karma_using_declarations_char_class |
| 587 | using boost::spirit::karma::alpha; |
| 588 | using boost::spirit::karma::upper; |
| 589 | //] |
| 590 | |
| 591 | //[reference_karma_char_class |
| 592 | test_generator_attr(expected: "a" , g: alpha, attr: 'a'); |
| 593 | test_generator_attr(expected: "A" , g: alpha, attr: 'A'); |
| 594 | test_generator_attr(expected: "" , g: alpha, attr: '1'); // fails (as isalpha('1') is false) |
| 595 | test_generator_attr(expected: "A" , g: upper[alpha], attr: 'A'); |
| 596 | test_generator_attr(expected: "" , g: upper[alpha], attr: 'a'); // fails (as isupper('a') is false) |
| 597 | //] |
| 598 | } |
| 599 | |
| 600 | /////////////////////////////////////////////////////////////////////////// |
| 601 | // string |
| 602 | { |
| 603 | //[reference_karma_using_declarations_string |
| 604 | using boost::spirit::karma::lit; |
| 605 | using boost::spirit::ascii::string; |
| 606 | //] |
| 607 | |
| 608 | //[reference_karma_string |
| 609 | test_generator(expected: "abc" , g: "abc" ); |
| 610 | test_generator(expected: "abc" , g: lit("abc" )); |
| 611 | test_generator(expected: "abc" , g: lit(std::string("abc" ))); |
| 612 | |
| 613 | test_generator_attr(expected: "abc" , g: string, attr: "abc" ); |
| 614 | test_generator(expected: "abc" , g: string("abc" )); |
| 615 | test_generator(expected: "abc" , g: string(std::string("abc" ))); |
| 616 | |
| 617 | test_generator_attr(expected: "abc" , g: string("abc" ), attr: "abc" ); |
| 618 | test_generator_attr(expected: "" , g: string("abc" ), attr: "cba" ); // fails (as "abc" != "cba") |
| 619 | //] |
| 620 | } |
| 621 | |
| 622 | /////////////////////////////////////////////////////////////////////////// |
| 623 | // auxiliary |
| 624 | { |
| 625 | //[reference_karma_using_declarations_eol |
| 626 | using boost::spirit::karma::eol; |
| 627 | //] |
| 628 | |
| 629 | //[reference_karma_eol |
| 630 | test_generator(expected: "\n" , g: eol); |
| 631 | test_generator(expected: "abc\n" , g: "abc" << eol); |
| 632 | //] |
| 633 | } |
| 634 | |
| 635 | { |
| 636 | //[reference_karma_using_declarations_attr_cast |
| 637 | using boost::spirit::karma::int_; |
| 638 | //] |
| 639 | |
| 640 | //[reference_karma_attr_cast1 |
| 641 | int_data d = { .i: 1 }; |
| 642 | test_generator_attr(expected: "1" , g: boost::spirit::karma::attr_cast(expr: int_), attr: d); |
| 643 | //] |
| 644 | } |
| 645 | |
| 646 | { |
| 647 | //[reference_karma_using_declarations_eps |
| 648 | using boost::spirit::karma::eps; |
| 649 | using boost::phoenix::val; |
| 650 | //] |
| 651 | |
| 652 | //[reference_karma_eps |
| 653 | test_generator(expected: "abc" , g: eps[std::cout << val(t: "starting eps example" )] << "abc" ); |
| 654 | test_generator(expected: "abc" , g: eps(true) << "abc" ); |
| 655 | test_generator(expected: "" , g: eps(false) << "abc" ); // fails as eps expression is 'false' |
| 656 | //] |
| 657 | } |
| 658 | |
| 659 | { |
| 660 | //[reference_karma_using_declarations_lazy |
| 661 | namespace karma = boost::spirit::karma; |
| 662 | using boost::spirit::karma::_1; |
| 663 | using boost::spirit::ascii::string; |
| 664 | using boost::phoenix::val; |
| 665 | //] |
| 666 | |
| 667 | //[reference_karma_lazy |
| 668 | test_generator_attr(expected: "abc" , g: karma::lazy(f: val(t: string)), attr: "abc" ); |
| 669 | test_generator(expected: "abc" , g: karma::lazy(f: val(t: string))[_1 = "abc" ]); |
| 670 | //] |
| 671 | } |
| 672 | |
| 673 | /////////////////////////////////////////////////////////////////////////// |
| 674 | // stream module |
| 675 | { |
| 676 | //[reference_karma_using_declarations_stream |
| 677 | using boost::spirit::karma::stream; |
| 678 | //] |
| 679 | |
| 680 | //[reference_karma_stream |
| 681 | test_generator_attr(expected: "abc" , g: stream, attr: "abc" ); |
| 682 | test_generator(expected: "abc" , g: stream("abc" )); |
| 683 | test_generator_attr(expected: "{1.2,2.4}" , g: stream, attr: complex(1.2, 2.4)); |
| 684 | test_generator(expected: "{1.2,2.4}" , g: stream(complex(1.2, 2.4))); |
| 685 | //] |
| 686 | } |
| 687 | |
| 688 | /////////////////////////////////////////////////////////////////////////// |
| 689 | // auto module |
| 690 | { |
| 691 | //[reference_karma_using_declarations_auto |
| 692 | using boost::spirit::karma::auto_; |
| 693 | //] |
| 694 | |
| 695 | //[reference_karma_auto |
| 696 | /*`Emit a simple string using the `karma::string` generator: |
| 697 | */ |
| 698 | test_generator_attr(expected: "abc" , g: auto_, attr: "abc" ); |
| 699 | test_generator(expected: "abc" , g: auto_("abc" )); |
| 700 | |
| 701 | /*`Emit instances of the `complex` data type as defined above using the |
| 702 | generator defined by the customization point for `complex`: |
| 703 | */ |
| 704 | test_generator_attr(expected: "{1.2,2.4}" , g: auto_, attr: complex(1.2, 2.4)); |
| 705 | test_generator(expected: "{1.2,2.4}" , g: auto_(complex(1.2, 2.4))); |
| 706 | //] |
| 707 | } |
| 708 | |
| 709 | /////////////////////////////////////////////////////////////////////////// |
| 710 | // binary module |
| 711 | { |
| 712 | //[reference_karma_using_declarations_native_binary |
| 713 | using boost::spirit::karma::byte_; |
| 714 | using boost::spirit::karma::word; |
| 715 | using boost::spirit::karma::dword; |
| 716 | using boost::spirit::karma::qword; |
| 717 | //] |
| 718 | |
| 719 | //[reference_karma_native_binary_little |
| 720 | test_binary_generator(expected: "\x01" , size: 1, g: byte_(0x01)); |
| 721 | test_binary_generator(expected: "\x01\x02" , size: 2, g: word(0x0201)); |
| 722 | test_binary_generator(expected: "\x01\x02\x03\x04" , size: 4, g: dword(0x04030201)); |
| 723 | test_binary_generator(expected: "\x01\x02\x03\x04\x05\x06\x07\x08" , size: 8, g: qword(0x0807060504030201LL)); |
| 724 | |
| 725 | test_binary_generator_attr(expected: "\x01" , size: 1, g: byte_, attr: 0x01); |
| 726 | test_binary_generator_attr(expected: "\x01\x02" , size: 2, g: word, attr: 0x0201); |
| 727 | test_binary_generator_attr(expected: "\x01\x02\x03\x04" , size: 4, g: dword, attr: 0x04030201); |
| 728 | test_binary_generator_attr(expected: "\x01\x02\x03\x04\x05\x06\x07\x08" , size: 8, g: qword, attr: 0x0807060504030201LL); |
| 729 | //] |
| 730 | |
| 731 | //[reference_karma_native_binary_big |
| 732 | test_binary_generator(expected: "\x01" , size: 1, g: byte_(0x01)); |
| 733 | test_binary_generator(expected: "\x02\x01" , size: 2, g: word(0x0201)); |
| 734 | test_binary_generator(expected: "\x04\x03\x02\x01" , size: 4, g: dword(0x04030201)); |
| 735 | test_binary_generator(expected: "\x08\x07\x06\x05\x04\x03\x02\x01" , size: 8, g: qword(0x0807060504030201LL)); |
| 736 | |
| 737 | test_binary_generator_attr(expected: "\x01" , size: 1, g: byte_, attr: 0x01); |
| 738 | test_binary_generator_attr(expected: "\x02\x01" , size: 2, g: word, attr: 0x0201); |
| 739 | test_binary_generator_attr(expected: "\x04\x03\x02\x01" , size: 4, g: dword, attr: 0x04030201); |
| 740 | test_binary_generator_attr(expected: "\x08\x07\x06\x05\x04\x03\x02\x01" , size: 8, g: qword, attr: 0x0807060504030201LL); |
| 741 | //] |
| 742 | } |
| 743 | |
| 744 | { |
| 745 | //[reference_karma_using_declarations_little_binary |
| 746 | using boost::spirit::karma::little_word; |
| 747 | using boost::spirit::karma::little_dword; |
| 748 | using boost::spirit::karma::little_qword; |
| 749 | //] |
| 750 | |
| 751 | //[reference_karma_little_binary |
| 752 | test_binary_generator(expected: "\x01\x02" , size: 2, g: little_word(0x0201)); |
| 753 | test_binary_generator(expected: "\x01\x02\x03\x04" , size: 4, g: little_dword(0x04030201)); |
| 754 | test_binary_generator(expected: "\x01\x02\x03\x04\x05\x06\x07\x08" , size: 8, g: little_qword(0x0807060504030201LL)); |
| 755 | |
| 756 | test_binary_generator_attr(expected: "\x01\x02" , size: 2, g: little_word, attr: 0x0201); |
| 757 | test_binary_generator_attr(expected: "\x01\x02\x03\x04" , size: 4, g: little_dword, attr: 0x04030201); |
| 758 | test_binary_generator_attr(expected: "\x01\x02\x03\x04\x05\x06\x07\x08" , size: 8, g: little_qword, attr: 0x0807060504030201LL); |
| 759 | //] |
| 760 | } |
| 761 | |
| 762 | { |
| 763 | //[reference_karma_using_declarations_big_binary |
| 764 | using boost::spirit::karma::big_word; |
| 765 | using boost::spirit::karma::big_dword; |
| 766 | using boost::spirit::karma::big_qword; |
| 767 | //] |
| 768 | |
| 769 | //[reference_karma_big_binary |
| 770 | test_binary_generator(expected: "\x02\x01" , size: 2, g: big_word(0x0201)); |
| 771 | test_binary_generator(expected: "\x04\x03\x02\x01" , size: 4, g: big_dword(0x04030201)); |
| 772 | test_binary_generator(expected: "\x08\x07\x06\x05\x04\x03\x02\x01" , size: 8, g: big_qword(0x0807060504030201LL)); |
| 773 | |
| 774 | test_binary_generator_attr(expected: "\x02\x01" , size: 2, g: big_word, attr: 0x0201); |
| 775 | test_binary_generator_attr(expected: "\x04\x03\x02\x01" , size: 4, g: big_dword, attr: 0x04030201); |
| 776 | test_binary_generator_attr(expected: "\x08\x07\x06\x05\x04\x03\x02\x01" , size: 8, g: big_qword, attr: 0x0807060504030201LL); |
| 777 | //] |
| 778 | } |
| 779 | |
| 780 | // action |
| 781 | { |
| 782 | //[reference_karma_using_declarations_action |
| 783 | using boost::spirit::karma::int_; |
| 784 | using boost::spirit::karma::string; |
| 785 | using boost::spirit::karma::_1; |
| 786 | using boost::phoenix::ref; |
| 787 | using boost::phoenix::val; |
| 788 | //] |
| 789 | |
| 790 | //[reference_karma_action |
| 791 | int i = 42; |
| 792 | test_generator(expected: "42" , g: int_[_1 = ref(t&: i)]); |
| 793 | test_generator(expected: "abc" , g: string[_1 = val(t: "abc" )]); |
| 794 | //] |
| 795 | } |
| 796 | |
| 797 | // rule |
| 798 | { |
| 799 | //[karma_reference_rule |
| 800 | //`Some using declarations: |
| 801 | using boost::spirit::karma::rule; |
| 802 | using boost::spirit::karma::int_; |
| 803 | using boost::spirit::ascii::space; |
| 804 | using boost::spirit::ascii::space_type; |
| 805 | |
| 806 | /*`Basic rule: |
| 807 | */ |
| 808 | rule<output_iterator_type> r; |
| 809 | r = int_(123); |
| 810 | test_generator(expected: "123" , g: r); |
| 811 | |
| 812 | /*`Rule with consumed attribute: |
| 813 | */ |
| 814 | rule<output_iterator_type, int()> ra; |
| 815 | ra = int_; |
| 816 | test_generator_attr(expected: "123" , g: ra, attr: 123); |
| 817 | |
| 818 | /*`Rule with delimiter and consumed attribute: |
| 819 | */ |
| 820 | rule<output_iterator_type, std::vector<int>(), space_type> rs; |
| 821 | rs = *int_; |
| 822 | std::vector<int> v; |
| 823 | v.push_back(x: 123); |
| 824 | v.push_back(x: 456); |
| 825 | v.push_back(x: 789); |
| 826 | test_generator_attr_delim(expected: "123 456 789" , g: rs, d: space, attr: v); |
| 827 | //] |
| 828 | } |
| 829 | |
| 830 | // grammar |
| 831 | { |
| 832 | using client::num_list; |
| 833 | |
| 834 | //[karma_reference_grammar_using |
| 835 | //`Some using declarations: |
| 836 | using boost::spirit::ascii::space_type; |
| 837 | using boost::spirit::ascii::space; |
| 838 | using boost::spirit::int_; |
| 839 | using boost::spirit::karma::grammar; |
| 840 | using boost::spirit::karma::rule; |
| 841 | //] |
| 842 | |
| 843 | //[karma_reference_grammar |
| 844 | //`How to use the example grammar: |
| 845 | num_list nlist; |
| 846 | std::vector<int> v; |
| 847 | v.push_back(x: 123); |
| 848 | v.push_back(x: 456); |
| 849 | v.push_back(x: 789); |
| 850 | test_generator_attr_delim(expected: "123 , 456 , 789" , g: nlist, d: space, attr: v); |
| 851 | //] |
| 852 | } |
| 853 | |
| 854 | // symbols |
| 855 | { |
| 856 | //[reference_karma_using_declarations_symbols |
| 857 | using boost::spirit::karma::symbols; |
| 858 | //] |
| 859 | |
| 860 | //[reference_karma_symbols |
| 861 | symbols<char, char const*> sym; |
| 862 | |
| 863 | sym.add |
| 864 | ('a', "Apple" ) |
| 865 | ('b', "Banana" ) |
| 866 | ('o', "Orange" ) |
| 867 | ; |
| 868 | |
| 869 | test_generator_attr(expected: "Banana" , g: sym, attr: 'b'); |
| 870 | //] |
| 871 | } |
| 872 | |
| 873 | // as |
| 874 | { |
| 875 | //[reference_karma_using_declarations_as |
| 876 | using boost::spirit::utree; |
| 877 | using boost::spirit::utree_type; |
| 878 | using boost::spirit::utf8_symbol_type; |
| 879 | using boost::spirit::karma::as; |
| 880 | using boost::spirit::karma::as_string; |
| 881 | using boost::spirit::karma::char_; |
| 882 | using boost::spirit::karma::double_; |
| 883 | //] |
| 884 | |
| 885 | //[reference_karma_as |
| 886 | /*`To properly handle string concatenation with __utree__, we |
| 887 | make use of `as_string[]`. We also use `as<T>` to explicitly extract |
| 888 | a __utree__ symbol node.*/ |
| 889 | |
| 890 | typedef as<utf8_symbol_type> as_symbol_type; |
| 891 | as_symbol_type const as_symbol = as_symbol_type(); |
| 892 | |
| 893 | utree ut; |
| 894 | ut.push_back(val: "xyz" ); |
| 895 | ut.push_back(val: 1.23); |
| 896 | |
| 897 | test_generator_attr(expected: "xyz1.23" , g: as_string[*char_] << double_, attr: ut); |
| 898 | test_generator_attr(expected: "xyz1.23" , g: as<std::string>()[*char_] << double_, attr: ut); |
| 899 | |
| 900 | ut.clear(); |
| 901 | |
| 902 | ut.push_back(val: utf8_symbol_type("xyz" )); |
| 903 | ut.push_back(val: 1.23); |
| 904 | |
| 905 | test_generator_attr(expected: "xyz1.23" , g: as_symbol[*char_] << double_, attr: ut); |
| 906 | test_generator_attr(expected: "xyz1.23" , g: as<utf8_symbol_type>()[*char_] << double_, attr: ut); |
| 907 | //] |
| 908 | } |
| 909 | |
| 910 | return 0; |
| 911 | } |
| 912 | |