1 /*=============================================================================
2     Copyright (c) 2001-2003 Joel de Guzman
3     http://spirit.sourceforge.net/
4 
5     Use, modification and distribution is subject to the Boost Software
6     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #include <iostream>
10 #include <boost/detail/lightweight_test.hpp>
11 
12 
13 #include <boost/spirit/include/classic_core.hpp>
14 #include <boost/spirit/include/classic_closure.hpp>
15 #include <boost/spirit/include/classic_parametric.hpp>
16 #include <boost/spirit/include/phoenix1_binders.hpp>
17 using namespace BOOST_SPIRIT_CLASSIC_NS;
18 using namespace phoenix;
19 
20 ///////////////////////////////////////////////////////////////////////////////
21 //
22 //  Closure tests
23 //
24 ///////////////////////////////////////////////////////////////////////////////
25 struct my_closure1 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure1, double>
26 {
27     member1 val;
28 };
29 
30 struct my_closure2 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure2, char>
31 {
32     member1 ch;
33 };
34 
35 struct my_closure3 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure3, char>
36 {
37     member1 ch;
38 };
39 
40 struct X { int a; int b; };
41 
42 #if defined(BOOST_SPIRIT_DEBUG)
43 //  If debugging is switched on, all closure members should have a
44 //  corresponding output streaming operator
45 std::ostream &
operator <<(std::ostream & o,X const & x)46 operator<< (std::ostream& o, X const &x)
47 {
48     o << "X(" << x.a << ", " << x.b << ")";
49     return o;
50 }
51 #endif // defined(BOOST_SPIRIT_DEBUG)
52 
53 struct my_closure4 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure4, X>
54 {
55     member1 x;
56 };
57 
58 // MWCW8.3 needs the default constructor here or it won't compile.
59 // It should not be needed.
YY60 struct Y { Y() {} Y(int) {} };
61 
62 #if defined(BOOST_SPIRIT_DEBUG)
63 //  If debugging is switched on, all closure members should have a
64 //  corresponding output streaming operator
65 std::ostream &
operator <<(std::ostream & o,Y const & x)66 operator<< (std::ostream& o, Y const &x)
67 {
68     o << "Y";
69     return o;
70 }
71 #endif // defined(BOOST_SPIRIT_DEBUG)
72 
73 struct my_closure5 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure5, int, Y>
74 {
75     member1 y;
76 };
77 
78 struct my_closure6 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure6, int, int, int>
79 {
80     member1 x;
81     member2 y;
82     member3 z;
83 };
84 
85 void
closure_tests()86 closure_tests()
87 {
88     rule<phrase_scanner_t, my_closure1::context_t> num_list;
89     double n;
90 
91     num_list =
92     (
93         real_p[num_list.val = arg1] >>  *(',' >> real_p[num_list.val += arg1])
94     )
95     [var(n) = num_list.val];
96 
97     parse_info<char const*> pi;
98     pi = parse("123, 456, 789", num_list, space_p);
99     BOOST_TEST(pi.hit);
100     BOOST_TEST(pi.full);
101     BOOST_TEST(n == 123 + 456 + 789);
102 
103     rule<scanner<>, my_closure2::context_t> rev;
104     rev = anychar_p[rev.ch = arg1] >> !rev >> f_ch_p(rev.ch);
105 
106     pi = parse("xyzzyx", rev);
107     BOOST_TEST(pi.hit);
108     BOOST_TEST(pi.full);
109 
110     pi = parse("xyzczyx", rev);
111     BOOST_TEST(!pi.hit);
112 
113     subrule<0, my_closure3::context_t> rev2;
114     pi = parse("atoyyota",
115         rev2 = anychar_p[rev2.ch = arg1] >> !rev2 >> f_ch_p(rev2.ch)
116     );
117 
118     BOOST_TEST(pi.hit);
119     BOOST_TEST(pi.full);
120 
121     pi = parse("whatdahell",
122         rev2 = anychar_p[rev2.ch = arg1] >> !rev2 >> f_ch_p(rev2.ch)
123     );
124     BOOST_TEST(!pi.hit);
125 
126     rule<phrase_scanner_t, my_closure4::context_t> complex_p;
127     complex_p =
128             int_p[bind(&X::a)(complex_p.x) = arg1]
129         >>  ','
130         >>  int_p[bind(&X::b)(complex_p.x) = arg1]
131     ;
132 
133     X x;
134     pi = parse("123, 456", complex_p[var(x) = arg1], space_p);
135     BOOST_TEST(pi.hit);
136     BOOST_TEST(x.a == 123);
137     BOOST_TEST(x.b == 456);
138 
139     rule<scanner<>, my_closure5::context_t> init1; // compile check only
140     rule<> r1 = init1(3, 3); // member2 is constructed from int
141 
142     rule<scanner<>, my_closure6::context_t> init2; // compile check only
143     rule<> r2 = init2(3); // member2 and member3 are default constructed
144 }
145 
146 ///////////////////////////////////////////////////////////////////////////////
147 //
148 //  Main
149 //
150 ///////////////////////////////////////////////////////////////////////////////
151 int
main()152 main()
153 {
154     closure_tests();
155     return boost::report_errors();
156 }
157 
158