os/ossrv/ossrv_pub/boost_apis/boost/spirit/dynamic/switch.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 #ifndef BOOST_SPIRIT_SWITCH_HPP
    10 #define BOOST_SPIRIT_SWITCH_HPP
    11 
    12 ///////////////////////////////////////////////////////////////////////////////
    13 //
    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
    17 //  different one.
    18 //
    19 ///////////////////////////////////////////////////////////////////////////////
    20 #if !defined(BOOST_SPIRIT_DEFAULTCASE_MAGIC)
    21 #define BOOST_SPIRIT_DEFAULTCASE_MAGIC 0x15F97A7
    22 #endif
    23 
    24 ///////////////////////////////////////////////////////////////////////////////
    25 //
    26 //  Spirit predefined maximum number of possible case_p/default_p case branch
    27 //  parsers.
    28 //
    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)
    33 
    34 ///////////////////////////////////////////////////////////////////////////////
    35 #include <boost/static_assert.hpp>
    36 
    37 ///////////////////////////////////////////////////////////////////////////////
    38 //
    39 // Ensure   BOOST_SPIRIT_SELECT_LIMIT > 0
    40 //
    41 ///////////////////////////////////////////////////////////////////////////////
    42 BOOST_STATIC_ASSERT(BOOST_SPIRIT_SWITCH_CASE_LIMIT > 0);
    43 
    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>
    49 
    50 ///////////////////////////////////////////////////////////////////////////////
    51 namespace boost { namespace spirit {
    52 
    53 ///////////////////////////////////////////////////////////////////////////////
    54 //
    55 //  The switch_parser allows to build switch like parsing constructs, which
    56 //  will have much better perfomance as comparable straight solutions.
    57 //
    58 //  Input stream driven syntax:
    59 //
    60 //      switch_p
    61 //      [
    62 //          case_p<'a'>
    63 //              (...parser to use, if the next character is 'a'...),
    64 //          case_p<'b'>
    65 //              (...parser to use, if the next character is 'b'...),
    66 //          default_p
    67 //              (...parser to use, if nothing was matched before...)
    68 //      ]
    69 //
    70 //  General syntax:
    71 //
    72 //      switch_p(...lazy expression returning the switch condition value...)
    73 //      [
    74 //          case_p<1>
    75 //              (...parser to use, if the switch condition value is 1...),
    76 //          case_p<2>
    77 //              (...parser to use, if the switch condition value is 2...),
    78 //          default_p
    79 //              (...parser to use, if nothing was matched before...)
    80 //      ]
    81 //
    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
    84 //  defined).
    85 //
    86 ///////////////////////////////////////////////////////////////////////////////
    87 template <typename CaseT, typename CondT = impl::get_next_token_cond>
    88 struct switch_parser
    89 :   public unary<CaseT, parser<switch_parser<CaseT, CondT> > >
    90 {
    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;
    94 
    95     switch_parser(CaseT const &case_)
    96     :   base_t(case_), cond(CondT())
    97     {}
    98 
    99     switch_parser(CaseT const &case_, CondT const &cond_)
   100     :   base_t(case_), cond(cond_)
   101     {}
   102 
   103     template <typename ScannerT>
   104     struct result
   105     {
   106         typedef typename match_result<ScannerT, nil_t>::type type;
   107     };
   108 
   109     template <typename ScannerT>
   110     typename parser_result<self_t, ScannerT>::type
   111     parse(ScannerT const& scan) const
   112     {
   113         return this->subject().parse(scan,
   114             impl::make_cond_functor<CondT>::do_(cond));
   115     }
   116 
   117     CondT cond;
   118 };
   119 
   120 ///////////////////////////////////////////////////////////////////////////////
   121 template <typename CondT>
   122 struct switch_cond_parser
   123 {
   124     switch_cond_parser(CondT const &cond_)
   125     :   cond(cond_)
   126     {}
   127 
   128     template <typename ParserT>
   129     switch_parser<ParserT, CondT>
   130     operator[](parser<ParserT> const &p) const
   131     {
   132         return switch_parser<ParserT, CondT>(p.derived(), cond);
   133     }
   134 
   135     CondT const &cond;
   136 };
   137 
   138 ///////////////////////////////////////////////////////////////////////////////
   139 template <int N, typename ParserT, bool IsDefault>
   140 struct case_parser
   141 :   public unary<ParserT, parser<case_parser<N, ParserT, IsDefault> > >
   142 {
   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;
   146 
   147     typedef typename base_t::subject_t          self_subject_t;
   148 
   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
   154     ));
   155 
   156     case_parser(parser<ParserT> const &p)
   157     :   base_t(p.derived())
   158     {}
   159 
   160     template <typename ScannerT>
   161     struct result
   162     {
   163         typedef typename match_result<ScannerT, nil_t>::type type;
   164     };
   165 
   166     template <typename ScannerT, typename CondT>
   167     typename parser_result<self_t, ScannerT>::type
   168     parse(ScannerT const& scan, CondT const &cond) const
   169     {
   170         typedef impl::default_case<self_t> default_t;
   171 
   172         if (!scan.at_end()) {
   173             typedef impl::default_delegate_parse<
   174                 value, is_default, default_t::value> default_parse_t;
   175 
   176             typename ScannerT::iterator_t const save(scan.first);
   177             return default_parse_t::parse(cond(scan), *this,
   178                 *this, scan, save);
   179         }
   180 
   181         return default_t::is_epsilon ? scan.empty_match() : scan.no_match();
   182     }
   183 
   184     template <int N1, typename ParserT1, bool IsDefault1>
   185     impl::compound_case_parser<
   186         self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
   187     >
   188     operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
   189     {
   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);
   193 
   194         typedef case_parser<N1, ParserT1, IsDefault1> right_t;
   195         return impl::compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
   196     }
   197 };
   198 
   199 ///////////////////////////////////////////////////////////////////////////////
   200 struct switch_parser_gen {
   201 
   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
   209     {
   210         return switch_cond_parser<CondT>(cond);
   211     }
   212 
   213 //  This generates a switch parser, which is driven by the next character/token
   214 //  found in the input stream.
   215     template <typename CaseT>
   216     switch_parser<CaseT>
   217     operator[](parser<CaseT> const &p) const
   218     {
   219         return switch_parser<CaseT>(p.derived());
   220     }
   221 };
   222 
   223 switch_parser_gen const switch_p = switch_parser_gen();
   224 
   225 ///////////////////////////////////////////////////////////////////////////////
   226 template <int N, typename ParserT>
   227 inline case_parser<N, ParserT, false>
   228 case_p(parser<ParserT> const &p)
   229 {
   230     return case_parser<N, ParserT, false>(p);
   231 }
   232 
   233 ///////////////////////////////////////////////////////////////////////////////
   234 struct default_parser_gen
   235 :   public case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
   236 {
   237     default_parser_gen()
   238     :   case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
   239             (epsilon_p)
   240     {}
   241 
   242     template <typename ParserT>
   243     case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>
   244     operator()(parser<ParserT> const &p) const
   245     {
   246         return case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>(p);
   247     }
   248 };
   249 
   250 default_parser_gen const default_p = default_parser_gen();
   251 
   252 ///////////////////////////////////////////////////////////////////////////////
   253 }}  // namespace boost::spirit
   254 
   255 #endif // BOOST_SPIRIT_SWITCH_HPP