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