• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/assign/std/vector.hpp>
10 
11 #include <boost/spirit/include/karma_char.hpp>
12 #include <boost/spirit/include/karma_string.hpp>
13 #include <boost/spirit/include/karma_numeric.hpp>
14 #include <boost/spirit/include/karma_generate.hpp>
15 #include <boost/spirit/include/karma_operator.hpp>
16 #include <boost/spirit/include/karma_action.hpp>
17 #include <boost/spirit/include/karma_nonterminal.hpp>
18 #include <boost/spirit/include/karma_auxiliary.hpp>
19 #include <boost/spirit/include/karma_directive.hpp>
20 #include <boost/fusion/include/vector.hpp>
21 #include <boost/spirit/include/phoenix_core.hpp>
22 #include <boost/spirit/include/phoenix_operator.hpp>
23 #include <boost/fusion/include/std_pair.hpp>
24 
25 #include <boost/assign/std/vector.hpp>
26 
27 #include "test.hpp"
28 
29 using namespace spirit_test;
30 
31 ///////////////////////////////////////////////////////////////////////////////
32 struct action
33 {
actionaction34     action (std::vector<char>& vec)
35       : vec(vec), it(vec.begin())
36     {}
37 
operator ()action38     void operator()(unsigned& value, boost::spirit::unused_type, bool& pass) const
39     {
40        pass = (it != vec.end());
41        if (pass)
42            value = *it++;
43     }
44 
45     std::vector<char>& vec;
46     mutable std::vector<char>::iterator it;
47 };
48 
49 struct A
50 {
51     double d1;
52     double d2;
53 };
54 
55 BOOST_FUSION_ADAPT_STRUCT(
56     A,
57     (double, d1)
58     (double, d2)
59 )
60 
61 ///////////////////////////////////////////////////////////////////////////////
main()62 int main()
63 {
64     using namespace boost::spirit;
65     using namespace boost::spirit::ascii;
66     namespace fusion = boost::fusion;
67 
68     {
69         std::string s1("aaaa");
70         BOOST_TEST(test("aaaa", *char_, s1));
71         BOOST_TEST(test_delimited("a a a a ", *char_, s1, ' '));
72 
73         std::string s2("");
74         BOOST_TEST(test("", *char_, s2));
75         BOOST_TEST(test_delimited("", *char_, s2, ' '));
76     }
77 
78     {
79         std::string s1("aaaaa");
80         BOOST_TEST(test("aaaaa", char_ << *(char_ << char_), s1));
81         BOOST_TEST(test_delimited("a a a a a ",
82             char_ << *(char_ << char_), s1, ' '));
83 
84         s1 = "a";
85         BOOST_TEST(test("a", char_ << *(char_ << char_), s1));
86         s1 = "aa";
87         BOOST_TEST(!test("", char_ << *(char_ << char_), s1));
88 //         BOOST_TEST(test("aa", char_ << *buffer[char_ << char_] << char_, s1));
89         s1 = "aaaa";
90         BOOST_TEST(!test("", char_ << *(char_ << char_), s1));
91 //         BOOST_TEST(test("aaaa", char_ << *buffer[char_ << char_] << char_, s1));
92     }
93 
94     {
95         using boost::spirit::karma::strict;
96         using boost::spirit::karma::relaxed;
97         using namespace boost::assign;
98 
99         typedef std::pair<char, char> data;
100         std::vector<data> v1;
101         v1 += std::make_pair('a', 'a'),
102               std::make_pair('b', 'b'),
103               std::make_pair('c', 'c'),
104               std::make_pair('d', 'd'),
105               std::make_pair('e', 'e'),
106               std::make_pair('f', 'f'),
107               std::make_pair('g', 'g');
108 
109         karma::rule<spirit_test::output_iterator<char>::type, data()> r;
110         r = &char_('a') << char_;
111 
112         BOOST_TEST(test("a", r << *(r << r), v1));
113         BOOST_TEST(test("a", relaxed[r << *(r << r)], v1));
114         BOOST_TEST(!test("", strict[r << *(r << r)], v1));
115 
116          v1 += std::make_pair('a', 'a');
117 
118         BOOST_TEST(!test("", r << *(r << r), v1));
119         BOOST_TEST(!test("", relaxed[r << *(r << r)], v1));
120         BOOST_TEST(!test("", strict[r << *(r << r)], v1));
121 
122          v1 += std::make_pair('a', 'a');
123 
124         BOOST_TEST(test("aaa", r << *(r << r), v1));
125         BOOST_TEST(test("aaa", relaxed[r << *(r << r)], v1));
126         BOOST_TEST(!test("", strict[r << *(r << r)], v1));
127     }
128 
129     {
130         using namespace boost::assign;
131 
132         std::vector<char> v;
133         v += 'a', 'b', 'c';
134 
135         BOOST_TEST(test("abc", *char_, v));
136         BOOST_TEST(test_delimited("a b c ", *char_, v, ' '));
137     }
138 
139     {
140         using namespace boost::assign;
141 
142         std::vector<int> v;
143         v += 10, 20, 30;
144 
145         BOOST_TEST(test("102030", *int_, v));
146         BOOST_TEST(test_delimited("10, 20, 30, ", *int_, v, lit(", ")));
147 
148         BOOST_TEST(test("10,20,30,", *(int_ << ','), v));
149         BOOST_TEST(test_delimited("10 , 20 , 30 , ", *(int_ << ','), v, lit(' ')));
150 
151 // leads to infinite loops
152 //         fusion::vector<char, char> cc ('a', 'c');
153 //         BOOST_TEST(test("ac", char_ << *(lit(' ') << ',') << char_, cc));
154 //         BOOST_TEST(test_delimited("a c ",
155 //             char_ << *(lit(' ') << ',') << char_, cc, " "));
156     }
157 
158     { // actions
159         using namespace boost::assign;
160         namespace phx = boost::phoenix;
161 
162         std::vector<char> v;
163         v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
164 
165         BOOST_TEST(test("abcdefgh", (*char_)[_1 = phx::ref(v)]));
166         BOOST_TEST(test_delimited("a b c d e f g h ",
167             (*char_ )[_1 = phx::ref(v)], space));
168     }
169 
170     // failing sub-generators
171     {
172         using boost::spirit::karma::strict;
173         using boost::spirit::karma::relaxed;
174 
175         using namespace boost::assign;
176 
177         typedef std::pair<char, char> data;
178         std::vector<data> v2;
179         v2 += std::make_pair('a', 'a'),
180               std::make_pair('b', 'b'),
181               std::make_pair('c', 'c'),
182               std::make_pair('d', 'd'),
183               std::make_pair('e', 'e'),
184               std::make_pair('f', 'f'),
185               std::make_pair('g', 'g');
186 
187         karma::rule<spirit_test::output_iterator<char>::type, data()> r;
188 
189         r = &char_('d') << char_;
190         BOOST_TEST(test("d", *r, v2));
191         BOOST_TEST(test("d", relaxed[*r], v2));
192         BOOST_TEST(test("", strict[*r], v2));
193 
194         r = &char_('a') << char_;
195         BOOST_TEST(test("a", *r, v2));
196         BOOST_TEST(test("a", relaxed[*r], v2));
197         BOOST_TEST(test("a", strict[*r], v2));
198 
199         r = &char_('g') << char_;
200         BOOST_TEST(test("g", *r, v2));
201         BOOST_TEST(test("g", relaxed[*r], v2));
202         BOOST_TEST(test("", strict[*r], v2));
203 
204         r = !char_('d') << char_;
205         BOOST_TEST(test("abcefg", *r, v2));
206         BOOST_TEST(test("abcefg", relaxed[*r], v2));
207         BOOST_TEST(test("abc", strict[*r], v2));
208 
209         r = !char_('a') << char_;
210         BOOST_TEST(test("bcdefg", *r, v2));
211         BOOST_TEST(test("bcdefg", relaxed[*r], v2));
212         BOOST_TEST(test("", strict[*r], v2));
213 
214         r = !char_('g') << char_;
215         BOOST_TEST(test("abcdef", *r, v2));
216         BOOST_TEST(test("abcdef", relaxed[*r], v2));
217         BOOST_TEST(test("abcdef", strict[*r], v2));
218 
219         r = &char_('A') << char_;
220         BOOST_TEST(test("", *r, v2));
221     }
222 
223     {
224         // make sure user defined end condition is applied if no attribute
225         // is passed in
226         using namespace boost::assign;
227 
228         std::vector<char> v;
229         v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
230         BOOST_TEST(test("[6162636465666768]", '[' << *hex[action(v)] << ']'));
231     }
232 
233     {
234         using boost::spirit::karma::double_;
235 
236         std::vector<A> v(1);
237         v[0].d1 = 1.0;
238         v[0].d2 = 2.0;
239         BOOST_TEST(test("A1.02.0", 'A' << *(double_ << double_), v));
240     }
241 
242     return boost::report_errors();
243 }
244 
245