1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
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 // this code is not supposed to be executed, so the asserts are for
10 // demonstration purposes only
11 // boostinspect:naassert_macro
12 
13 //[reference_includes
14 #include <boost/spirit/include/support_utree.hpp>
15 #include <boost/spirit/include/qi.hpp>
16 #include <boost/spirit/include/phoenix_core.hpp>
17 #include <boost/spirit/include/phoenix_operator.hpp>
18 #include <boost/fusion/include/adapt_struct.hpp>
19 #include <boost/assert.hpp>
20 #include <boost/predef/other/endian.h>
21 #include <iostream>
22 #include <string>
23 #include <cstdlib>
24 //]
25 
26 //[reference_test
27 template <typename P>
test_parser(char const * input,P const & p,bool full_match=true)28 void test_parser(
29     char const* input, P const& p, bool full_match = true)
30 {
31     using boost::spirit::qi::parse;
32 
33     char const* f(input);
34     char const* l(f + strlen(f));
35     if (parse(f, l, p) && (!full_match || (f == l)))
36         std::cout << "ok" << std::endl;
37     else
38         std::cout << "fail" << std::endl;
39 }
40 
41 template <typename P>
test_phrase_parser(char const * input,P const & p,bool full_match=true)42 void test_phrase_parser(
43     char const* input, P const& p, bool full_match = true)
44 {
45     using boost::spirit::qi::phrase_parse;
46     using boost::spirit::qi::ascii::space;
47 
48     char const* f(input);
49     char const* l(f + strlen(f));
50     if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
51         std::cout << "ok" << std::endl;
52     else
53         std::cout << "fail" << std::endl;
54 }
55 //]
56 
57 //[reference_test_attr
58 template <typename P, typename T>
test_parser_attr(char const * input,P const & p,T & attr,bool full_match=true)59 void test_parser_attr(
60     char const* input, P const& p, T& attr, bool full_match = true)
61 {
62     using boost::spirit::qi::parse;
63 
64     char const* f(input);
65     char const* l(f + strlen(f));
66     if (parse(f, l, p, attr) && (!full_match || (f == l)))
67         std::cout << "ok" << std::endl;
68     else
69         std::cout << "fail" << std::endl;
70 }
71 
72 template <typename P, typename T>
test_phrase_parser_attr(char const * input,P const & p,T & attr,bool full_match=true)73 void test_phrase_parser_attr(
74     char const* input, P const& p, T& attr, bool full_match = true)
75 {
76     using boost::spirit::qi::phrase_parse;
77     using boost::spirit::qi::ascii::space;
78 
79     char const* f(input);
80     char const* l(f + strlen(f));
81     if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
82         std::cout << "ok" << std::endl;
83     else
84         std::cout << "fail" << std::endl;
85 }
86 //]
87 
88 //[reference_print_info
89 struct printer
90 {
91     typedef boost::spirit::utf8_string string;
92 
elementprinter93     void element(string const& tag, string const& value, int depth) const
94     {
95         for (int i = 0; i < (depth*4); ++i) // indent to depth
96             std::cout << ' ';
97 
98         std::cout << "tag: " << tag;
99         if (value != "")
100             std::cout << ", value: " << value;
101         std::cout << std::endl;
102     }
103 };
104 
print_info(boost::spirit::info const & what)105 void print_info(boost::spirit::info const& what)
106 {
107     using boost::spirit::basic_info_walker;
108 
109     printer pr;
110     basic_info_walker<printer> walker(pr, what.tag, 0);
111     boost::apply_visitor(walker, what.value);
112 }
113 //]
114 
115 //[reference_test_real_policy
116 ///////////////////////////////////////////////////////////////////////////////
117 //  These policies can be used to parse thousand separated
118 //  numbers with at most 2 decimal digits after the decimal
119 //  point. e.g. 123,456,789.01
120 ///////////////////////////////////////////////////////////////////////////////
121 template <typename T>
122 struct ts_real_policies : boost::spirit::qi::ureal_policies<T>
123 {
124     //  2 decimal places Max
125     template <typename Iterator, typename Attribute>
126     static bool
parse_frac_nts_real_policies127     parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr,
128                  int& frac_digits)
129     {
130         Iterator savef = first;
131         bool r = boost::spirit::qi::
132             extract_uint<T, 10, 1, 2, true>::call(first, last, attr);
133         if (r) {
134             // Optimization note: don't compute frac_digits if T is
135             // an unused_type. This should be optimized away by the compiler.
136             if (!boost::is_same<T, boost::spirit::unused_type>::value)
137                 frac_digits = static_cast<int>(std::distance(savef, first));
138         }
139         return r;
140     }
141 
142     //  No exponent
143     template <typename Iterator>
144     static bool
parse_expts_real_policies145     parse_exp(Iterator&, Iterator const&)
146     {
147         return false;
148     }
149 
150     //  No exponent
151     template <typename Iterator, typename Attribute>
152     static bool
parse_exp_nts_real_policies153     parse_exp_n(Iterator&, Iterator const&, Attribute&)
154     {
155         return false;
156     }
157 
158     //  Thousands separated numbers
159     template <typename Iterator, typename Accumulator>
160     static bool
parse_nts_real_policies161     parse_n(Iterator& first, Iterator const& last, Accumulator& result)
162     {
163         using boost::spirit::qi::uint_parser;
164         namespace qi = boost::spirit::qi;
165 
166         uint_parser<unsigned, 10, 1, 3> uint3;
167         uint_parser<unsigned, 10, 3, 3> uint3_3;
168 
169         if (parse(first, last, uint3, result))
170         {
171             Accumulator n;
172             Iterator iter = first;
173 
174             while (qi::parse(iter, last, ',') && qi::parse(iter, last, uint3_3, n))
175             {
176                 result = result * 1000 + n;
177                 first = iter;
178             }
179 
180             return true;
181         }
182         return false;
183     }
184 };
185 //]
186 
187 //[reference_test_bool_policy
188 ///////////////////////////////////////////////////////////////////////////////
189 //  These policies can be used to parse "eurt" (i.e. "true" spelled backwards)
190 //  as `false`
191 ///////////////////////////////////////////////////////////////////////////////
192 struct backwards_bool_policies : boost::spirit::qi::bool_policies<>
193 {
194     // we want to interpret a 'true' spelled backwards as 'false'
195     template <typename Iterator, typename Attribute>
196     static bool
parse_falsebackwards_bool_policies197     parse_false(Iterator& first, Iterator const& last, Attribute& attr)
198     {
199         namespace qi = boost::spirit::qi;
200         if (qi::detail::string_parse("eurt", first, last, qi::unused))
201         {
202             namespace traits = boost::spirit::traits;
203             traits::assign_to(false, attr);    // result is false
204             return true;
205         }
206         return false;
207     }
208 };
209 //]
210 
211 //[reference_qi_complex
212 // a simple complex number representation z = a + bi
213 struct complex
214 {
complexcomplex215     complex (double a = 0.0, double b = 0.0)
216       : a(a), b(b)
217     {}
218 
219     double a;
220     double b;
221 };
222 //]
223 
224 //[reference_qi_stream_complex
225 // define streaming operator for the type complex
226 std::istream&
operator >>(std::istream & is,complex & z)227 operator>> (std::istream& is, complex& z)
228 {
229     char lbrace = '\0', comma = '\0', rbrace = '\0';
230     is >> lbrace >> z.a >> comma >> z.b >> rbrace;
231     if (lbrace != '{' || comma != ',' || rbrace != '}')
232         is.setstate(std::ios_base::failbit);
233     return is;
234 }
235 //]
236 
237 //[reference_qi_auto_complex
238 /*`The following construct is required to allow the `complex` data structure
239    to be utilized as a __fusion__ sequence. This is required as we will
240    emit output for this data structure with a __qi__ sequence:
241    `'{' >> qi::double_ >> ',' >> qi::double_ >> '}'`.
242 */
243 BOOST_FUSION_ADAPT_STRUCT(
244     complex,
245     (double, a)
246     (double, b)
247 )
248 
249 /*`We add a specialization for the create_parser customization point
250    defining a custom output format for the complex type. Generally, any
251    specialization for create_parser is expected to return the proto
252    expression to be used to match input for the type the customization
253    point has been specialized for.
254  */
255 /*`We need to utilize `proto::deep_copy` as the expression contains literals
256    (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto
257    expression by reference only. The deep copy converts the proto tree to
258    hold this by value. The deep copy operation can be left out for simpler
259    proto expressions (not containing references to temporaries). Alternatively
260    you could use the `proto::make_expr` facility to build the required
261    proto expression.
262 */
263 namespace boost { namespace spirit { namespace traits
264 {
265     template <>
266     struct create_parser<complex>
267     {
268         typedef proto::result_of::deep_copy<
269             BOOST_TYPEOF('{' >> qi::double_ >> ',' >> qi::double_ >> '}')
270         >::type type;
271 
callboost::spirit::traits::create_parser272         static type call()
273         {
274             return proto::deep_copy(
275                 '{' >> qi::double_ >> ',' >> qi::double_ >> '}');
276         }
277     };
278 }}}
279 //]
280 
281 //[reference_qi_auxiliary_attr_cast_data1
282 // this is just a test structure we want to use in place of an int
283 struct int_data
284 {
285     int i;
286 };
287 
288 
289 // we provide a custom attribute transformation to allow its use as an int
290 namespace boost { namespace spirit { namespace traits
291 {
292     // in this case we just expose the embedded 'int' as the attribute instance
293     // to use, allowing to leave the function 'post()' empty
294     template <>
295     struct transform_attribute<int_data, int, qi::domain>
296     {
297         typedef int& type;
preboost::spirit::traits::transform_attribute298         static int& pre(int_data& d) { return d.i; }
postboost::spirit::traits::transform_attribute299         static void post(int_data& val, int const& attr) {}
failboost::spirit::traits::transform_attribute300         static void fail(int_data&) {}
301     };
302 }}}
303 //]
304 
305 namespace client
306 {
307     using boost::spirit::qi::grammar;
308     using boost::spirit::qi::rule;
309     using boost::spirit::ascii::space_type;
310 
311 //[reference_grammar_definition
312 /*`Basic grammar usage:
313  */
314     struct num_list : grammar<char const*, space_type>
315     {
num_listclient::num_list316         num_list() : base_type(start)
317         {
318             using boost::spirit::int_;
319             num = int_;
320             start = num >> *(',' >> num);
321         }
322 
323         rule<char const*, space_type> start, num;
324     };
325 //]
326 }
327 
328 int
main()329 main()
330 {
331     {
332         //[reference_using_declarations_lit_char
333         using boost::spirit::qi::lit;
334         using boost::spirit::ascii::char_;
335         //]
336 
337         //[reference_char_literals
338         test_parser("x", 'x');                      // plain literal
339         test_parser("x", lit('x'));                 // explicit literal
340         test_parser("x", char_('x'));               // ascii::char_
341         //]
342 
343         //[reference_char_range
344         char ch;
345         test_parser_attr("5", char_('0','9'), ch);  // ascii::char_ range
346         std::cout << ch << std::endl;               // prints '5'
347         //]
348 
349         //[reference_char_set
350         test_parser_attr("5", char_("0-9"), ch);    // ascii::char_ set
351         std::cout << ch << std::endl;               // prints '5'
352         //]
353 
354         //[reference_char_phoenix
355         namespace phx = boost::phoenix;
356         test_parser("x", phx::val('x'));            // direct
357         test_parser("5",
358             char_(phx::val('0'),phx::val('9')));    // ascii::char_ range
359         //]
360     }
361 
362     {
363         //[reference_using_declarations_lit_string
364         using boost::spirit::qi::lit;
365         using boost::spirit::ascii::string;
366         //]
367 
368         //[reference_string_literals
369         test_parser("boost", "boost");          // plain literal
370         test_parser("boost", lit("boost"));     // explicit literal
371         test_parser("boost", string("boost"));  // ascii::string
372         //]
373     }
374 
375     {
376         using boost::spirit::qi::lit;
377         using boost::spirit::ascii::string;
378 
379         //[reference_string_std_string
380         std::string s("boost");
381         test_parser("boost", s);            // direct
382         test_parser("boost", lit(s));       // explicit
383         test_parser("boost", string(s));    // ascii::string
384         //]
385     }
386 
387     {
388         using boost::spirit::qi::lit;
389         using boost::spirit::ascii::string;
390 
391         //[reference_string_phoenix
392         namespace phx = boost::phoenix;
393         test_parser("boost", phx::val("boost"));            // direct
394         test_parser("boost", lit(phx::val("boost")));       // explicit
395         test_parser("boost", string(phx::val("boost")));    // ascii::string
396         //]
397     }
398 
399     {
400         //[reference_using_declarations_symbols
401         using boost::spirit::qi::symbols;
402         //]
403 
404         //[reference_symbols_with_data
405         symbols<char, int> sym;
406 
407         sym.add
408             ("Apple", 1)
409             ("Banana", 2)
410             ("Orange", 3)
411         ;
412 
413         int i;
414         test_parser_attr("Banana", sym, i);
415         std::cout << i << std::endl;
416         //]
417     }
418 
419     {
420         //[reference_using_declarations_lexeme
421         using boost::spirit::qi::lexeme;
422         using boost::spirit::qi::lit;
423         using boost::spirit::ascii::digit;
424         //]
425 
426         //[reference_lexeme
427         /*`The use of lexeme here will prevent skipping in between the
428             digits and the sign making inputs such as `"1 2 345"` erroneous.*/
429         test_phrase_parser("12345", lexeme[ -(lit('+') | '-') >> +digit ]);
430         //]
431     }
432 
433     // as
434     {
435         //[reference_using_declarations_as
436         using boost::spirit::utree;
437         using boost::spirit::utree_type;
438         using boost::spirit::utf8_symbol_type;
439         using boost::spirit::qi::as;
440         using boost::spirit::qi::as_string;
441         using boost::spirit::qi::char_;
442         //]
443 
444         //[reference_as
445         /*`To properly handle string concatenation with __utree__, we
446            make use of `as_string[]`. We also use `as<T>` to explicitly create
447            a __utree__ symbol node.*/
448         utree ut;
449 
450         typedef as<utf8_symbol_type> as_symbol_type;
451         as_symbol_type const as_symbol = as_symbol_type();
452 
453         test_parser_attr("foo", as_string[*char_], ut);
454         std::cout << ut << std::endl; // will output >"foo"<
455         BOOST_ASSERT(ut.which() == utree_type::string_type);
456         ut.clear();
457 
458         test_parser_attr("foo", as<std::string>()[*char_], ut);
459         std::cout << ut << std::endl; // will output >"foo"<
460         BOOST_ASSERT(ut.which() == utree_type::string_type);
461         ut.clear();
462 
463         test_parser_attr("foo", as_symbol[*char_], ut);
464         std::cout << ut << std::endl; // will output >foo<
465         BOOST_ASSERT(ut.which() == utree_type::symbol_type);
466         ut.clear();
467 
468         test_parser_attr("foo", as<utf8_symbol_type>()[*char_], ut);
469         std::cout << ut << std::endl; // will output >foo<
470         BOOST_ASSERT(ut.which() == utree_type::symbol_type);
471         //]
472     }
473 
474     {
475         //[reference_using_declarations_no_skip
476         using boost::spirit::qi::no_skip;
477         using boost::spirit::qi::char_;
478         //]
479 
480         //[reference_no_skip
481         /*`The use of no_skip here will prevent skipping of whitespace in front
482            and in between the characters of the string `'  abc  '`.*/
483 
484         std::string str;
485         test_phrase_parser_attr("'  abc  '",
486             '\'' >> no_skip[+~char_('\'')] >> '\'', str);
487         std::cout << str << std::endl;    // will output: >  abc  <
488         //]
489     }
490 
491     {
492         //[reference_using_declarations_hold
493         using boost::spirit::qi::hold;
494         using boost::spirit::qi::int_;
495         using boost::spirit::qi::attr;
496         //]
497 
498         //[reference_hold
499         /*`The use of `hold[]` here will make sure the changes to the attribute
500            caused by the (failing) first alternative will not be visible after
501            the whole parsing succeeded. */
502 
503         std::vector<int> v;
504         test_phrase_parser_attr("123",
505               hold[int_ >> ':' >> int_] | int_ >> attr(0), v);
506         std::cout << v[0] << "," << v[1] << std::endl;    // will output: >123,0<
507         //]
508     }
509 
510     {
511         //[reference_using_declarations_no_case
512         using boost::spirit::ascii::no_case;
513         using boost::spirit::ascii::char_;
514         using boost::spirit::ascii::alnum;
515         using boost::spirit::qi::symbols;
516         //]
517 
518         //[reference_no_case
519         test_parser("X", no_case[char_('x')]);
520         test_parser("6", no_case[alnum]);
521         //]
522 
523         //[reference_symbols_with_no_case
524         symbols<char, int> sym;
525 
526         sym.add
527             ("apple", 1)    // symbol strings are added in lowercase...
528             ("banana", 2)
529             ("orange", 3)
530         ;
531 
532         int i;
533         // ...because sym is used for case-insensitive parsing
534         test_parser_attr("Apple", no_case[ sym ], i);
535         std::cout << i << std::endl;
536         test_parser_attr("ORANGE", no_case[ sym ], i);
537         std::cout << i << std::endl;
538         //]
539     }
540 
541     {
542         //[reference_using_declarations_omit
543         using boost::spirit::qi::omit;
544         using boost::spirit::qi::int_;
545         using boost::spirit::ascii::char_;
546         //]
547 
548         //[reference_omit
549         /*`This parser ignores the first two characters
550             and extracts the succeeding `int`:*/
551         int i;
552         test_parser_attr("xx345", omit[char_ >> char_] >> int_, i);
553         std::cout << i << std::endl; // should print 345
554         //]
555     }
556 
557     {
558         //[reference_using_declarations_matches
559         using boost::spirit::qi::matches;
560         using boost::spirit::qi::int_;
561         //]
562 
563         //[reference_matches
564         /*`This parser tries to match an `int` and returns `true` a its
565            attribute as it succeeded matching: */
566         bool result = false;
567         test_parser_attr("345", matches[int_], result);
568         std::cout << std::boolalpha << result << std::endl; // should print: true
569 
570         /*`This parser tries to match an `int` as well and returns `false` as
571            its attribute as it fails matching: */
572         result = true;
573         test_parser_attr("abc", matches[int_], result);
574         std::cout << std::boolalpha << result << std::endl; // should print: false
575         //]
576     }
577 
578     {
579         //[reference_using_declarations_raw
580         using boost::spirit::qi::raw;
581         using boost::spirit::ascii::alpha;
582         using boost::spirit::ascii::alnum;
583         //]
584 
585         //[reference_raw
586         //`This parser matches and extracts C++ identifiers:
587         std::string id;
588         test_parser_attr("James007", raw[(alpha | '_') >> *(alnum | '_')], id);
589         std::cout << id << std::endl; // should print James007
590         //]
591     }
592 
593     {
594         //[reference_using_declarations_repeat
595         using boost::spirit::qi::repeat;
596         using boost::spirit::qi::lit;
597         using boost::spirit::qi::uint_parser;
598         using boost::spirit::qi::_1;
599         using boost::spirit::ascii::char_;
600         namespace phx = boost::phoenix;
601         //]
602 
603         //[reference_repeat
604         //`A parser for a file name with a maximum of 255 characters:
605         test_parser("batman.jpeg", repeat(1, 255)[char_("a-zA-Z_./")]);
606 
607         /*`A parser for a specific bitmap file format which has exactly 4096 RGB color information.
608             (for the purpose of this example, we will be testing only 3 RGB color information.)
609          */
610         uint_parser<unsigned, 16, 6, 6> rgb;
611         std::vector<unsigned> colors;
612         test_parser_attr("ffffff0000003f3f3f", repeat(3)[rgb], colors);
613         std::cout
614             << std::hex
615             << colors[0] << ','
616             << colors[1] << ','
617             << colors[2] << std::endl;
618 
619         /*`A 256 bit binary string (1..256 1s or 0s). (For the purpose of this example,
620             we will be testing only 16 bits.)
621          */
622         test_parser("1011101011110010", repeat(16)[lit('1') | '0']);
623         //]
624 
625         std::cout << std::dec; // reset to decimal
626 
627         //[reference_repeat_pascal
628         /*`This trivial example cannot be practically defined in traditional EBNF.
629             Although some EBNF variants allow more powerful repetition constructs other
630             than the Kleene Star, we are still limited to parsing fixed strings.
631             The nature of EBNF forces the repetition factor to be a constant.
632             On the other hand, Spirit allows the repetition factor to be variable at
633             run time. We could write a grammar that accepts the input string above.
634             Example using phoenix:
635          */
636         std::string str;
637         int n;
638         test_parser_attr("\x0bHello World",
639             char_[phx::ref(n) = _1] >> repeat(phx::ref(n))[char_], str);
640         std::cout << n << ',' << str << std::endl;  // will print "11,Hello World"
641         //]
642     }
643 
644     {
645         //[reference_using_declarations_skip
646         using boost::spirit::qi::skip;
647         using boost::spirit::qi::int_;
648         using boost::spirit::ascii::space;
649         //]
650 
651         //[reference_skip
652         /*`Explicitly specify a skip parser. This parser parses comma
653             delimited numbers, ignoring spaces.*/
654         test_parser("1, 2, 3, 4, 5", skip(space)[int_ >> *(',' >> int_)]);
655         //]
656     }
657 
658     // attr()
659     {
660         //[reference_using_declarations_attr
661         namespace phx = boost::phoenix;
662         using boost::spirit::qi::attr;
663         //]
664 
665         //[reference_attr
666         std::string str;
667         test_parser_attr("", attr("boost"), str);
668         std::cout << str << std::endl;            // will print 'boost'
669 
670         double d;
671         test_parser_attr("", attr(1.0), d);
672         std::cout << d << std::endl;              // will print '1.0'
673         //]
674 
675         //[reference_attr_phoenix
676         d = 0.0;
677         double d1 = 1.2;
678         test_parser_attr("", attr(phx::ref(d1)), d);
679         std::cout << d << std::endl;              // will print '1.2'
680         //]
681     }
682 
683     // attr_cast
684     {
685         //[reference_qi_using_declarations_attr_cast
686         using boost::spirit::qi::int_;
687         //]
688 
689         //[reference_qi_attr_cast1
690         int_data d = { 0 };
691         test_parser_attr("1", boost::spirit::qi::attr_cast(int_), d);
692         std::cout << d.i << std::endl;
693         //]
694     }
695 
696     // eol
697     {
698         //[reference_using_declarations_eol
699         using boost::spirit::qi::eol;
700         //]
701 
702         //[reference_eol
703         test_parser("\n", eol);
704         //]
705     }
706 
707     // eoi
708     {
709         //[reference_using_declarations_eoi
710         using boost::spirit::qi::eoi;
711         //]
712 
713         //[reference_eoi
714         test_parser("", eoi);
715         //]
716     }
717 
718     // eps
719     {
720         //[reference_using_declarations_eps
721         using boost::spirit::qi::eps;
722         using boost::spirit::qi::int_;
723         using boost::spirit::qi::_1;
724         namespace phx = boost::phoenix;
725         //]
726 
727         //[reference_eps
728         //`Basic `eps`:
729         test_parser("", eps); // always matches
730         //]
731 
732         //[reference_eps_if
733         /*`This example simulates the "classic" `if_p` parser. Here, `int_` will be
734             tried only if the condition, `c`, is true.
735          */
736         bool c = true; // a flag
737         test_parser("1234", eps(phx::ref(c) == true) >> int_);
738         //]
739 
740         //[reference_eps_while
741         /*`This example simulates the "classic" `while_p` parser. Here, the kleene loop
742             will exit once the condition, `c`, becomes true. Notice that the condition, `c`,
743             is turned to `false` when we get to parse `4`.
744          */
745         test_phrase_parser("1 2 3 4",
746             *(eps(phx::ref(c) == true) >> int_[phx::ref(c) = (_1 == 4)]));
747         //]
748     }
749 
750     // lazy
751     {
752         //[reference_using_declarations_lazy
753         using boost::spirit::qi::lazy;
754         using boost::spirit::ascii::string;
755         using boost::phoenix::val;
756         //]
757 
758         //[reference_lazy
759         /*` Here, the phoenix::val expression creates a function
760             that returns its argument when invoked. The lazy expression
761             defers the invocation of this function at parse time. Then,
762             this parser (string parser) is called into action. All this
763             takes place at parse time.
764          */
765         test_parser("Hello", lazy(val(string("Hello"))));
766 
767         //` The above is equivalent to:
768         test_parser("Hello", string("Hello"));
769         //]
770     }
771 
772     // char class
773     {
774         //[reference_using_declarations_char_class
775         using boost::spirit::ascii::alnum;
776         using boost::spirit::ascii::blank;
777         using boost::spirit::ascii::digit;
778         using boost::spirit::ascii::lower;
779         //]
780 
781         //[reference_char_class
782         test_parser("1", alnum);
783         test_parser(" ", blank);
784         test_parser("1", digit);
785         test_parser("a", lower);
786         //]
787     }
788 
789     // uint
790     {
791         //[reference_using_declarations_uint
792         using boost::phoenix::val;
793         using boost::spirit::qi::lit;
794         using boost::spirit::qi::uint_;
795         using boost::spirit::qi::uint_parser;
796         //]
797 
798         //[reference_uint
799         // unsigned int
800         test_parser("12345", uint_);
801         test_parser("12345", uint_(12345));
802         test_parser("12345", uint_(val(12345)));
803 
804         // literals
805         test_parser("12345", lit(12345));
806         test_parser("12345", lit(val(12345)));
807         //]
808 
809         //[reference_thousand_separated
810         //`Thousand separated number parser:
811         uint_parser<unsigned, 10, 1, 3> uint3_p;        //  1..3 digits
812         uint_parser<unsigned, 10, 3, 3> uint3_3_p;      //  exactly 3 digits
813         test_parser("12,345,678", uint3_p >> *(',' >> uint3_3_p));
814         //]
815     }
816 
817     // int
818     {
819         //[reference_using_declarations_int
820         using boost::phoenix::val;
821         using boost::spirit::qi::lit;
822         using boost::spirit::qi::int_;
823         //]
824 
825         //[reference_int
826         // signed int
827         test_parser("+12345", int_);
828         test_parser("-12345", int_);
829         test_parser("+12345", int_(12345));
830         test_parser("-12345", int_(-12345));
831         test_parser("+12345", int_(val(12345)));
832         test_parser("-12345", int_(val(-12345)));
833 
834         // literals
835         test_parser("+12345", lit(12345));
836         test_parser("-12345", lit(-12345));
837         test_parser("+12345", lit(val(12345)));
838         test_parser("-12345", lit(val(-12345)));
839         //]
840     }
841 
842     // real
843     {
844         //[reference_using_declarations_real
845         using boost::phoenix::val;
846         using boost::spirit::qi::double_;
847         using boost::spirit::qi::real_parser;
848         using boost::spirit::qi::lit;
849         //]
850 
851         //[reference_real
852         // double
853         test_parser("+12345e6", double_);
854         test_parser("-12345e6", double_);
855         test_parser("+12345e6", double_(12345e6));
856         test_parser("-12345e6", double_(-123456e6));
857         test_parser("+12345e6", double_(val(12345e6)));
858         test_parser("-12345e6", double_(val(-123456e6)));
859 
860         // literals
861         test_parser("+12345e6", lit(12345e6));
862         test_parser("-12345e6", lit(-123456e6));
863         test_parser("+12345e6", lit(val(12345e6)));
864         test_parser("-12345e6", lit(val(-123456e6)));
865         //]
866 
867         //[reference_custom_real
868         real_parser<double, ts_real_policies<double> > ts_real;
869         test_parser("123,456,789.01", ts_real);
870         test_parser("123,456,789.01", ts_real(123456789.01));
871         //]
872     }
873 
874     // bool_
875     {
876         //[reference_using_declarations_bool
877         using boost::phoenix::val;
878         using boost::spirit::qi::bool_;
879         using boost::spirit::qi::bool_parser;
880         using boost::spirit::qi::lit;
881         //]
882 
883         //[reference_bool
884         // bool
885         test_parser("true", bool_);
886         test_parser("false", bool_);
887         test_parser("true", bool_(true));
888         test_parser("false", bool_(false));
889         test_parser("true", bool_(val(true)));
890         test_parser("false", bool_(val(false)));
891 
892         // literals
893         test_parser("true", lit(true));
894         test_parser("false", lit(false));
895         test_parser("true", lit(val(true)));
896         test_parser("false", lit(val(false)));
897         //]
898 
899         //[reference_custom_bool
900         bool_parser<bool, backwards_bool_policies> backwards_bool;
901         test_parser("true", backwards_bool);
902         test_parser("eurt", backwards_bool);
903         test_parser("true", backwards_bool(true));
904         test_parser("eurt", backwards_bool(false));
905         //]
906     }
907 
908     // sequence
909     {
910         //[reference_using_declarations_sequence
911         using boost::spirit::ascii::char_;
912         using boost::spirit::qi::_1;
913         using boost::spirit::qi::_2;
914         namespace bf = boost::fusion;
915         //]
916 
917         //[reference_sequence
918         //`Simple usage:
919         test_parser("xy", char_ >> char_);
920 
921         //`Extracting the attribute tuple (using __fusion__):
922         bf::vector<char, char> attr;
923         test_parser_attr("xy", char_ >> char_, attr);
924         std::cout << bf::at_c<0>(attr) << ',' << bf::at_c<1>(attr) << std::endl;
925 
926         //`Extracting the attribute vector (using __stl__):
927         std::vector<char> vec;
928         test_parser_attr("xy", char_ >> char_, vec);
929         std::cout << vec[0] << ',' << vec[1] << std::endl;
930 
931         //`Extracting the attributes using __qi_semantic_actions__ (using __phoenix__):
932         test_parser("xy", (char_ >> char_)[std::cout << _1 << ',' << _2 << std::endl]);
933         //]
934     }
935 
936     // sequential_or
937     {
938         //[reference_using_declarations_sequential_or
939         using boost::spirit::qi::int_;
940         //]
941 
942         //[reference_sequential_or
943         //`Correctly parsing a number with optional fractional digits:
944         test_parser("123.456", int_ || ('.' >> int_));  // full
945         test_parser("123", int_ || ('.' >> int_));      // just the whole number
946         test_parser(".456", int_ || ('.' >> int_));     // just the fraction
947 
948         /*`A naive but incorrect solution would try to do this using optionals (e.g.):
949 
950                 int_ >> -('.' >> int_)  // will not match ".456"
951                 -int_ >> ('.' >> int_)  // will not match "123"
952                 -int_ >> -('.' >> int_) // will match empty strings! Ooops.
953          */
954         //]
955     }
956 
957     // alternative
958     {
959         //[reference_using_declarations_alternative
960         using boost::spirit::ascii::string;
961         using boost::spirit::qi::int_;
962         using boost::spirit::qi::_1;
963         using boost::variant;
964         //]
965 
966         //[reference_alternative
967         //`Simple usage:
968         test_parser("Hello", string("Hello") | int_);
969         test_parser("123", string("Hello") | int_);
970 
971         //`Extracting the attribute variant (using __boost_variant__):
972         variant<std::string, int> attr;
973         test_parser_attr("Hello", string("Hello") | int_, attr);
974 
975         /*`This should print `"Hello"`. Note: There are better ways to extract the value
976             from the variant. See __boost_variant__ visitation. This code is solely
977             for demonstration.
978          */
979         if (boost::get<int>(&attr))
980             std::cout << boost::get<int>(attr) << std::endl;
981         else
982             std::cout << boost::get<std::string>(attr) << std::endl;
983 
984         /*`Extracting the attributes using __qi_semantic_actions__ with __phoenix__
985             (this should print `123`):
986          */
987         test_parser("123", (string("Hello") | int_)[std::cout << _1 << std::endl]);
988         //]
989 
990     }
991 
992     // permutation
993     {
994         //[reference_using_declarations_permutation
995         using boost::spirit::ascii::char_;
996         //]
997 
998         //[reference_permutation
999         //`Parse a string containing DNA codes (ACTG)
1000         test_parser("ACTGGCTAGACT", *(char_('A') ^ 'C' ^ 'T' ^ 'G'));
1001         //]
1002     }
1003 
1004     // expect
1005     {
1006         //[reference_using_declarations_expect
1007         using boost::spirit::ascii::char_;
1008         using boost::spirit::qi::expectation_failure;
1009         //]
1010 
1011         //[reference_expect
1012         /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
1013             with a deliberate parsing error when `"o"` is expected and `"i"` is what is
1014             found in the input. The `catch` block prints the information related to the
1015             error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
1016             you use an __qi_error_handler__ to deal with the error.
1017          */
1018         try
1019         {
1020             test_parser("xi", char_('x') > char_('o')); // should throw an exception
1021         }
1022         catch (expectation_failure<char const*> const& x)
1023         {
1024             std::cout << "expected: "; print_info(x.what_);
1025             std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
1026         }
1027         /*`The code above will print:[teletype]
1028 
1029                 expected: tag: literal-char, value: o
1030                 got: "i"``[c++]``
1031          */
1032         //]
1033     }
1034 
1035     // expectd
1036     {
1037         //[reference_using_declarations_expectd
1038         using boost::spirit::ascii::char_;
1039         using boost::spirit::qi::expect;
1040         using boost::spirit::qi::expectation_failure;
1041         //]
1042 
1043         //[reference_expectd
1044         /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
1045             with a deliberate parsing error when `"o"` is expected and `"x"` is what is
1046             found in the input. The `catch` block prints the information related to the
1047             error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
1048             you use an __qi_error_handler__ to deal with the error.
1049          */
1050         try
1051         {
1052             test_parser("xi", expect[char_('o')]); // should throw an exception
1053         }
1054         catch (expectation_failure<char const*> const& x)
1055         {
1056             std::cout << "expected: "; print_info(x.what_);
1057             std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
1058         }
1059         /*`The code above will print:[teletype]
1060 
1061                 expected: tag: literal-char, value: o
1062                 got: "x"``[c++]``
1063          */
1064         //]
1065     }
1066 
1067     // and-predicate
1068     {
1069         //[reference_and_predicate
1070         //`Some using declarations:
1071         using boost::spirit::lit;
1072 
1073         /*`Basic look-ahead example: make sure that the last character is a
1074             semicolon, but don't consume it, just peek at the next character:
1075          */
1076         test_phrase_parser("Hello ;", lit("Hello") >> &lit(';'), false);
1077         //]
1078     }
1079 
1080     // not-predicate
1081     {
1082         //[reference_not_predicate
1083         //`Some using declarations:
1084         using boost::spirit::ascii::char_;
1085         using boost::spirit::ascii::alpha;
1086         using boost::spirit::qi::lit;
1087         using boost::spirit::qi::symbols;
1088 
1089         /*`Here's an alternative to the `*(r - x) >> x` idiom using the
1090             not-predicate instead. This parses a list of characters terminated
1091             by a ';':
1092          */
1093         test_parser("abcdef;", *(!lit(';') >> char_) >> ';');
1094 
1095         /*`The following parser ensures that we match distinct keywords
1096             (stored in a symbol table). To do this, we make sure that the
1097             keyword does not follow an alpha or an underscore:
1098          */
1099         symbols<char, int> keywords;
1100         keywords = "begin", "end", "for";
1101 
1102         // This should fail:
1103         test_parser("beginner", keywords >> !(alpha | '_'));
1104 
1105         // This is ok:
1106         test_parser("end ", keywords >> !(alpha | '_'), false);
1107 
1108         // This is ok:
1109         test_parser("for()", keywords >> !(alpha | '_'), false);
1110         //]
1111     }
1112 
1113     // difference
1114     {
1115         //[reference_difference
1116         //`Some using declarations:
1117         using boost::spirit::ascii::char_;
1118 
1119         /*`Parse a C/C++ style comment:
1120          */
1121         test_parser("/*A Comment*/", "/*" >> *(char_ - "*/") >> "*/");
1122         //]
1123     }
1124 
1125     // kleene
1126     {
1127         //[reference_kleene
1128         //`Some using declarations:
1129         using boost::spirit::qi::int_;
1130 
1131         /*`Parse a comma separated list of numbers and put them in a vector:
1132          */
1133         std::vector<int> attr;
1134         test_phrase_parser_attr(
1135             "111, 222, 333, 444, 555", int_ >> *(',' >> int_), attr);
1136         std::cout
1137             << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
1138             << attr[3] << ',' << attr[4]
1139             << std::endl;
1140         //]
1141     }
1142 
1143     // plus
1144     {
1145         //[reference_plus
1146         //`Some using declarations:
1147         using boost::spirit::ascii::alpha;
1148         using boost::spirit::qi::lexeme;
1149 
1150         /*`Parse one or more strings containing one or more alphabetic
1151             characters and put them in a vector:
1152          */
1153         std::vector<std::string> attr;
1154         test_phrase_parser_attr("yaba daba doo", +lexeme[+alpha], attr);
1155         std::cout << attr[0] << ',' << attr[1] << ',' << attr[2] << std::endl;
1156         //]
1157     }
1158 
1159     // optional
1160     {
1161         //[reference_optional
1162         //`Some using declarations:
1163         using boost::spirit::ascii::char_;
1164         using boost::spirit::qi::lexeme;
1165         using boost::spirit::qi::int_;
1166         using boost::fusion::vector;
1167         using boost::fusion::at_c;
1168         using boost::optional;
1169 
1170         /*`Parse a person info with name (in quotes) optional age [footnote
1171             James Bond is shy about his age :-)] and optional sex, all
1172             separated by comma.
1173          */
1174         vector<std::string, optional<int>, optional<char> > attr;
1175 
1176         test_phrase_parser_attr(
1177             "\"James Bond\", M"
1178           , lexeme['"' >> +(char_ - '"') >> '"']    // name
1179                 >> -(',' >> int_)                   // optional age
1180                 >> -(',' >> char_)                  // optional sex
1181           , attr);
1182 
1183         // Should print: James Bond,M
1184         std::cout << at_c<0>(attr);                 // print name
1185         if (at_c<1>(attr))                          // print optional age
1186             std::cout << ',' << *at_c<1>(attr);
1187         if (at_c<2>(attr))                          // print optional sex
1188             std::cout << ',' << *at_c<2>(attr);
1189         std::cout << std::endl;
1190         //]
1191     }
1192 
1193     // list
1194     {
1195         //[reference_list
1196         //`Some using declarations:
1197         using boost::spirit::qi::int_;
1198 
1199         /*`Parse a comma separated list of numbers and put them in a vector:
1200          */
1201         std::vector<int> attr;
1202         test_phrase_parser_attr(
1203             "111, 222, 333, 444, 555", int_ % ',', attr);
1204         std::cout
1205             << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
1206             << attr[3] << ',' << attr[4]
1207             << std::endl;
1208         //]
1209     }
1210 
1211     // stream
1212     {
1213         //[reference_qi_stream
1214         //`Using declarations and variables:
1215         using boost::spirit::qi::stream;
1216         using boost::spirit::qi::stream_parser;
1217 
1218         /*`Parse a simple string using the operator>>(istream&, std::string&);
1219          */
1220         std::string str;
1221         test_parser_attr("abc", stream, str);
1222         std::cout << str << std::endl;                  // prints: abc
1223 
1224         /*`Parse our complex type using the operator>>(istream&, complex&);
1225          */
1226         complex c;
1227         test_parser_attr("{1.0,2.5}", stream_parser<char, complex>(), c);
1228         std::cout << c.a << "," << c.b << std::endl;    // prints: 1.0,2.5
1229         //]
1230     }
1231 
1232     ///////////////////////////////////////////////////////////////////////////
1233     // auto module
1234     {
1235         //[reference_qi_using_declarations_auto
1236         using boost::spirit::qi::auto_;
1237         //]
1238 
1239         //[reference_qi_auto
1240         /*`Parse a simple integer using the generated parser component `int_`:
1241          */
1242         int i = 0;
1243         test_parser_attr("123", auto_, i);
1244         std::cout << i << std::endl;                    // prints: 123
1245 
1246         /*`Parse an instance of the `complex` data type as defined above using
1247            the parser as generated by the defined customization point:
1248          */
1249         complex c;
1250         test_parser_attr("{1.2,2.4}", auto_, c);
1251         std::cout << c.a << "," << c.b << std::endl;    // prints: 1.2,2.4
1252         //]
1253     }
1254 
1255     // native binary
1256     {
1257         //[reference_qi_native_binary
1258         //`Using declarations and variables:
1259         using boost::spirit::qi::byte_;
1260         using boost::spirit::qi::word;
1261         using boost::spirit::qi::dword;
1262         using boost::spirit::qi::qword;
1263 
1264         boost::uint8_t uc;
1265         boost::uint16_t us;
1266         boost::uint32_t ui;
1267 //<-
1268 #ifdef BOOST_HAS_LONG_LONG
1269 //->
1270         boost::uint64_t ul;
1271 //<-
1272 #endif
1273 
1274 #if BOOST_ENDIAN_LITTLE_BYTE
1275 //->
1276         //`Basic usage of the native binary parsers for little endian platforms:
1277         test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
1278         test_parser_attr("\x01\x02", word, us); assert(us == 0x0201);
1279         test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x04030201);
1280 //<-
1281 #ifdef BOOST_HAS_LONG_LONG
1282 //->
1283         test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
1284         assert(ul == 0x0807060504030201LL);
1285 
1286 //<-
1287 #endif
1288 //->
1289         test_parser("\x01", byte_(0x01));
1290         test_parser("\x01\x02", word(0x0201));
1291         test_parser("\x01\x02\x03\x04", dword(0x04030201));
1292 //<-
1293 #ifdef BOOST_HAS_LONG_LONG
1294 //->
1295         test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
1296             qword(0x0807060504030201LL));
1297 //<-
1298 #endif
1299 #else
1300 //->
1301         //`Basic usage of the native binary parsers for big endian platforms:
1302         test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
1303         test_parser_attr("\x01\x02", word, us); assert(us ==  0x0102);
1304         test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x01020304);
1305 //<-
1306 #ifdef BOOST_HAS_LONG_LONG
1307 //->
1308         test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
1309         assert(0x0102030405060708LL);
1310 
1311 //<-
1312 #endif
1313 //->
1314         test_parser("\x01", byte_(0x01));
1315         test_parser("\x01\x02", word(0x0102));
1316         test_parser("\x01\x02\x03\x04", dword(0x01020304));
1317 //<-
1318 #ifdef BOOST_HAS_LONG_LONG
1319 //->
1320         test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
1321             qword(0x0102030405060708LL));
1322 //<-
1323 #endif
1324 #endif
1325 //->
1326         //]
1327     }
1328 
1329     // little binary
1330     {
1331         //[reference_qi_little_binary
1332         //`Using declarations and variables:
1333         using boost::spirit::qi::little_word;
1334         using boost::spirit::qi::little_dword;
1335         using boost::spirit::qi::little_qword;
1336 
1337         boost::uint16_t us;
1338         boost::uint32_t ui;
1339 //<-
1340 #ifdef BOOST_HAS_LONG_LONG
1341 //->
1342         boost::uint64_t ul;
1343 //<-
1344 #endif
1345 
1346 //->
1347         //`Basic usage of the little endian binary parsers:
1348         test_parser_attr("\x01\x02", little_word, us); assert(us == 0x0201);
1349         test_parser_attr("\x01\x02\x03\x04", little_dword, ui); assert(ui == 0x04030201);
1350 //<-
1351 #ifdef BOOST_HAS_LONG_LONG
1352 //->
1353         test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", little_qword, ul);
1354         assert(ul == 0x0807060504030201LL);
1355 
1356 //<-
1357 #endif
1358 //->
1359         test_parser("\x01\x02", little_word(0x0201));
1360         test_parser("\x01\x02\x03\x04", little_dword(0x04030201));
1361 //<-
1362 #ifdef BOOST_HAS_LONG_LONG
1363 //->
1364         test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
1365             little_qword(0x0807060504030201LL));
1366 //<-
1367 #endif
1368 //->
1369         //]
1370     }
1371 
1372     // big binary
1373     {
1374         //[reference_qi_big_binary
1375         //`Using declarations and variables:
1376         using boost::spirit::qi::big_word;
1377         using boost::spirit::qi::big_dword;
1378         using boost::spirit::qi::big_qword;
1379 
1380         boost::uint16_t us;
1381         boost::uint32_t ui;
1382 //<-
1383 #ifdef BOOST_HAS_LONG_LONG
1384 //->
1385         boost::uint64_t ul;
1386 //<-
1387 #endif
1388 
1389 //->
1390         //`Basic usage of the big endian binary parsers:
1391         test_parser_attr("\x01\x02", big_word, us); assert(us ==  0x0102);
1392         test_parser_attr("\x01\x02\x03\x04", big_dword, ui); assert(ui == 0x01020304);
1393 //<-
1394 #ifdef BOOST_HAS_LONG_LONG
1395 //->
1396         test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", big_qword, ul);
1397         assert(0x0102030405060708LL);
1398 
1399 //<-
1400 #endif
1401 //->
1402         test_parser("\x01\x02", big_word(0x0102));
1403         test_parser("\x01\x02\x03\x04", big_dword(0x01020304));
1404 //<-
1405 #ifdef BOOST_HAS_LONG_LONG
1406 //->
1407         test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
1408             big_qword(0x0102030405060708LL));
1409 //<-
1410 #endif
1411 //->
1412         //]
1413     }
1414 
1415     // rule
1416     {
1417         //[reference_rule
1418         //`Some using declarations:
1419         using boost::spirit::qi::rule;
1420         using boost::spirit::qi::int_;
1421         using boost::spirit::qi::locals;
1422         using boost::spirit::qi::_1;
1423         using boost::spirit::qi::_a;
1424         using boost::spirit::ascii::alpha;
1425         using boost::spirit::ascii::char_;
1426         using boost::spirit::ascii::space_type;
1427 
1428         /*`Basic rule:
1429          */
1430         rule<char const*> r;
1431         r = int_;
1432         test_parser("123", r);
1433 
1434         /*`Rule with synthesized attribute:
1435          */
1436         rule<char const*, int()> ra;
1437         ra = int_;
1438         int i;
1439         test_parser_attr("123", ra, i);
1440         assert(i ==  123);
1441 
1442         /*`Rule with skipper and synthesized attribute:
1443          */
1444         rule<char const*, std::vector<int>(), space_type> rs;
1445         rs = *int_;
1446         std::vector<int> v;
1447         test_phrase_parser_attr("123 456 789", rs, v);
1448         assert(v[0] ==  123);
1449         assert(v[1] ==  456);
1450         assert(v[2] ==  789);
1451 
1452         /*`Rule with one local variable:
1453          */
1454         rule<char const*, locals<char> > rl;
1455         rl = alpha[_a = _1] >> char_(_a); // get two identical characters
1456         test_parser("aa", rl); // pass
1457         test_parser("ax", rl); // fail
1458         //]
1459     }
1460 
1461     // grammar
1462     {
1463         using client::num_list;
1464 
1465         //[reference_grammar_using
1466         //`Some using declarations:
1467         using boost::spirit::ascii::space_type;
1468         using boost::spirit::int_;
1469         using boost::spirit::qi::grammar;
1470         using boost::spirit::qi::rule;
1471         //]
1472 
1473         //[reference_grammar
1474         //`How to use the example grammar:
1475         num_list nlist;
1476         test_phrase_parser("123, 456, 789", nlist);
1477         //]
1478     }
1479 
1480     return 0;
1481 }
1482