]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
1e59de90 TL |
10 | #include <boost/phoenix/core.hpp> |
11 | #include <boost/phoenix/operator.hpp> | |
7c673cae FG |
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> | |
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> | |
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> | |
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> | |
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 | ||
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 | |
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 | |
f67539c2 | 151 | ,John); // full in original order |
7c673cae FG |
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 | } |