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