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