1 /*=============================================================================
2 Copyright (c) 2002-2003 Hartmut Kaiser
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 ///////////////////////////////////////////////////////////////////////////////
10 // This example shows the usage of the refactoring parser family parsers
11 // See the "Refactoring Parsers" chapter in the User's Guide.
12
13 #include <iostream>
14 #include <string>
15
16 #include <boost/spirit/include/classic_core.hpp>
17 #include <boost/spirit/include/classic_refactoring.hpp>
18
19 ///////////////////////////////////////////////////////////////////////////////
20 // used namespaces
21 using namespace std;
22 using namespace BOOST_SPIRIT_CLASSIC_NS;
23
24 ///////////////////////////////////////////////////////////////////////////////
25 // actor, used by the refactor_action_p test
26 struct refactor_action_actor
27 {
refactor_action_actorrefactor_action_actor28 refactor_action_actor (std::string &str_) : str(str_) {}
29
30 template <typename IteratorT>
operator ()refactor_action_actor31 void operator() (IteratorT const &first, IteratorT const &last) const
32 {
33 str = std::string(first, last-first);
34 }
35
36 std::string &str;
37 };
38
39 ///////////////////////////////////////////////////////////////////////////////
40 // main entry point
main()41 int main()
42 {
43 parse_info<> result;
44 char const *test_string = "Some string followed by a newline\n";
45
46 ///////////////////////////////////////////////////////////////////////////////
47 //
48 // 1. Testing the refactor_unary_d parser
49 //
50 // The following test should successfully parse the test string, because the
51 //
52 // refactor_unary_d[
53 // *anychar_p - '\n'
54 // ]
55 //
56 // is refactored into
57 //
58 // *(anychar_p - '\n').
59 //
60 ///////////////////////////////////////////////////////////////////////////////
61
62 result = parse(test_string, refactor_unary_d[*anychar_p - '\n'] >> '\n');
63
64 if (result.full)
65 {
66 cout << "Successfully refactored an unary!" << endl;
67 }
68 else
69 {
70 cout << "Failed to refactor an unary!" << endl;
71 }
72
73 // Parsing the same test string without refactoring fails, because the
74 // *anychar_p eats up all the input up to the end of the input string.
75
76 result = parse(test_string, (*anychar_p - '\n') >> '\n');
77
78 if (result.full)
79 {
80 cout
81 << "Successfully parsed test string (should not happen)!"
82 << endl;
83 }
84 else
85 {
86 cout
87 << "Correctly failed parsing the test string (without refactoring)!"
88 << endl;
89 }
90 cout << endl;
91
92 ///////////////////////////////////////////////////////////////////////////////
93 //
94 // 2. Testing the refactor_action_d parser
95 //
96 // The following test should successfully parse the test string, because the
97 //
98 // refactor_action_d[
99 // (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$'
100 // ]
101 //
102 // is refactored into
103 //
104 // (*(anychar_p - '$') >> '$')[refactor_action_actor(str)].
105 //
106 ///////////////////////////////////////////////////////////////////////////////
107
108 std::string str;
109 char const *test_string2 = "Some test string ending with a $";
110
111 result =
112 parse(test_string2,
113 refactor_action_d[
114 (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$'
115 ]
116 );
117
118 if (result.full && str == std::string(test_string2))
119 {
120 cout << "Successfully refactored an action!" << endl;
121 cout << "Parsed: \"" << str << "\"" << endl;
122 }
123 else
124 {
125 cout << "Failed to refactor an action!" << endl;
126 }
127
128 // Parsing the same test string without refactoring fails, because the
129 // the attached actor gets called only for the first part of the string
130 // (without the '$')
131
132 result =
133 parse(test_string2,
134 (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$'
135 );
136
137 if (result.full && str == std::string(test_string2))
138 {
139 cout << "Successfully parsed test string!" << endl;
140 cout << "Parsed: \"" << str << "\"" << endl;
141 }
142 else
143 {
144 cout
145 << "Correctly failed parsing the test string (without refactoring)!"
146 << endl;
147 cout << "Parsed instead: \"" << str << "\"" << endl;
148 }
149 cout << endl;
150
151 ///////////////////////////////////////////////////////////////////////////////
152 //
153 // 3. Testing the refactor_action_d parser with an embedded (nested)
154 // refactor_unary_p parser
155 //
156 // The following test should successfully parse the test string, because the
157 //
158 // refactor_action_unary_d[
159 // ((*anychar_p)[refactor_action_actor(str)] - '$')
160 // ] >> '$'
161 //
162 // is refactored into
163 //
164 // (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$'.
165 //
166 ///////////////////////////////////////////////////////////////////////////////
167
168 const refactor_action_gen<refactor_unary_gen<> > refactor_action_unary_d =
169 refactor_action_gen<refactor_unary_gen<> >(refactor_unary_d);
170
171 result =
172 parse(test_string2,
173 refactor_action_unary_d[
174 ((*anychar_p)[refactor_action_actor(str)] - '$')
175 ] >> '$'
176 );
177
178 if (result.full)
179 {
180 cout
181 << "Successfully refactored an action attached to an unary!"
182 << endl;
183 cout << "Parsed: \"" << str << "\"" << endl;
184 }
185 else
186 {
187 cout << "Failed to refactor an action!" << endl;
188 }
189
190 // Parsing the same test string without refactoring fails, because the
191 // anychar_p eats up all the input up to the end of the string
192
193 result =
194 parse(test_string2,
195 ((*anychar_p)[refactor_action_actor(str)] - '$') >> '$'
196 );
197
198 if (result.full)
199 {
200 cout << "Successfully parsed test string!" << endl;
201 cout << "Parsed: \"" << str << "\"" << endl;
202 }
203 else
204 {
205 cout
206 << "Correctly failed parsing the test string (without refactoring)!"
207 << endl;
208 cout << "Parsed instead: \"" << str << "\"" << endl;
209 }
210 cout << endl;
211
212 return 0;
213 }
214
215