1 /*=============================================================================
2     Copyright (c) 1998-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 //#define BOOST_SPIRIT_DEBUG
14 #define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 3
15 
16 #include <boost/spirit/include/classic_core.hpp>
17 #include <boost/spirit/include/classic_stored_rule.hpp>
18 using namespace BOOST_SPIRIT_CLASSIC_NS;
19 
20 ///////////////////////////////////////////////////////////////////////////////
21 //
22 //  Rule tests
23 //
24 ///////////////////////////////////////////////////////////////////////////////
25 void
aliasing_tests()26 aliasing_tests()
27 {
28     rule<>  a = ch_p('a');
29     rule<>  b = ch_p('b');
30     rule<>  c = ch_p('c');
31 
32     std::cout << "sizeof(rule<>): " << sizeof(rule<>) << std::endl;
33 
34     BOOST_SPIRIT_DEBUG_RULE(a);
35     BOOST_SPIRIT_DEBUG_RULE(b);
36     BOOST_SPIRIT_DEBUG_RULE(c);
37 
38     rule<>  start;
39     BOOST_SPIRIT_DEBUG_RULE(start);
40 
41     rule<>  d;
42     d = start;  // aliasing
43 
44     parse_info<char const*> pi;
45 
46     start = *(a | b | c);
47     pi = parse("abcabcacb", d);
48     BOOST_TEST(pi.hit);
49     BOOST_TEST(pi.full);
50     BOOST_TEST(pi.length == 9);
51     BOOST_TEST(*pi.stop == 0);
52 
53     start   = (a | b) >> (start | b);
54     pi = parse("aaaabababaaabbb", d);
55     BOOST_TEST(pi.hit);
56     BOOST_TEST(pi.full);
57     BOOST_TEST(pi.length == 15);
58     BOOST_TEST(*pi.stop == 0);
59 }
60 
61 void
rule_template_param_tests()62 rule_template_param_tests()
63 {
64     // test that rules can be issued its template params in any order:
65 
66     rule<> rx1;
67     rule<scanner<> > rx2;
68     rule<scanner<>, parser_context<> > rx3;
69     rule<scanner<>, parser_context<>, parser_address_tag> rx4;
70 
71     rule<parser_context<> > rx5;
72     rule<parser_context<>, parser_address_tag> rx6;
73     rule<parser_context<>, parser_address_tag, scanner<> > rx7;
74 
75     rule<parser_address_tag> rx8;
76     rule<parser_address_tag, scanner<> > rx9;
77     rule<parser_address_tag, scanner<>, parser_context<> > rx10;
78 
79     rule<parser_address_tag, parser_context<> > rx11;
80     rule<parser_address_tag, parser_context<>, scanner<> > rx12;
81 
82     rule<parser_context<>, scanner<> > rx13;
83     rule<parser_context<>, scanner<>, parser_address_tag> rx14;
84 }
85 
86 struct my_grammar : public grammar<my_grammar>
87 {
88     template <typename ScannerT>
89     struct definition
90     {
definitionmy_grammar::definition91         definition(my_grammar const& /*self*/)
92         {
93             r = lower_p;
94             rr = +(lexeme_d[r] >> as_lower_d[r] >> r);
95         }
96 
97         typedef scanner_list<
98             ScannerT
99           , typename lexeme_scanner<ScannerT>::type
100           , typename as_lower_scanner<ScannerT>::type
101         > scanners;
102 
103         rule<scanners> r;
104         rule<ScannerT> rr;
startmy_grammar::definition105         rule<ScannerT> const& start() const { return rr; }
106     };
107 };
108 
109 void
rule_2_or_more_scanners_tests()110 rule_2_or_more_scanners_tests()
111 {
112     { // 2 scanners
113         typedef scanner_list<scanner<>, phrase_scanner_t> scanners;
114 
115         rule<scanners>  r = +anychar_p;
116         BOOST_TEST(parse("abcdefghijk", r).full);
117         BOOST_TEST(parse("a b c d e f g h i j k", r, space_p).full);
118     }
119 
120     { // 3 scanners
121         my_grammar g;
122         BOOST_TEST(parse("abcdef aBc d e f aBc d E f", g, space_p).full);
123     }
124 }
125 
126 void
rule_basic_tests()127 rule_basic_tests()
128 {
129     rule<>  a = ch_p('a');
130     rule<>  b = ch_p('b');
131     rule<>  c = ch_p('c');
132 
133     BOOST_SPIRIT_DEBUG_RULE(a);
134     BOOST_SPIRIT_DEBUG_RULE(b);
135     BOOST_SPIRIT_DEBUG_RULE(c);
136 
137     parse_info<char const*> pi;
138 
139     rule<>  start = *(a | b | c);
140 
141     BOOST_SPIRIT_DEBUG_RULE(start);
142 
143     pi = parse("abcabcacb", start);
144     BOOST_TEST(pi.hit);
145     BOOST_TEST(pi.full);
146     BOOST_TEST(pi.length == 9);
147     BOOST_TEST(*pi.stop == 0);
148 
149     start   = (a | b) >> (start | b);
150     pi = parse("aaaabababaaabbb", start);
151     BOOST_TEST(pi.hit);
152     BOOST_TEST(pi.full);
153     BOOST_TEST(pi.length == 15);
154     BOOST_TEST(*pi.stop == 0);
155 
156     pi = parse("aaaabababaaabba", start);
157     BOOST_TEST(pi.hit);
158     BOOST_TEST(!pi.full);
159     BOOST_TEST(pi.length == 14);
160 
161     rule<> r = anychar_p;
162     r.copy(); // copy test (compile only)
163 }
164 
165 void
stored_rule_basic_tests()166 stored_rule_basic_tests()
167 {
168     stored_rule<>  a = ch_p('a');
169     stored_rule<>  b = ch_p('b');
170     stored_rule<>  c = ch_p('c');
171 
172     BOOST_SPIRIT_DEBUG_RULE(a);
173     BOOST_SPIRIT_DEBUG_RULE(b);
174     BOOST_SPIRIT_DEBUG_RULE(c);
175 
176     parse_info<char const*> pi;
177 
178     stored_rule<>  start = *(a | b | c);
179 
180     BOOST_SPIRIT_DEBUG_RULE(start);
181 
182     pi = parse("abcabcacb", start);
183     BOOST_TEST(pi.hit);
184     BOOST_TEST(pi.full);
185     BOOST_TEST(pi.length == 9);
186     BOOST_TEST(*pi.stop == 0);
187 
188     start   = (a | b) >> (start | b);
189     pi = parse("aaaabababaaabbb", start);
190     BOOST_TEST(pi.hit);
191     BOOST_TEST(pi.full);
192     BOOST_TEST(pi.length == 15);
193     BOOST_TEST(*pi.stop == 0);
194 
195     pi = parse("aaaabababaaabba", start);
196     BOOST_TEST(pi.hit);
197     BOOST_TEST(!pi.full);
198     BOOST_TEST(pi.length == 14);
199 }
200 
201 void
stored_rule_dynamic_tests()202 stored_rule_dynamic_tests()
203 {
204     rule<>  a = ch_p('a');
205     rule<>  b = ch_p('b');
206     rule<>  c = ch_p('c');
207 
208     BOOST_SPIRIT_DEBUG_RULE(a);
209     BOOST_SPIRIT_DEBUG_RULE(b);
210     BOOST_SPIRIT_DEBUG_RULE(c);
211 
212     parse_info<char const*> pi;
213 
214     // The FF is the dynamic equivalent of start = *(a | b | c);
215     stored_rule<>  start = a;
216     start = start.copy() | b;
217     start = start.copy() | c;
218     start = *(start.copy());
219 
220     std::cout << "sizeof(stored_rule<>): " << sizeof(stored_rule<>) << std::endl;
221 
222     BOOST_SPIRIT_DEBUG_RULE(start);
223 
224     pi = parse("abcabcacb", start);
225     BOOST_TEST(pi.hit);
226     BOOST_TEST(pi.full);
227     BOOST_TEST(pi.length == 9);
228     BOOST_TEST(*pi.stop == 0);
229 
230     // The FF is the dynamic equivalent of start = (a | b) >> (start | b);
231     start = b;
232     start = a | start.copy();
233     start = start.copy() >> (start | b);
234 
235     pi = parse("aaaabababaaabbb", start);
236     BOOST_TEST(pi.hit);
237     BOOST_TEST(pi.full);
238     BOOST_TEST(pi.length == 15);
239     BOOST_TEST(*pi.stop == 0);
240 
241     pi = parse("aaaabababaaabba", start);
242     BOOST_TEST(pi.hit);
243     BOOST_TEST(!pi.full);
244     BOOST_TEST(pi.length == 14);
245 }
246 
247 ///////////////////////////////////////////////////////////////////////////////
248 //
249 //  Main
250 //
251 ///////////////////////////////////////////////////////////////////////////////
252 int
main()253 main()
254 {
255     rule_basic_tests();
256     aliasing_tests();
257     rule_template_param_tests();
258     rule_2_or_more_scanners_tests();
259     stored_rule_basic_tests();
260     stored_rule_dynamic_tests();
261 
262     return boost::report_errors();
263 }
264 
265