• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2011 Thomas Bernard
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 #include <string>
9 #include <vector>
10 
11 #include <boost/detail/lightweight_test.hpp>
12 #include <boost/utility/enable_if.hpp>
13 
14 #include <boost/spirit/include/qi_operator.hpp>
15 #include <boost/spirit/include/qi_char.hpp>
16 #include <boost/spirit/include/qi_string.hpp>
17 #include <boost/spirit/include/qi_numeric.hpp>
18 #include <boost/spirit/include/qi_directive.hpp>
19 #include <boost/spirit/include/qi_action.hpp>
20 #include <boost/spirit/include/qi_nonterminal.hpp>
21 #include <boost/spirit/include/support_argument.hpp>
22 #include <boost/spirit/include/phoenix_core.hpp>
23 #include <boost/spirit/include/phoenix_operator.hpp>
24 #include <boost/spirit/include/phoenix_container.hpp>
25 #include <boost/spirit/repository/include/qi_kwd.hpp>
26 #include <boost/spirit/repository/include/qi_keywords.hpp>
27 
28 #include <string>
29 #include <iostream>
30 #include "test.hpp"
31 
32 struct x_attr
33 {
34 
35 };
36 
37 namespace boost { namespace spirit { namespace traits
38 {
39 
40 
41     template <>
42     struct container_value<x_attr>
43     {
44         typedef char type; // value type of container
45     };
46 
47 
48     template <>
49     struct push_back_container<x_attr, char>
50     {
callboost::spirit::traits::push_back_container51         static bool call(x_attr& /*c*/, char /*val*/)
52         {
53             // push back value type into container
54             return true;
55         }
56     };
57 }}}
58 
59 int
main()60 main()
61 {
62     using spirit_test::test_attr;
63     using spirit_test::test;
64     using namespace boost::spirit;
65     using namespace boost::spirit::ascii;
66     using boost::spirit::repository::kwd;
67     using boost::spirit::repository::ikwd;
68     using boost::spirit::repository::dkwd;
69     using boost::spirit::qi::inf;
70     using boost::spirit::qi::omit;
71     using boost::spirit::qi::int_;
72     using boost::spirit::qi::lit;
73     using boost::spirit::qi::_1;
74     using boost::spirit::qi::lexeme;
75 
76 
77     {
78 
79         // no constraints
80         boost::fusion::vector<char,char,int> data;
81         BOOST_TEST( test_attr("c=1 a=a", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], data, space));
82         BOOST_TEST( boost::fusion::at_c<0>(data) == 'a' );
83         BOOST_TEST( boost::fusion::at_c<1>(data) == 0 );
84         BOOST_TEST( boost::fusion::at_c<2>(data) == 1 );
85 
86         BOOST_TEST( test("a=a c=1", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
87 
88         BOOST_TEST( test("", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
89 
90         // Exact
91         BOOST_TEST(test("a=a b=b c=1", kwd("a",1)[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
92         BOOST_TEST(test("a=a b=c b=e c=1", kwd("a",1)[ '=' > char_] / kwd("b",2)[ '=' > char_] / kwd("c")['=' > int_], space));
93         BOOST_TEST(!test("b=c b=e c=1", kwd("a",1)[ '=' > char_] / kwd("b",2)[ '=' > char_] / kwd("c")['=' > int_], space));
94 
95         // Min - Max
96         BOOST_TEST(test("a=f b=c b=e c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,2)[ '=' > char_] / kwd("c",1,2)['=' > int_], space));
97         BOOST_TEST(!test("b=c b=e c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,1)[ '=' > char_] / kwd("c",1,2)['=' > int_], space));
98         BOOST_TEST(test("a=g a=f b=c b=e c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,2)[ '=' > char_] / kwd("c",1,2)['=' > int_], space));
99         BOOST_TEST(!test("a=f a=e b=c b=e a=p c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,1)[ '=' > char_] / kwd("c",1,2)['=' > int_], space));
100 
101         // Min - inf
102         BOOST_TEST(test("a=f b=c b=e c=1", kwd("a",1,inf)[ '=' > char_] / kwd("b",0,inf)[ '=' > char_] / kwd("c",1,inf)['=' > int_], space ));
103         BOOST_TEST(!test("b=c b=e c=1", kwd("a",1,inf)[ '=' > char_] / kwd("b",0,inf)[ '=' > char_] / kwd("c",1,inf)['=' > int_], space ));
104         BOOST_TEST(test("a=f a=f a=g b=c b=e c=1 a=e", kwd("a",1,inf)[ '=' > char_] / kwd("b",0,inf)[ '=' > char_] / kwd("c",1,inf)['=' > int_], space ));
105     }
106 
107     {   // Single keyword, empty string
108         BOOST_TEST(test(" ", kwd("aad")[char_],space));
109         // Single keyword
110         BOOST_TEST(test("aad E ", kwd("aad")[char_],space));
111         // Single no case keyword
112         BOOST_TEST(test("AaD E ", ikwd("aad")[char_],space));
113 
114     }
115 
116     {
117         // Vector container
118         boost::fusion::vector<std::vector<int>,std::vector<int>,std::vector<int> > data;
119         BOOST_TEST(test_attr(" a=1 b=2 b=5 c=3",kwd("a")[ '=' > int_] / kwd("b")[ '=' > int_] / kwd("c")['=' > int_] , data, space)
120                     && (boost::fusion::at_c<0>(data).size()==1)
121                     && (boost::fusion::at_c<0>(data)[0]==1)
122 
123                     &&(boost::fusion::at_c<1>(data).size()==2)
124                     &&(boost::fusion::at_c<1>(data)[0]==2)
125                     &&(boost::fusion::at_c<1>(data)[1]==5)
126 
127                     &&(boost::fusion::at_c<2>(data).size()==1)
128                     &&(boost::fusion::at_c<2>(data)[0]==3)
129             );
130     }
131 
132     {
133         // no_case test
134         BOOST_TEST( test("B=a c=1 a=E", no_case[kwd("a")[ "=E" ] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_]], space));
135         BOOST_TEST( test("B=a c=1 a=e", no_case[kwd("a")[ "=E" ] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_]], space));
136         BOOST_TEST( !test("B=a c=1 A=E", no_case[kwd("a")[ '=' > char_]] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
137         BOOST_TEST( test("b=a c=1 A=E", no_case[kwd("a")[ '=' > char_]] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
138         BOOST_TEST( !test("A=a c=1 a=E", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
139         BOOST_TEST( test("A=a c=1 a=E", ikwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
140         BOOST_TEST( !test("A=a C=1 a=E", ikwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space));
141     }
142 
143     {
144         // iterator restoration
145         BOOST_TEST( test("a=a c=1 ba=d", (kwd("a")[ '=' > char_] / kwd("b")[ '=' > int_] / kwd("c")['=' > int_] ) > lit("ba=") > char_, space));
146         BOOST_TEST( test("A=a c=1 ba=d", (ikwd("a")[ '=' > char_] / kwd("b")[ '=' > int_] / kwd("c")['=' > int_] ) > lit("ba=") > char_, space));
147     }
148 
149     { // actions
150         namespace phx = boost::phoenix;
151 
152         std::vector<int> v;
153         BOOST_TEST(test("b=2 c=4", kwd("b")['=' > int_][phx::ref(v)=_1] / kwd("c")[ '=' > int_ ],space) &&
154             v[0] == 2 );
155     }
156 
157 
158     {
159         // no constraints
160         boost::fusion::vector<char,char,int> data;
161         BOOST_TEST( test_attr("c,1,2=1 2,b=a", kwd( char_ >> lit(',') >> int_ )[ '=' >> char_] / kwd(int_ >> lit(',') >> char_)[ '=' >> char_] / kwd(char_ >> lit(',') >> int_ >> lit(',') >> int_)['=' >> int_], data, space));
162         BOOST_TEST( boost::fusion::at_c<0>(data) == 0 );
163         BOOST_TEST( boost::fusion::at_c<1>(data) == 'a');
164         BOOST_TEST( boost::fusion::at_c<2>(data) == 1 );
165 
166         BOOST_TEST( test("2,b=a c,1,2=1", kwd( char_ >> ',' >> int_ )[ '=' >> char_] / kwd(int_ >> ',' >> char_)[ '=' >> char_] / kwd(char_ >> ',' >> int_ >> ',' >> int_)['=' >> int_], space));
167 
168         BOOST_TEST( test("", kwd( char_ >> ',' >> int_ )[ '=' >> char_] / kwd(int_ >> ',' >> char_)[ '=' >> char_] / kwd(char_ >> ',' >> int_ >> ',' >> int_)['=' >> int_], space));
169 
170         // Exact
171         BOOST_TEST(test("7a=a 5b=b 2c=1", kwd(int_ >> lit('a'),1)[ '=' >> char_] / kwd(int_ >> lit('b'))[ '=' >> char_] / kwd(int_ >> lit('c'))['=' >> int_], space));
172         BOOST_TEST(test("7a=a 3b=d 5b=b 2c=1", kwd(int_ >> lit('a'),1)[ '=' >> char_] / kwd(int_ >> lit('b'),2)[ '=' >> char_] / kwd(int_ >>'c')['=' >> int_], space));
173         BOOST_TEST(!test("7a=a 5b=b 2c=1", kwd(int_ >> lit('a'),1)[ '=' >> char_] / kwd(int_ >> lit('b'),2)[ '=' >> char_] / kwd(int_ >>'c')['=' >> int_], space));
174 
175         // Min - Max
176         BOOST_TEST(test("6a=f 2b=c 3b=e 1c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,2)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space));
177         BOOST_TEST(!test("1b=c 6b=e 2c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,1)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space));
178         BOOST_TEST(test("4a=g 7a=f 2b=c 1b=e 4c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,2)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space));
179         BOOST_TEST(!test("1a=f a=e 2b=c 5b=e 6a=p 67c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,1)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space));
180 
181         // Min - inf
182         BOOST_TEST(test("41a=f 44b=c 12b=e 45c=1", kwd(int_ >> "a",1,inf)[ '=' >> char_] / kwd(int_ >> "b",0,inf)[ '=' >> char_] / kwd(int_ >> "c",1,inf)['=' >> int_], space ));
183         BOOST_TEST(!test("31b=c 55b=e 2c=1", kwd("a",1,inf)[ '=' >> char_] / kwd("b",0,inf)[ '=' >> char_] / kwd("c",1,inf)['=' >> int_], space ));
184         BOOST_TEST(test("12a=f 45a=f 12a=g 1b=c 7b=e 12c=1 6a=e", kwd(int_ >> "a",1,inf)[ '=' >> char_] / kwd(int_ >> "b",0,inf)[ '=' >> char_] / kwd(int_ >> "c",1,inf)['=' >> int_], space ));
185 
186     }
187 
188     {
189 
190         // Vector container
191         boost::fusion::vector<std::vector<int>,std::vector<int>,std::vector<int> > data;
192         BOOST_TEST(test_attr(" 41a=1 4b=2 12b=5 5c=3",kwd(int_ >> "a")[ '=' >> int_] / kwd(int_ >> "b")[ '=' >> int_] / kwd(int_ >> "c")['=' >> int_] , data, space)
193             && (boost::fusion::at_c<0>(data).size()==1)
194             && (boost::fusion::at_c<0>(data)[0]==1)
195 
196             &&(boost::fusion::at_c<1>(data).size()==2)
197             &&(boost::fusion::at_c<1>(data)[0]==2)
198             &&(boost::fusion::at_c<1>(data)[1]==5)
199 
200             &&(boost::fusion::at_c<2>(data).size()==1)
201             &&(boost::fusion::at_c<2>(data)[0]==3)
202          );
203 
204 
205 
206     }
207 
208     {
209         // no_case test
210         BOOST_TEST( test("12B=a 5c=1 1a=E", no_case[kwd(int_ >> "a")[ "=E" ] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_]], space));
211         BOOST_TEST( test("5B=a 2c=1 5a=e", no_case[kwd(int_ >> "a")[ "=E" ] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_]], space));
212         BOOST_TEST( !test("1B=a 8c=1 1A=E", no_case[kwd(int_ >> "a")[ '=' >> char_]] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space));
213         BOOST_TEST( test("2b=a 6c=1 5A=E", no_case[kwd(int_ >> "a")[ '=' >> char_]] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space));
214         BOOST_TEST( !test("1A=a 5c=1 1a=E", kwd(int_ >> "a")[ '=' >> char_] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space));
215         BOOST_TEST( test("A=a 23c=1 a=E", ikwd("a")[ '=' >> char_] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space));
216         BOOST_TEST( !test("A=a 21C=1 a=E", ikwd("a")[ '=' >> char_] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space));
217     }
218 
219     {
220         // iterator restoration
221         BOOST_TEST( test("4a=a c4=1 ba=d", (kwd(int_ >> "a")[ '=' >> char_] / kwd("b" >> int_)[ '=' >> int_] / kwd("c" >> int_ )['=' >> int_] ) >> lit("ba=") >> char_, space));
222     }
223 
224     { // actions
225         namespace phx = boost::phoenix;
226 
227         std::vector<int> v;
228         BOOST_TEST(test("b4=2 c1=4", kwd("b" >> int_)['=' >> int_][phx::ref(v)=_1] / kwd("c" >> int_)[ '=' >> int_ ],space) &&
229             v[0] == 2 );
230     }
231 
232     {
233         // complex keyword single test
234         int result=0;
235 
236         BOOST_TEST( test_attr("(a,1) = 3214", kwd( '(' >> char_ >> ',' >> int_ >> ')' )['=' >> int_], result, space) );
237         BOOST_TEST(result==3214);
238     }
239     {
240         // Mixed complex keyword loop
241         boost::fusion::vector<int,int,int> data;
242 
243         BOOST_TEST( test_attr("(a,1) = 3214 b += 2 hello 10 (a,2)=31", kwd( '(' >> char_ >> ',' >> int_ >> ')' )['=' >> int_] / kwd("hello")[int_] / kwd("b")["+=" >> int_], data, space) );
244         BOOST_TEST( boost::fusion::at_c<0>(data) == 31);
245         BOOST_TEST( boost::fusion::at_c<1>(data) == 10);
246         BOOST_TEST( boost::fusion::at_c<2>(data) == 2);
247     }
248 
249     // dkwd and idkwd
250     {
251       BOOST_TEST( test("a =a", dkwd("a")[ '=' > char_] , space));
252       BOOST_TEST( !test("a=a", dkwd("a")[ '=' > char_] , space));
253       BOOST_TEST(test("a =a b =b c=1", dkwd("a",1)[ '=' > char_] / dkwd("b",1,2)[ '=' > char_] / kwd("c")['=' > int_], space));
254       BOOST_TEST(!test("a=a b=b c =1", dkwd("a",1)[ '=' > char_] / dkwd("b",1,2)[ '=' > char_] / kwd("c")['=' > int_], space));
255 
256       BOOST_TEST(test("a =a b =b b =d c=1", dkwd("a",1,inf)[ '=' > char_] / dkwd("b",2,inf)[ '=' > char_] / kwd("c")['=' > int_], space));
257 
258     }
259 
260     { // attribute customization
261 
262 //        x_attr x;
263 //        test_attr("a = b c = d", kwd("a")['=' > char_] / kwd("c")['=' > char_], x);
264     }
265 
266 
267    return boost::report_errors();
268 }
269 
270