Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:09:00

0001 /*=============================================================================
0002     Copyright (c) 2003 Hartmut Kaiser
0003     http://spirit.sourceforge.net/
0004 
0005   Distributed under the Boost Software License, Version 1.0. (See accompanying
0006   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 =============================================================================*/
0008 #ifndef BOOST_SPIRIT_SWITCH_HPP
0009 #define BOOST_SPIRIT_SWITCH_HPP
0010 
0011 ///////////////////////////////////////////////////////////////////////////////
0012 //
0013 //  The default_p parser generator template uses the following magic number
0014 //  as the corresponding case label value inside the generated switch()
0015 //  statements. If this number conflicts with your code, please pick a
0016 //  different one.
0017 //
0018 ///////////////////////////////////////////////////////////////////////////////
0019 #if !defined(BOOST_SPIRIT_DEFAULTCASE_MAGIC)
0020 #define BOOST_SPIRIT_DEFAULTCASE_MAGIC 0x15F97A7
0021 #endif
0022 
0023 ///////////////////////////////////////////////////////////////////////////////
0024 //
0025 //  Spirit predefined maximum number of possible case_p/default_p case branch
0026 //  parsers.
0027 //
0028 ///////////////////////////////////////////////////////////////////////////////
0029 #if !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
0030 #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 3
0031 #endif // !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
0032 
0033 ///////////////////////////////////////////////////////////////////////////////
0034 #include <boost/static_assert.hpp>
0035 
0036 ///////////////////////////////////////////////////////////////////////////////
0037 //
0038 // Ensure   BOOST_SPIRIT_SELECT_LIMIT > 0
0039 //
0040 ///////////////////////////////////////////////////////////////////////////////
0041 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SWITCH_CASE_LIMIT > 0);
0042 
0043 #include <boost/spirit/home/classic/namespace.hpp>
0044 #include <boost/spirit/home/classic/core/config.hpp>
0045 #include <boost/type_traits/is_same.hpp>
0046 #include <boost/spirit/home/classic/core/parser.hpp>
0047 #include <boost/spirit/home/classic/core/composite/epsilon.hpp>
0048 #include <boost/spirit/home/classic/dynamic/impl/switch.ipp>
0049 
0050 ///////////////////////////////////////////////////////////////////////////////
0051 namespace boost { namespace spirit {
0052 
0053 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0054 
0055 ///////////////////////////////////////////////////////////////////////////////
0056 //
0057 //  The switch_parser allows to build switch like parsing constructs, which
0058 //  will have much better performance as comparable straight solutions.
0059 //
0060 //  Input stream driven syntax:
0061 //
0062 //      switch_p
0063 //      [
0064 //          case_p<'a'>
0065 //              (...parser to use, if the next character is 'a'...),
0066 //          case_p<'b'>
0067 //              (...parser to use, if the next character is 'b'...),
0068 //          default_p
0069 //              (...parser to use, if nothing was matched before...)
0070 //      ]
0071 //
0072 //  General syntax:
0073 //
0074 //      switch_p(...lazy expression returning the switch condition value...)
0075 //      [
0076 //          case_p<1>
0077 //              (...parser to use, if the switch condition value is 1...),
0078 //          case_p<2>
0079 //              (...parser to use, if the switch condition value is 2...),
0080 //          default_p
0081 //              (...parser to use, if nothing was matched before...)
0082 //      ]
0083 //
0084 //  The maximum number of possible case_p branches is defined by the p constant
0085 //  BOOST_SPIRIT_SWITCH_CASE_LIMIT (this value defaults to 3 if not otherwise
0086 //  defined).
0087 //
0088 ///////////////////////////////////////////////////////////////////////////////
0089 template <typename CaseT, typename CondT = impl::get_next_token_cond>
0090 struct switch_parser
0091 :   public unary<CaseT, parser<switch_parser<CaseT, CondT> > >
0092 {
0093     typedef switch_parser<CaseT, CondT>     self_t;
0094     typedef unary_parser_category           parser_category_t;
0095     typedef unary<CaseT, parser<self_t> >   base_t;
0096 
0097     switch_parser(CaseT const &case_)
0098     :   base_t(case_), cond(CondT())
0099     {}
0100 
0101     switch_parser(CaseT const &case_, CondT const &cond_)
0102     :   base_t(case_), cond(cond_)
0103     {}
0104 
0105     template <typename ScannerT>
0106     struct result
0107     {
0108         typedef typename match_result<ScannerT, nil_t>::type type;
0109     };
0110 
0111     template <typename ScannerT>
0112     typename parser_result<self_t, ScannerT>::type
0113     parse(ScannerT const& scan) const
0114     {
0115         return this->subject().parse(scan,
0116             impl::make_cond_functor<CondT>::do_(cond));
0117     }
0118 
0119     CondT cond;
0120 };
0121 
0122 ///////////////////////////////////////////////////////////////////////////////
0123 template <typename CondT>
0124 struct switch_cond_parser
0125 {
0126     switch_cond_parser(CondT const &cond_)
0127     :   cond(cond_)
0128     {}
0129 
0130     template <typename ParserT>
0131     switch_parser<ParserT, CondT>
0132     operator[](parser<ParserT> const &p) const
0133     {
0134         return switch_parser<ParserT, CondT>(p.derived(), cond);
0135     }
0136 
0137     CondT const &cond;
0138 };
0139 
0140 ///////////////////////////////////////////////////////////////////////////////
0141 template <int N, typename ParserT, bool IsDefault>
0142 struct case_parser
0143 :   public unary<ParserT, parser<case_parser<N, ParserT, IsDefault> > >
0144 {
0145     typedef case_parser<N, ParserT, IsDefault> self_t;
0146     typedef unary_parser_category               parser_category_t;
0147     typedef unary<ParserT, parser<self_t> >     base_t;
0148 
0149     typedef typename base_t::subject_t          self_subject_t;
0150 
0151     BOOST_STATIC_CONSTANT(int, value = N);
0152     BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
0153     BOOST_STATIC_CONSTANT(bool, is_simple = true);
0154     BOOST_STATIC_CONSTANT(bool, is_epsilon = (
0155         is_default && boost::is_same<self_subject_t, epsilon_parser>::value
0156     ));
0157 
0158     case_parser(parser<ParserT> const &p)
0159     :   base_t(p.derived())
0160     {}
0161 
0162     template <typename ScannerT>
0163     struct result
0164     {
0165         typedef typename match_result<ScannerT, nil_t>::type type;
0166     };
0167 
0168     template <typename ScannerT, typename CondT>
0169     typename parser_result<self_t, ScannerT>::type
0170     parse(ScannerT const& scan, CondT const &cond) const
0171     {
0172         typedef impl::default_case<self_t> default_t;
0173 
0174         if (!scan.at_end()) {
0175             typedef impl::default_delegate_parse<
0176                 value, is_default, default_t::value> default_parse_t;
0177 
0178             typename ScannerT::iterator_t const save(scan.first);
0179             return default_parse_t::parse(cond(scan), *this,
0180                 *this, scan, save);
0181         }
0182 
0183         return default_t::is_epsilon ? scan.empty_match() : scan.no_match();
0184     }
0185 
0186     template <int N1, typename ParserT1, bool IsDefault1>
0187     impl::compound_case_parser<
0188         self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
0189     >
0190     operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
0191     {
0192         //  If the following compile time assertion fires, you've probably used
0193         //  more than one default_p case inside the switch_p parser construct.
0194         BOOST_STATIC_ASSERT(!is_default || !IsDefault1);
0195 
0196         typedef case_parser<N1, ParserT1, IsDefault1> right_t;
0197         return impl::compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
0198     }
0199 };
0200 
0201 ///////////////////////////////////////////////////////////////////////////////
0202 struct switch_parser_gen {
0203 
0204 //  This generates a switch parser, which is driven by the condition value
0205 //  returned by the lazy parameter expression 'cond'. This may be a parser,
0206 //  which result is used or a phoenix actor, which will be dereferenced to
0207 //  obtain the switch condition value.
0208     template <typename CondT>
0209     switch_cond_parser<CondT>
0210     operator()(CondT const &cond) const
0211     {
0212         return switch_cond_parser<CondT>(cond);
0213     }
0214 
0215 //  This generates a switch parser, which is driven by the next character/token
0216 //  found in the input stream.
0217     template <typename CaseT>
0218     switch_parser<CaseT>
0219     operator[](parser<CaseT> const &p) const
0220     {
0221         return switch_parser<CaseT>(p.derived());
0222     }
0223 };
0224 
0225 switch_parser_gen const switch_p = switch_parser_gen();
0226 
0227 ///////////////////////////////////////////////////////////////////////////////
0228 template <int N, typename ParserT>
0229 inline case_parser<N, ParserT, false>
0230 case_p(parser<ParserT> const &p)
0231 {
0232     return case_parser<N, ParserT, false>(p);
0233 }
0234 
0235 ///////////////////////////////////////////////////////////////////////////////
0236 struct default_parser_gen
0237 :   public case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
0238 {
0239     default_parser_gen()
0240     :   case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
0241             (epsilon_p)
0242     {}
0243 
0244     template <typename ParserT>
0245     case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>
0246     operator()(parser<ParserT> const &p) const
0247     {
0248         return case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>(p);
0249     }
0250 };
0251 
0252 default_parser_gen const default_p = default_parser_gen();
0253 
0254 ///////////////////////////////////////////////////////////////////////////////
0255 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0256 
0257 }}  // namespace BOOST_SPIRIT_CLASSIC_NS
0258 
0259 #endif // BOOST_SPIRIT_SWITCH_HPP