1 //  Copyright (c) 2011 Aaron Graham
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 //  The purpose of this example is to demonstrate the use of the advance parser.
7 
8 //[qi_advance_includes
9 #include <boost/spirit/include/qi.hpp>
10 #include <boost/spirit/include/phoenix_operator.hpp>
11 #include <boost/spirit/repository/include/qi_advance.hpp>
12 //]
13 
14 #include <list>
15 #include <string>
16 
17 //[qi_advance_namespaces
18 namespace qi = boost::spirit::qi;
19 using boost::spirit::repository::qi::advance;
20 //]
21 
22 namespace client
23 {
24     //[qi_advance_grammar
25     template <typename Iterator>
26     struct advance_grammar : qi::grammar<Iterator, qi::locals<int> >
27     {
advance_grammarclient::advance_grammar28         advance_grammar() : advance_grammar::base_type(start)
29         {
30             using qi::byte_;
31             using qi::eoi;
32             using namespace qi::labels;
33 
34             start
35                 =  byte_  [_a = _1]
36                 >> advance(_a)
37                 >> "boost"
38                 >> byte_  [_a = _1]
39                 >> (advance(_a) | "qi") // note alternative when advance fails
40                 >> eoi
41                 ;
42         }
43 
44         qi::rule<Iterator, qi::locals<int> > start;
45     };
46     //]
47 }
48 
main()49 int main()
50 {
51     // This parser is tested with both random access iterators (std::string)
52     // and bidirectional iterators (std::list).
53     char const* result;
54 
55     //[qi_advance_example1
56     unsigned char const alt1[] =
57     {
58         5,                         // number of bytes to advance
59         1, 2, 3, 4, 5,             // data to advance through
60         'b', 'o', 'o', 's', 't',   // word to parse
61         2,                         // number of bytes to advance
62         11, 12                     // more data to advance through
63         // eoi
64     };
65 
66     std::string const alt1_string(alt1, alt1 + sizeof alt1);
67     std::list<unsigned char> const alt1_list(alt1, alt1 + sizeof alt1);
68 
69     result =
70         qi::parse(alt1_string.begin(), alt1_string.end()
71             , client::advance_grammar<std::string::const_iterator>())
72         ? "succeeded" : "failed";
73     std::cout << "Parsing alt1 using random access iterator " << result << std::endl;
74 
75     result =
76         qi::parse(alt1_list.begin(), alt1_list.end()
77             , client::advance_grammar<std::list<unsigned char>::const_iterator>())
78         ? "succeeded" : "failed";
79     std::cout << "Parsing alt1 using bidirectional iterator " << result << std::endl;
80     //]
81 
82     //[qi_advance_example2
83     unsigned char const alt2[] =
84     {
85         2,                         // number of bytes to advance
86         1, 2,                      // data to advance through
87         'b', 'o', 'o', 's', 't',   // word to parse
88         4,                         // number of bytes to advance
89         'q', 'i'                   // alternative (advance won't work)
90         // eoi
91     };
92 
93     std::string const alt2_string(alt2, alt2 + sizeof alt2);
94     std::list<unsigned char> const alt2_list(alt2, alt2 + sizeof alt2);
95 
96     result =
97         qi::parse(alt2_string.begin(), alt2_string.end()
98             , client::advance_grammar<std::string::const_iterator>())
99         ? "succeeded" : "failed";
100     std::cout << "Parsing alt2 using random access iterator " << result << std::endl;
101 
102     result =
103         qi::parse(alt2_list.begin(), alt2_list.end()
104             , client::advance_grammar<std::list<unsigned char>::const_iterator>())
105         ? "succeeded" : "failed";
106     std::cout << "Parsing alt2 using bidirectional iterator " << result << std::endl;
107     //]
108 
109     return 0;
110 }
111