1 ///////////////////////////////////////////////////////////////////////////////
2 // test_typeof2.cpp
3 //
4 //  Copyright 2008 David Jenkins. Distributed under the Boost
5 //  Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #define BOOST_TYPEOF_LIMIT_SIZE 200
9 #define BOOST_TYPEOF_EMULATION 1
10 
11 #include <string>
12 #include <map>
13 #include <list>
14 #include <stack>
15 #include <boost/version.hpp>
16 #include <boost/xpressive/xpressive_static.hpp>
17 #include <boost/xpressive/regex_actions.hpp>
18 #include <boost/xpressive/xpressive_typeof.hpp>
19 #include <boost/typeof/std/stack.hpp>
20 #include <boost/typeof/std/list.hpp>
21 #include <boost/test/unit_test.hpp>
22 
23 
24 // I couldn't find these registrations anywhere else, so I put them here
25 // They are necessary for this program to compile
26 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
27 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::mpl::int_, (int))
28 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::reference_wrapper, (typename))
29 
30 // Here's the test for typeof registration, to be used on static regular expressions
31 #define TYPEOF_TEST(Expr) { BOOST_PROTO_AUTO(Dummy, Expr); }
32 
33 namespace xp = boost::xpressive;
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 // test_actions
37 //  regular expressions from test_actions.cpp
test_actions()38 void test_actions()
39 {
40     using namespace boost::xpressive;
41     // regexes from test_actions.cpp
42     std::string result;
43     TYPEOF_TEST((+_w)[ xp::ref(result) += _ ] >> *(' ' >> (+_w)[ xp::ref(result) += ',' + _ ]));
44     TYPEOF_TEST((+_w)[ xp::ref(result) += _ ] >> *(' ' >> (+_w)[ xp::ref(result) += ',' + _ ]) >> repeat<4>(_));
45     std::list<int> result2;
46     TYPEOF_TEST((+_d)[ xp::ref(result2)->*push_back( as<int>(_) ) ]
47         >> *(' ' >> (+_d)[ xp::ref(result2)->*push_back( as<int>(_) ) ]));
48     std::map<std::string, int> result3;
49     TYPEOF_TEST(( (s1= +_w) >> "=>" >> (s2= +_d) )[ xp::ref(result3)[s1] = as<int>(s2) ]);
50     placeholder< std::map<std::string, int> > const _map5 = {{}};
51     TYPEOF_TEST(( (s1= +_w) >> "=>" >> (s2= +_d) )[ _map5[s1] = as<int>(s2) ]);
52 
53     smatch what;
54     placeholder< std::map<std::string, int> > const _map6 = {{}};
55     std::map<std::string, int> result6;
56     what.let(_map6 = result6); // bind the argument!
57 
58     local<int> left, right;
59     std::stack<int> stack_;
60     reference<std::stack<int> > stack(stack_);
61     cregex expression2, factor2, term2, group2;
62     TYPEOF_TEST( '(' >> by_ref(expression2) >> ')');
63     TYPEOF_TEST( (+_d)[ push(stack, as<int>(_)) ] | group2);
64     TYPEOF_TEST(factor2 >> *(
65             ('*' >> factor2)
66                 [ right = top(stack)
67                 , pop(stack)
68                 , left = top(stack)
69                 , pop(stack)
70                 , push(stack, left * right)
71                 ]
72          ));
73     TYPEOF_TEST(term2 >> *(
74             ('+' >> term2)
75                 [ right = top(stack)
76                 , pop(stack)
77                 , left = top(stack)
78                 , pop(stack)
79                 , push(stack, left + right)
80                 ]
81          ));
82 }
83 
84 
85 #ifndef BOOST_XPRESSIVE_NO_WREGEX
86     struct City
87     {
88         std::wstring name;
89         char const* nickname;
90         int population;
91     };
BOOST_TYPEOF_REGISTER_TYPE(City)92     BOOST_TYPEOF_REGISTER_TYPE(City)
93 #endif
94 
95 ///////////////////////////////////////////////////////////////////////////////
96 // test_symbols
97 //  regular expressions from test_symbols.cpp
98 void test_symbols()
99 {
100     using namespace boost::xpressive;
101     std::string result;
102     std::map<std::string,std::string> map10;
103     TYPEOF_TEST((a1=map10)[ xp::ref(result) = a1 ] >> *(' ' >> (a1=map10)[ xp::ref(result) += ',' + a1 ]));
104     TYPEOF_TEST((a1=map10)[ xp::ref(result) = a1 ]
105         >> *((a1=map10)[ xp::ref(result) += ',', xp::ref(result) += a1 ]));
106     std::list<int> result12;
107     std::map<std::string,int> map12;
108     TYPEOF_TEST((a1=map12)[ xp::ref(result12)->*push_back( a1 ) ]
109         >> *(' ' >> (a1=map12)[ xp::ref(result12)->*push_back( a1 ) ]));
110 
111     placeholder< std::map<std::string, int> > const _map13 = {};
112     BOOST_PROTO_AUTO(pair13, ( (a1=map10) >> "=>" >> (a2= map12) )[ _map13[a1] = a2 ]);
113     smatch what;
114     std::map<std::string, int> result13;
115     what.let(_map13 = result13);
116     TYPEOF_TEST(pair13 >> *(+_s >> pair13));
117 
118     int result14 = 0;
119     std::map<std::string,int> map1a;
120     std::map<std::string,int> map2a;
121     std::map<std::string,int> map3a;
122     TYPEOF_TEST((a1=map1a)[ xp::ref(result14) += a1 ]
123         >> (a2=map2a)[ xp::ref(result) += a2 ]
124         >> (a3=map3a)[ xp::ref(result) += a3 ]
125         );
126         {
127     TYPEOF_TEST(icase(a1= map10) [ xp::ref(result) = a1 ]
128         >> repeat<3>( (' ' >> icase(a1= map10) [ xp::ref(result) += ',', xp::ref(result) += a1 ]) )
129         );
130     TYPEOF_TEST(*((a1= map1a) | (a1= map2a) | 'e') [ xp::ref(result) += (a1 | "9") ]);
131         }
132 #ifndef BOOST_XPRESSIVE_NO_WREGEX
133     City result17a, result17b;
134     std::map<std::wstring, City> map17;
135     TYPEOF_TEST((a1= map17)[ xp::ref(result17a) = a1 ] >> +_s
136         >> (a1= map17)[ xp::ref(result17b) = a1 ]);
137 #else
138     // This test is empty
139 #endif
140 
141 }
142 
three_or_six(xp::csub_match const & sub)143 bool three_or_six(xp::csub_match const &sub)
144 {
145     return sub.length() == 3 || sub.length() == 6;
146 }
147 
148 ///////////////////////////////////////////////////////////////////////////////
149 // test_assert
150 //  regular expressions from test_assert.cpp
test_assert()151 void test_assert()
152 {
153     using namespace boost::xpressive;
154     std::string result;
155     TYPEOF_TEST((bow >> +_w >> eow)[ check(&three_or_six) ]);
156     TYPEOF_TEST((bow >> +_w >> eow)[ check(length(_)==3 || length(_)==6) ]);
157     int const days_per_month[] =
158         {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 31, 31};
159     mark_tag month(1), day(2);
160     // Note: if you uncomment the lines below,
161     // the BOOST_TYPEOF_LIMIT_SIZE is exceeded
162     TYPEOF_TEST((
163         // Month must be between 1 and 12 inclusive
164         (month= _d >> !_d)     [ check(as<int>(_) >= 1
165                                     && as<int>(_) <= 12) ]
166         //>>  '/'
167         //    // Day must be between 1 and 31 inclusive
168         //>>  (day=   _d >> !_d)     [ check(as<int>(_) >= 1
169         //                                && as<int>(_) <= 31) ]
170         //>>  '/'
171         //    // Only consider years between 1970 and 2038
172         //>>  (_d >> _d >> _d >> _d) [ check(as<int>(_) >= 1970
173         //                                && as<int>(_) <= 2038) ]
174         )
175         // Ensure the month actually has that many days.
176         [ check( ref(days_per_month)[as<int>(month)-1] >= as<int>(day) ) ]);
177 }
178 
179