1 /*=============================================================================
2     Copyright (c) 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 #include <iostream>
10 #include <boost/detail/lightweight_test.hpp>
11 
12 
13 #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 6
14 #define BOOST_SPIRIT_SELECT_LIMIT 6
15 #define PHOENIX_LIMIT 6
16 
17 //#define BOOST_SPIRIT_DEBUG
18 #include <boost/mpl/list.hpp>
19 #include <boost/mpl/for_each.hpp>
20 
21 #include <boost/spirit/include/classic_primitives.hpp>
22 #include <boost/spirit/include/classic_numerics.hpp>
23 #include <boost/spirit/include/classic_actions.hpp>
24 #include <boost/spirit/include/classic_operators.hpp>
25 #include <boost/spirit/include/classic_rule.hpp>
26 #include <boost/spirit/include/classic_grammar.hpp>
27 #include <boost/spirit/include/classic_switch.hpp>
28 #include <boost/spirit/include/classic_select.hpp>
29 #include <boost/spirit/include/classic_closure.hpp>
30 
31 using namespace BOOST_SPIRIT_CLASSIC_NS;
32 
33 namespace test_grammars {
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 //  Test the direct switch_p usage
37     struct switch_grammar_direct : public grammar<switch_grammar_direct>
38     {
39         template <typename ScannerT>
40         struct definition
41         {
definitiontest_grammars::switch_grammar_direct::definition42             definition(switch_grammar_direct const& /*self*/)
43             {
44                 r = switch_p [
45                         case_p<'a'>(int_p),
46                         case_p<'b'>(ch_p(',')),
47                         case_p<'c'>(str_p("bcd")),
48                         case_p<'d'>(eps_p)
49                     ];
50             }
51 
52             rule<ScannerT> r;
starttest_grammars::switch_grammar_direct::definition53             rule<ScannerT> const& start() const { return r; }
54         };
55     };
56 
57 ///////////////////////////////////////////////////////////////////////////////
58 //  Test the switch_p usage given a parser as the switch condition
59     struct switch_grammar_parser : public grammar<switch_grammar_parser>
60     {
61         template <typename ScannerT>
62         struct definition
63         {
definitiontest_grammars::switch_grammar_parser::definition64             definition(switch_grammar_parser const& /*self*/)
65             {
66                 r = switch_p(anychar_p) [
67                         case_p<'a'>(int_p),
68                         case_p<'b'>(ch_p(',')),
69                         case_p<'c'>(str_p("bcd")),
70                         case_p<'d'>(eps_p)
71                     ];
72             }
73 
74             rule<ScannerT> r;
starttest_grammars::switch_grammar_parser::definition75             rule<ScannerT> const& start() const { return r; }
76         };
77     };
78 
79 ///////////////////////////////////////////////////////////////////////////////
80 //  Test the switch_p usage given an actor as the switch condition
81     struct select_result : public BOOST_SPIRIT_CLASSIC_NS::closure<select_result, int>
82     {
83         member1 val;
84     };
85 
86     struct switch_grammar_actor : public grammar<switch_grammar_actor>
87     {
88         template <typename ScannerT>
89         struct definition
90         {
definitiontest_grammars::switch_grammar_actor::definition91             definition(switch_grammar_actor const& /*self*/)
92             {
93                 using phoenix::arg1;
94                 r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >>
95                     switch_p(r.val) [
96                         case_p<0>(int_p),
97                         case_p<1>(ch_p(',')),
98                         case_p<2>(str_p("bcd")),
99                         case_p<3>(eps_p)
100                     ];
101             }
102 
103             rule<ScannerT, select_result::context_t> r;
104             rule<ScannerT, select_result::context_t> const&
starttest_grammars::switch_grammar_actor::definition105             start() const { return r; }
106         };
107     };
108 
109 }   // namespace test_grammars
110 
111 ///////////////////////////////////////////////////////////////////////////////
112 namespace tests {
113 
114     //  Tests for known (to the grammars) sequences
115     struct check_grammar_known {
116 
117         template <typename GrammarT>
operator ()tests::check_grammar_known118         void operator()(GrammarT)
119         {
120             GrammarT g;
121 
122             BOOST_TEST(parse("a1", g).full);
123             BOOST_TEST(!parse("a,", g).hit);
124             BOOST_TEST(!parse("abcd", g).hit);
125             BOOST_TEST(!parse("a", g).hit);
126 
127             BOOST_TEST(parse("a 1", g, space_p).full);
128             BOOST_TEST(!parse("a ,", g, space_p).hit);
129             BOOST_TEST(!parse("a bcd", g, space_p).hit);
130             BOOST_TEST(!parse("a ", g, space_p).hit);
131 
132             BOOST_TEST(!parse("b1", g).hit);
133             BOOST_TEST(parse("b,", g).full);
134             BOOST_TEST(!parse("bbcd", g).hit);
135             BOOST_TEST(!parse("b", g).hit);
136 
137             BOOST_TEST(!parse("b 1", g, space_p).hit);
138             BOOST_TEST(parse("b ,", g, space_p).full);
139             BOOST_TEST(!parse("b bcd", g, space_p).hit);
140             BOOST_TEST(!parse("b ", g, space_p).hit);
141 
142             BOOST_TEST(!parse("c1", g).hit);
143             BOOST_TEST(!parse("c,", g).hit);
144             BOOST_TEST(parse("cbcd", g).full);
145             BOOST_TEST(!parse("c", g).hit);
146 
147             BOOST_TEST(!parse("c 1", g, space_p).hit);
148             BOOST_TEST(!parse("c ,", g, space_p).hit);
149             BOOST_TEST(parse("c bcd", g, space_p).full);
150             BOOST_TEST(!parse("c ", g, space_p).hit);
151 
152             BOOST_TEST(parse("d1", g).hit);
153             BOOST_TEST(parse("d,", g).hit);
154             BOOST_TEST(parse("dbcd", g).hit);
155             BOOST_TEST(parse("d", g).full);
156 
157             BOOST_TEST(parse("d 1", g, space_p).hit);
158             BOOST_TEST(parse("d ,", g, space_p).hit);
159             BOOST_TEST(parse("d bcd", g, space_p).hit);
160             BOOST_TEST(parse(" d", g, space_p).full); // JDG 10-18-2005 removed trailing ' ' to
161                                                   // avoid post skip problems
162 
163             BOOST_TEST(parse(" a 1 b , c bcd d", *g, space_p).full);
164             // JDG 10-18-2005 removed trailing ' ' to avoid post skip problems
165         }
166     };
167 
168     // Tests for unknown (to the grammar) sequences
169     struct check_grammar_unknown_default {
170 
171         template <typename GrammarT>
operator ()tests::check_grammar_unknown_default172         void operator()(GrammarT)
173         {
174             GrammarT g;
175 
176             BOOST_TEST(!parse("x1", g).hit);
177             BOOST_TEST(!parse("x,", g).hit);
178             BOOST_TEST(!parse("xbcd", g).hit);
179 
180             BOOST_TEST(!parse("x 1", g, space_p).hit);
181             BOOST_TEST(!parse("x ,", g, space_p).hit);
182             BOOST_TEST(!parse("x bcd", g, space_p).hit);
183         }
184     };
185 
186 }   // namespace tests
187 
188 int
main()189 main()
190 {
191     //  Test switch_p without any default_p case branches
192     typedef boost::mpl::list<
193         test_grammars::switch_grammar_direct,
194         test_grammars::switch_grammar_parser,
195         test_grammars::switch_grammar_actor
196     > grammar_list_t;
197 
198     boost::mpl::for_each<grammar_list_t>(tests::check_grammar_known());
199     boost::mpl::for_each<grammar_list_t>(tests::check_grammar_unknown_default());
200 
201     return boost::report_errors();
202 }
203