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