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