1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
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 | #include <boost/spirit/include/qi_auto.hpp> |
7 | |
8 | #include <boost/fusion/include/std_pair.hpp> |
9 | #include <boost/algorithm/string/predicate.hpp> |
10 | |
11 | #include <boost/spirit/include/qi_bool.hpp> |
12 | #include <boost/spirit/include/qi_char.hpp> |
13 | #include <boost/spirit/include/qi_numeric.hpp> |
14 | #include <boost/spirit/include/qi_string.hpp> |
15 | #include <boost/spirit/include/qi_nonterminal.hpp> |
16 | #include <boost/spirit/include/qi_operator.hpp> |
17 | #include <boost/spirit/include/qi_directive.hpp> |
18 | |
19 | #include "test.hpp" |
20 | |
21 | namespace qi = boost::spirit::qi; |
22 | namespace traits = boost::spirit::traits; |
23 | |
24 | /////////////////////////////////////////////////////////////////////////////// |
25 | template <typename Char, typename T> |
26 | bool test_create_parser(Char const *in, T& t) |
27 | { |
28 | Char const* last = in; |
29 | while (*last) |
30 | last++; |
31 | |
32 | BOOST_TEST((traits::meta_create_exists<qi::domain, T>::value)); |
33 | return qi::phrase_parse(in, last, qi::create_parser<T>(), qi::space, t); |
34 | } |
35 | |
36 | template <typename Char, typename T> |
37 | bool test_create_parser_auto(Char const *in, T& t) |
38 | { |
39 | Char const* last = in; |
40 | while (*last) |
41 | last++; |
42 | |
43 | BOOST_TEST((traits::meta_create_exists<qi::domain, T>::value)); |
44 | return qi::phrase_parse(in, last, t, qi::space); |
45 | } |
46 | |
47 | template <typename Char, typename Attribute> |
48 | bool test_rule(Char const* in, Attribute const& expected) |
49 | { |
50 | BOOST_TEST((traits::meta_create_exists<qi::domain, Attribute>::value)); |
51 | |
52 | Attribute attr = Attribute(); |
53 | qi::rule<Char const*, Attribute()> r = qi::create_parser<Attribute>(); |
54 | return spirit_test::test_attr(in, r, attr) && attr == expected; |
55 | } |
56 | |
57 | template <typename Char, typename Attribute, typename Skipper> |
58 | bool test_rule(Char const* in, Attribute const& expected, Skipper const& skipper) |
59 | { |
60 | BOOST_TEST((traits::meta_create_exists<qi::domain, Attribute>::value)); |
61 | |
62 | Attribute attr = Attribute(); |
63 | qi::rule<Char const*, Attribute(), Skipper> r = qi::create_parser<Attribute>(); |
64 | return spirit_test::test_attr(in, r, attr, skipper) && attr == expected; |
65 | } |
66 | |
67 | struct my_type {}; |
68 | |
69 | /////////////////////////////////////////////////////////////////////////////// |
70 | int main() |
71 | { |
72 | { |
73 | BOOST_TEST((!traits::meta_create_exists<qi::domain, my_type>::value)); |
74 | } |
75 | |
76 | { |
77 | // test primitive types |
78 | bool b = false; |
79 | BOOST_TEST(test_create_parser("true" , b) && b == true); |
80 | int i = 0; |
81 | BOOST_TEST(test_create_parser("1" , i) && i == 1); |
82 | double d = 0; |
83 | BOOST_TEST(test_create_parser("1.1" , d) && d == 1.1); |
84 | char c = '\0'; |
85 | BOOST_TEST(test_create_parser("a" , c) && c == 'a'); |
86 | wchar_t wc = L'\0'; |
87 | BOOST_TEST(test_create_parser(L"a" , wc) && wc == L'a'); |
88 | |
89 | // test containers |
90 | std::vector<int> v; |
91 | BOOST_TEST(test_create_parser("0 1 2" , v) && v.size() == 3 && |
92 | v[0] == 0 && v[1] == 1 && v[2] == 2); |
93 | |
94 | std::list<int> l; |
95 | BOOST_TEST(test_create_parser("0 1 2" , l) && l.size() == 3 && |
96 | *l.begin() == 0 && *(++l.begin()) == 1 && *(++ ++l.begin()) == 2); |
97 | |
98 | // test optional |
99 | boost::optional<int> o; |
100 | BOOST_TEST(test_create_parser("" , o) && !o); |
101 | BOOST_TEST(test_create_parser("1" , o) && !!o && boost::get<int>(o) == 1); |
102 | |
103 | // test alternative |
104 | boost::variant<double, bool, std::vector<char> > vv; |
105 | BOOST_TEST(test_create_parser("true" , vv) && vv.which() == 1 && |
106 | boost::get<bool>(vv) == true); |
107 | BOOST_TEST(test_create_parser("1.0" , vv) && vv.which() == 0 && |
108 | boost::get<double>(vv) == 1.0); |
109 | BOOST_TEST(test_create_parser("some_string" , vv) && vv.which() == 2 && |
110 | boost::equals(boost::get<std::vector<char> >(vv), "some_string" )); |
111 | |
112 | // test fusion sequence |
113 | std::pair<int, double> p; |
114 | BOOST_TEST(test_create_parser("1 2.0" , p) && |
115 | p.first == 1 && p.second == 2.0); |
116 | } |
117 | |
118 | { |
119 | // test containers |
120 | std::vector<int> v; |
121 | BOOST_TEST(test_create_parser_auto("0 1 2" , v) && v.size() == 3 && |
122 | v[0] == 0 && v[1] == 1 && v[2] == 2); |
123 | |
124 | std::list<int> l; |
125 | BOOST_TEST(test_create_parser_auto("0 1 2" , l) && l.size() == 3 && |
126 | *l.begin() == 0 && *(++l.begin()) == 1 && *(++ ++l.begin()) == 2); |
127 | |
128 | // test optional |
129 | boost::optional<int> o; |
130 | BOOST_TEST(test_create_parser_auto("" , o) && !o); |
131 | BOOST_TEST(test_create_parser_auto("1" , o) && !!o && boost::get<int>(o) == 1); |
132 | |
133 | // test alternative |
134 | boost::variant<double, bool, std::vector<char> > vv; |
135 | BOOST_TEST(test_create_parser_auto("true" , vv) && vv.which() == 1 && |
136 | boost::get<bool>(vv) == true); |
137 | BOOST_TEST(test_create_parser_auto("1.0" , vv) && vv.which() == 0 && |
138 | boost::get<double>(vv) == 1.0); |
139 | BOOST_TEST(test_create_parser_auto("some_string" , vv) && vv.which() == 2 && |
140 | boost::equals(boost::get<std::vector<char> >(vv), "some_string" )); |
141 | |
142 | // test fusion sequence |
143 | std::pair<int, double> p; |
144 | BOOST_TEST(test_create_parser_auto("1 2.0" , p) && |
145 | p.first == 1 && p.second == 2.0); |
146 | } |
147 | |
148 | { |
149 | using qi::auto_; |
150 | using qi::no_case; |
151 | using spirit_test::test_attr; |
152 | |
153 | // test primitive types |
154 | bool b = false; |
155 | BOOST_TEST(test_attr("true" , auto_, b) && b == true); |
156 | int i = 0; |
157 | BOOST_TEST(test_attr("1" , auto_, i) && i == 1); |
158 | double d = 0; |
159 | BOOST_TEST(test_attr("1.1" , auto_, d) && d == 1.1); |
160 | char c = '\0'; |
161 | BOOST_TEST(test_attr("a" , auto_, c) && c == 'a'); |
162 | wchar_t wc = L'\0'; |
163 | BOOST_TEST(test_attr(L"a" , auto_, wc) && wc == L'a'); |
164 | |
165 | b = false; |
166 | BOOST_TEST(test_attr("TRUE" , no_case[auto_], b) && b == true); |
167 | |
168 | // test containers |
169 | std::vector<int> v; |
170 | BOOST_TEST(test_attr("0 1 2" , auto_, v, qi::space) && v.size() == 3 && |
171 | v[0] == 0 && v[1] == 1 && v[2] == 2); |
172 | v.clear(); |
173 | BOOST_TEST(test_attr("0,1,2" , auto_ % ',', v) && v.size() == 3 && |
174 | v[0] == 0 && v[1] == 1 && v[2] == 2); |
175 | |
176 | std::list<int> l; |
177 | BOOST_TEST(test_attr("0 1 2" , auto_, l, qi::space) && l.size() == 3 && |
178 | *l.begin() == 0 && *(++l.begin()) == 1 && *(++ ++l.begin()) == 2); |
179 | l.clear(); |
180 | BOOST_TEST(test_attr("0,1,2" , auto_ % ',', l) && l.size() == 3 && |
181 | *l.begin() == 0 && *(++l.begin()) == 1 && *(++ ++l.begin()) == 2); |
182 | |
183 | // test optional |
184 | boost::optional<int> o; |
185 | BOOST_TEST(test_attr("" , auto_, o) && !o); |
186 | BOOST_TEST(test_attr("1" , auto_, o) && !!o && boost::get<int>(o) == 1); |
187 | |
188 | // test alternative |
189 | boost::variant<double, bool, std::vector<char> > vv; |
190 | BOOST_TEST(test_attr("true" , auto_, vv) && vv.which() == 1 && |
191 | boost::get<bool>(vv) == true); |
192 | BOOST_TEST(test_attr("1.0" , auto_, vv) && vv.which() == 0 && |
193 | boost::get<double>(vv) == 1.0); |
194 | BOOST_TEST(test_create_parser("some_string" , vv) && vv.which() == 2 && |
195 | boost::equals(boost::get<std::vector<char> >(vv), "some_string" )); |
196 | |
197 | // test fusion sequence |
198 | std::pair<int, double> p; |
199 | BOOST_TEST(test_attr("1 2.0" , auto_, p, qi::space) && |
200 | p.first == 1 && p.second == 2.0); |
201 | } |
202 | |
203 | { |
204 | // test primitive types |
205 | BOOST_TEST(test_rule("true" , true)); |
206 | BOOST_TEST(test_rule("1" , 1)); |
207 | BOOST_TEST(test_rule("1.1" , 1.1)); |
208 | |
209 | // test containers |
210 | std::vector<int> v; |
211 | v.push_back(x: 0); |
212 | v.push_back(x: 1); |
213 | v.push_back(x: 2); |
214 | BOOST_TEST(test_rule("0 1 2" , v, qi::space)); |
215 | |
216 | std::list<int> l; |
217 | l.push_back(x: 0); |
218 | l.push_back(x: 1); |
219 | l.push_back(x: 2); |
220 | BOOST_TEST(test_rule("0 1 2" , l, qi::space)); |
221 | |
222 | // test optional |
223 | boost::optional<int> o; |
224 | BOOST_TEST(test_rule("" , o)); |
225 | o = 1; |
226 | BOOST_TEST(test_rule("1" , o)); |
227 | |
228 | // test alternative |
229 | // boost::variant<int, double, float, std::string> vv; |
230 | // vv = 1; |
231 | // BOOST_TEST(test_rule("1", vv)); |
232 | // vv = 1.0; |
233 | // BOOST_TEST(test_rule("1.0", vv)); |
234 | // vv = 1.0f; |
235 | // BOOST_TEST(test_rule("1.0", vv)); |
236 | // vv = "some string"; |
237 | // BOOST_TEST(test_rule("some string", vv)); |
238 | |
239 | // test fusion sequence |
240 | std::pair<int, double> p (1, 2.0); |
241 | BOOST_TEST(test_rule("1 2.0" , p, qi::space)); |
242 | } |
243 | |
244 | { |
245 | // test literal char interference |
246 | using spirit_test::test; |
247 | BOOST_TEST(test("x" , 'x')); |
248 | BOOST_TEST(test("x" , 'x', qi::space)); |
249 | BOOST_TEST(!test("y" , 'x')); |
250 | BOOST_TEST(!test("y" , 'x', qi::space)); |
251 | BOOST_TEST(test(L"x" , L'x')); |
252 | BOOST_TEST(test(L"x" , L'x', qi::space)); |
253 | BOOST_TEST(!test(L"y" , L'x')); |
254 | BOOST_TEST(!test(L"y" , L'x', qi::space)); |
255 | } |
256 | |
257 | return boost::report_errors(); |
258 | } |
259 | |