123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*=============================================================================
- Copyright (c) 2003 Hartmut Kaiser
- http://spirit.sourceforge.net/
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- =============================================================================*/
- #ifndef BOOST_SPIRIT_SWITCH_HPP
- #define BOOST_SPIRIT_SWITCH_HPP
- ///////////////////////////////////////////////////////////////////////////////
- //
- // The default_p parser generator template uses the following magic number
- // as the corresponding case label value inside the generated switch()
- // statements. If this number conflicts with your code, please pick a
- // different one.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #if !defined(BOOST_SPIRIT_DEFAULTCASE_MAGIC)
- #define BOOST_SPIRIT_DEFAULTCASE_MAGIC 0x15F97A7
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Spirit predefined maximum number of possible case_p/default_p case branch
- // parsers.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #if !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
- #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 3
- #endif // !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
- ///////////////////////////////////////////////////////////////////////////////
- #include <boost/static_assert.hpp>
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Ensure BOOST_SPIRIT_SELECT_LIMIT > 0
- //
- ///////////////////////////////////////////////////////////////////////////////
- BOOST_STATIC_ASSERT(BOOST_SPIRIT_SWITCH_CASE_LIMIT > 0);
- #include <boost/spirit/home/classic/namespace.hpp>
- #include <boost/spirit/home/classic/core/config.hpp>
- #include <boost/type_traits/is_same.hpp>
- #include <boost/spirit/home/classic/core/parser.hpp>
- #include <boost/spirit/home/classic/core/composite/epsilon.hpp>
- #include <boost/spirit/home/classic/dynamic/impl/switch.ipp>
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace spirit {
- BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
- ///////////////////////////////////////////////////////////////////////////////
- //
- // The switch_parser allows to build switch like parsing constructs, which
- // will have much better performance as comparable straight solutions.
- //
- // Input stream driven syntax:
- //
- // switch_p
- // [
- // case_p<'a'>
- // (...parser to use, if the next character is 'a'...),
- // case_p<'b'>
- // (...parser to use, if the next character is 'b'...),
- // default_p
- // (...parser to use, if nothing was matched before...)
- // ]
- //
- // General syntax:
- //
- // switch_p(...lazy expression returning the switch condition value...)
- // [
- // case_p<1>
- // (...parser to use, if the switch condition value is 1...),
- // case_p<2>
- // (...parser to use, if the switch condition value is 2...),
- // default_p
- // (...parser to use, if nothing was matched before...)
- // ]
- //
- // The maximum number of possible case_p branches is defined by the p constant
- // BOOST_SPIRIT_SWITCH_CASE_LIMIT (this value defaults to 3 if not otherwise
- // defined).
- //
- ///////////////////////////////////////////////////////////////////////////////
- template <typename CaseT, typename CondT = impl::get_next_token_cond>
- struct switch_parser
- : public unary<CaseT, parser<switch_parser<CaseT, CondT> > >
- {
- typedef switch_parser<CaseT, CondT> self_t;
- typedef unary_parser_category parser_category_t;
- typedef unary<CaseT, parser<self_t> > base_t;
- switch_parser(CaseT const &case_)
- : base_t(case_), cond(CondT())
- {}
- switch_parser(CaseT const &case_, CondT const &cond_)
- : base_t(case_), cond(cond_)
- {}
- template <typename ScannerT>
- struct result
- {
- typedef typename match_result<ScannerT, nil_t>::type type;
- };
- template <typename ScannerT>
- typename parser_result<self_t, ScannerT>::type
- parse(ScannerT const& scan) const
- {
- return this->subject().parse(scan,
- impl::make_cond_functor<CondT>::do_(cond));
- }
- CondT cond;
- };
- ///////////////////////////////////////////////////////////////////////////////
- template <typename CondT>
- struct switch_cond_parser
- {
- switch_cond_parser(CondT const &cond_)
- : cond(cond_)
- {}
- template <typename ParserT>
- switch_parser<ParserT, CondT>
- operator[](parser<ParserT> const &p) const
- {
- return switch_parser<ParserT, CondT>(p.derived(), cond);
- }
- CondT const &cond;
- };
- ///////////////////////////////////////////////////////////////////////////////
- template <int N, typename ParserT, bool IsDefault>
- struct case_parser
- : public unary<ParserT, parser<case_parser<N, ParserT, IsDefault> > >
- {
- typedef case_parser<N, ParserT, IsDefault> self_t;
- typedef unary_parser_category parser_category_t;
- typedef unary<ParserT, parser<self_t> > base_t;
- typedef typename base_t::subject_t self_subject_t;
- BOOST_STATIC_CONSTANT(int, value = N);
- BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
- BOOST_STATIC_CONSTANT(bool, is_simple = true);
- BOOST_STATIC_CONSTANT(bool, is_epsilon = (
- is_default && boost::is_same<self_subject_t, epsilon_parser>::value
- ));
- case_parser(parser<ParserT> const &p)
- : base_t(p.derived())
- {}
- template <typename ScannerT>
- struct result
- {
- typedef typename match_result<ScannerT, nil_t>::type type;
- };
- template <typename ScannerT, typename CondT>
- typename parser_result<self_t, ScannerT>::type
- parse(ScannerT const& scan, CondT const &cond) const
- {
- typedef impl::default_case<self_t> default_t;
- if (!scan.at_end()) {
- typedef impl::default_delegate_parse<
- value, is_default, default_t::value> default_parse_t;
- typename ScannerT::iterator_t const save(scan.first);
- return default_parse_t::parse(cond(scan), *this,
- *this, scan, save);
- }
- return default_t::is_epsilon ? scan.empty_match() : scan.no_match();
- }
- template <int N1, typename ParserT1, bool IsDefault1>
- impl::compound_case_parser<
- self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
- >
- operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
- {
- // If the following compile time assertion fires, you've probably used
- // more than one default_p case inside the switch_p parser construct.
- BOOST_STATIC_ASSERT(!is_default || !IsDefault1);
- typedef case_parser<N1, ParserT1, IsDefault1> right_t;
- return impl::compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- struct switch_parser_gen {
- // This generates a switch parser, which is driven by the condition value
- // returned by the lazy parameter expression 'cond'. This may be a parser,
- // which result is used or a phoenix actor, which will be dereferenced to
- // obtain the switch condition value.
- template <typename CondT>
- switch_cond_parser<CondT>
- operator()(CondT const &cond) const
- {
- return switch_cond_parser<CondT>(cond);
- }
- // This generates a switch parser, which is driven by the next character/token
- // found in the input stream.
- template <typename CaseT>
- switch_parser<CaseT>
- operator[](parser<CaseT> const &p) const
- {
- return switch_parser<CaseT>(p.derived());
- }
- };
- switch_parser_gen const switch_p = switch_parser_gen();
- ///////////////////////////////////////////////////////////////////////////////
- template <int N, typename ParserT>
- inline case_parser<N, ParserT, false>
- case_p(parser<ParserT> const &p)
- {
- return case_parser<N, ParserT, false>(p);
- }
- ///////////////////////////////////////////////////////////////////////////////
- struct default_parser_gen
- : public case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
- {
- default_parser_gen()
- : case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
- (epsilon_p)
- {}
- template <typename ParserT>
- case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>
- operator()(parser<ParserT> const &p) const
- {
- return case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>(p);
- }
- };
- default_parser_gen const default_p = default_parser_gen();
- ///////////////////////////////////////////////////////////////////////////////
- BOOST_SPIRIT_CLASSIC_NAMESPACE_END
- }} // namespace BOOST_SPIRIT_CLASSIC_NS
- #endif // BOOST_SPIRIT_SWITCH_HPP
|