Update contrib.
1 /*=============================================================================
2 Copyright (c) 2003 Hartmut Kaiser
3 http://spirit.sourceforge.net/
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 #ifndef BOOST_SPIRIT_SWITCH_HPP
10 #define BOOST_SPIRIT_SWITCH_HPP
12 ///////////////////////////////////////////////////////////////////////////////
14 // The default_p parser generator template uses the following magic number
15 // as the corresponding case label value inside the generated switch()
16 // statements. If this number conflicts with your code, please pick a
19 ///////////////////////////////////////////////////////////////////////////////
20 #if !defined(BOOST_SPIRIT_DEFAULTCASE_MAGIC)
21 #define BOOST_SPIRIT_DEFAULTCASE_MAGIC 0x15F97A7
24 ///////////////////////////////////////////////////////////////////////////////
26 // Spirit predefined maximum number of possible case_p/default_p case branch
29 ///////////////////////////////////////////////////////////////////////////////
30 #if !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
31 #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 3
32 #endif // !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
34 ///////////////////////////////////////////////////////////////////////////////
35 #include <boost/static_assert.hpp>
37 ///////////////////////////////////////////////////////////////////////////////
39 // Ensure BOOST_SPIRIT_SELECT_LIMIT > 0
41 ///////////////////////////////////////////////////////////////////////////////
42 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SWITCH_CASE_LIMIT > 0);
44 #include <boost/spirit/core/config.hpp>
45 #include <boost/type_traits/is_same.hpp>
46 #include <boost/spirit/core/parser.hpp>
47 #include <boost/spirit/core/composite/epsilon.hpp>
48 #include <boost/spirit/dynamic/impl/switch.ipp>
50 ///////////////////////////////////////////////////////////////////////////////
51 namespace boost { namespace spirit {
53 ///////////////////////////////////////////////////////////////////////////////
55 // The switch_parser allows to build switch like parsing constructs, which
56 // will have much better perfomance as comparable straight solutions.
58 // Input stream driven syntax:
63 // (...parser to use, if the next character is 'a'...),
65 // (...parser to use, if the next character is 'b'...),
67 // (...parser to use, if nothing was matched before...)
72 // switch_p(...lazy expression returning the switch condition value...)
75 // (...parser to use, if the switch condition value is 1...),
77 // (...parser to use, if the switch condition value is 2...),
79 // (...parser to use, if nothing was matched before...)
82 // The maximum number of possible case_p branches is defined by the p constant
83 // BOOST_SPIRIT_SWITCH_CASE_LIMIT (this value defaults to 3 if not otherwise
86 ///////////////////////////////////////////////////////////////////////////////
87 template <typename CaseT, typename CondT = impl::get_next_token_cond>
89 : public unary<CaseT, parser<switch_parser<CaseT, CondT> > >
91 typedef switch_parser<CaseT, CondT> self_t;
92 typedef unary_parser_category parser_category_t;
93 typedef unary<CaseT, parser<self_t> > base_t;
95 switch_parser(CaseT const &case_)
96 : base_t(case_), cond(CondT())
99 switch_parser(CaseT const &case_, CondT const &cond_)
100 : base_t(case_), cond(cond_)
103 template <typename ScannerT>
106 typedef typename match_result<ScannerT, nil_t>::type type;
109 template <typename ScannerT>
110 typename parser_result<self_t, ScannerT>::type
111 parse(ScannerT const& scan) const
113 return this->subject().parse(scan,
114 impl::make_cond_functor<CondT>::do_(cond));
120 ///////////////////////////////////////////////////////////////////////////////
121 template <typename CondT>
122 struct switch_cond_parser
124 switch_cond_parser(CondT const &cond_)
128 template <typename ParserT>
129 switch_parser<ParserT, CondT>
130 operator[](parser<ParserT> const &p) const
132 return switch_parser<ParserT, CondT>(p.derived(), cond);
138 ///////////////////////////////////////////////////////////////////////////////
139 template <int N, typename ParserT, bool IsDefault>
141 : public unary<ParserT, parser<case_parser<N, ParserT, IsDefault> > >
143 typedef case_parser<N, ParserT, IsDefault> self_t;
144 typedef unary_parser_category parser_category_t;
145 typedef unary<ParserT, parser<self_t> > base_t;
147 typedef typename base_t::subject_t self_subject_t;
149 BOOST_STATIC_CONSTANT(int, value = N);
150 BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
151 BOOST_STATIC_CONSTANT(bool, is_simple = true);
152 BOOST_STATIC_CONSTANT(bool, is_epsilon = (
153 is_default && boost::is_same<self_subject_t, epsilon_parser>::value
156 case_parser(parser<ParserT> const &p)
157 : base_t(p.derived())
160 template <typename ScannerT>
163 typedef typename match_result<ScannerT, nil_t>::type type;
166 template <typename ScannerT, typename CondT>
167 typename parser_result<self_t, ScannerT>::type
168 parse(ScannerT const& scan, CondT const &cond) const
170 typedef impl::default_case<self_t> default_t;
172 if (!scan.at_end()) {
173 typedef impl::default_delegate_parse<
174 value, is_default, default_t::value> default_parse_t;
176 typename ScannerT::iterator_t const save(scan.first);
177 return default_parse_t::parse(cond(scan), *this,
181 return default_t::is_epsilon ? scan.empty_match() : scan.no_match();
184 template <int N1, typename ParserT1, bool IsDefault1>
185 impl::compound_case_parser<
186 self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
188 operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
190 // If the following compile time assertion fires, you've probably used
191 // more than one default_p case inside the switch_p parser construct.
192 BOOST_STATIC_ASSERT(!is_default || !IsDefault1);
194 typedef case_parser<N1, ParserT1, IsDefault1> right_t;
195 return impl::compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
199 ///////////////////////////////////////////////////////////////////////////////
200 struct switch_parser_gen {
202 // This generates a switch parser, which is driven by the condition value
203 // returned by the lazy parameter expression 'cond'. This may be a parser,
204 // which result is used or a phoenix actor, which will be dereferenced to
205 // obtain the switch condition value.
206 template <typename CondT>
207 switch_cond_parser<CondT>
208 operator()(CondT const &cond) const
210 return switch_cond_parser<CondT>(cond);
213 // This generates a switch parser, which is driven by the next character/token
214 // found in the input stream.
215 template <typename CaseT>
217 operator[](parser<CaseT> const &p) const
219 return switch_parser<CaseT>(p.derived());
223 switch_parser_gen const switch_p = switch_parser_gen();
225 ///////////////////////////////////////////////////////////////////////////////
226 template <int N, typename ParserT>
227 inline case_parser<N, ParserT, false>
228 case_p(parser<ParserT> const &p)
230 return case_parser<N, ParserT, false>(p);
233 ///////////////////////////////////////////////////////////////////////////////
234 struct default_parser_gen
235 : public case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
238 : case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
242 template <typename ParserT>
243 case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>
244 operator()(parser<ParserT> const &p) const
246 return case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>(p);
250 default_parser_gen const default_p = default_parser_gen();
252 ///////////////////////////////////////////////////////////////////////////////
253 }} // namespace boost::spirit
255 #endif // BOOST_SPIRIT_SWITCH_HPP