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 //[reference_includes
9 #include <boost/spirit/include/qi.hpp>
10 #include <boost/spirit/include/phoenix_core.hpp>
11 #include <boost/spirit/include/phoenix_operator.hpp>
12 #include <boost/fusion/include/adapt_struct.hpp>
13 #include <boost/spirit/repository/include/qi_kwd.hpp>
14 #include <boost/spirit/repository/include/qi_keywords.hpp>
15 #include <iostream>
16 #include <string>
17 #include <cstdlib>
18 #include <iterator>
19 //]
20 
21 //[reference_test
22 template <typename P>
test_parser(char const * input,P const & p,bool full_match=true)23 void test_parser(
24     char const* input, P const& p, bool full_match = true)
25 {
26     using boost::spirit::qi::parse;
27 
28     char const* f(input);
29     char const* l(f + strlen(f));
30     if (parse(f, l, p) && (!full_match || (f == l)))
31         std::cout << "ok" << std::endl;
32     else
33         std::cout << "fail" << std::endl;
34 }
35 
36 template <typename P>
test_phrase_parser(char const * input,P const & p,bool full_match=true)37 void test_phrase_parser(
38     char const* input, P const& p, bool full_match = true)
39 {
40     using boost::spirit::qi::phrase_parse;
41     using boost::spirit::qi::ascii::space;
42 
43     char const* f(input);
44     char const* l(f + strlen(f));
45     if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
46         std::cout << "ok" << std::endl;
47     else
48         std::cout << "fail" << std::endl;
49 }
50 //]
51 
52 //[reference_test_attr
53 template <typename P, typename T>
test_parser_attr(char const * input,P const & p,T & attr,bool full_match=true)54 void test_parser_attr(
55     char const* input, P const& p, T& attr, bool full_match = true)
56 {
57     using boost::spirit::qi::parse;
58 
59     char const* f(input);
60     char const* l(f + strlen(f));
61     if (parse(f, l, p, attr) && (!full_match || (f == l)))
62         std::cout << "ok" << std::endl;
63     else
64         std::cout << "fail" << std::endl;
65 }
66 
67 template <typename P, typename T>
test_phrase_parser_attr(char const * input,P const & p,T & attr,bool full_match=true)68 void test_phrase_parser_attr(
69     char const* input, P const& p, T& attr, bool full_match = true)
70 {
71     using boost::spirit::qi::phrase_parse;
72     using boost::spirit::qi::ascii::space;
73 
74     char const* f(input);
75     char const* l(f + strlen(f));
76     if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
77         std::cout << "ok" << std::endl;
78     else
79         std::cout << "fail" << std::endl;
80 }
81 //]
82 
83 
84 
85 //[reference_keyword_list_test_data_structure
86 // Data structure definitions to test the kwd directive
87 // and the keywords list operator
88 
89 struct person {
90     std::string name;
91     int age;
92     double size;
93     std::vector<std::string> favorite_colors;
94 
95 };
96 
operator <<(std::ostream & os,const person & p)97 std::ostream &operator<<(std::ostream &os, const person &p)
98 {
99     os<<"Person : "<<p.name<<", "<<p.age<<", "<<p.size<<std::endl;
100     std::copy(p.favorite_colors.begin(),p.favorite_colors.end(),std::ostream_iterator<std::string>(os,"\n"));
101     return os;
102 }
103 
104 BOOST_FUSION_ADAPT_STRUCT( person,
105     (std::string, name)
106     (int, age)
107     (double, size)
108     (std::vector<std::string>, favorite_colors)
109 )
110 //]
111 
112 int
main()113 main()
114 {
115 
116      // keyword_list
117     {
118         //[reference_using_declarations_keyword_list
119         using boost::spirit::repository::qi::kwd;
120         using boost::spirit::qi::inf;
121         using boost::spirit::ascii::space_type;
122         using boost::spirit::ascii::char_;
123         using boost::spirit::qi::double_;
124         using boost::spirit::qi::int_;
125         using boost::spirit::qi::rule;
126         //]
127 
128         //[reference_keyword_list_rule_declarations
129         rule<const char *, std::string(), space_type> parse_string;
130         rule<const char *, person(), space_type> no_constraint_person_rule, constraint_person_rule;
131 
132          parse_string   %= '"'> *(char_-'"') > '"';
133         //]
134 
135         //[reference_keyword_list_no_constraint_rule
136         no_constraint_person_rule %=
137             kwd("name")['=' > parse_string ]
138           / kwd("age")   ['=' > int_]
139           / kwd("size")   ['=' > double_ > 'm']
140           ;
141         //]
142 
143 
144         //[reference_keyword_list
145         //`Parsing a keyword list:
146         // Let's declare a small list of people for which we want to collect information.
147         person John,Mary,Mike,Hellen,Johny;
148         test_phrase_parser_attr(
149                         "name = \"John\" \n age = 10 \n size = 1.69m "
150                         ,no_constraint_person_rule
151                         ,John);  // full in orginal order
152         std::cout<<John;
153 
154         test_phrase_parser_attr(
155                         "age = 10 \n size = 1.69m \n name = \"Mary\""
156                         ,no_constraint_person_rule
157                         ,Mary);  // keyword oder doesn't matter
158         std::cout<<Mary;
159 
160         test_phrase_parser_attr(
161                          "size = 1.69m \n name = \"Mike\" \n age = 10 "
162                         ,no_constraint_person_rule
163                         ,Mike);  // still the same result
164 
165         std::cout<<Mike;
166 
167          /*`The code above will print:[teletype]
168 
169                 Person : John, 10, 1.69
170                 Person : Mary, 10, 1.69
171                 Person : Mike, 10, 1.69
172          */
173         //]
174 
175         //[reference_keyword_list_constraint_rule
176         /*`The parser definition below uses the kwd directive occurrence constraint variants to
177             make sure that the name and age keyword occur only once and allows the favorite color
178             entry to appear 0 or more times. */
179         constraint_person_rule %=
180             kwd("name",1)                 ['=' > parse_string ]
181           / kwd("age"   ,1)                 ['=' > int_]
182           / kwd("size"   ,1)                 ['=' > double_ > 'm']
183           / kwd("favorite color",0,inf) [ '=' > parse_string ]
184           ;
185         //]
186 
187         //[reference_keyword_list_constraints
188 
189         // Here all the give constraint are resepected : parsing will succeed.
190         test_phrase_parser_attr(
191             "name = \"Hellen\" \n age = 10 \n size = 1.80m \n favorite color = \"blue\" \n favorite color = \"green\" "
192             ,constraint_person_rule
193             ,Hellen);
194         std::cout<<Hellen;
195 
196        // Parsing this string will fail because the age and size minimum occurrence requirements aren't met.
197        test_phrase_parser_attr(
198             "name = \"Johny\"  \n favorite color = \"blue\" \n favorite color = \"green\" "
199             ,constraint_person_rule
200             ,Johny );
201 
202         /*`Parsing the first string will succeed but fail for the second string as the
203         occurrence constraints aren't met. This code should print:[teletype]
204 
205         Person : Hellen, 10, 1.8
206         blue
207         green
208         */
209         //]
210     }
211 
212 
213     return 0;
214 }
215