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.
sl@0
     1
/*=============================================================================
sl@0
     2
    Copyright (c) 2003 Hartmut Kaiser
sl@0
     3
    http://spirit.sourceforge.net/
sl@0
     4
sl@0
     5
    Use, modification and distribution is subject to the Boost Software
sl@0
     6
    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
sl@0
     7
    http://www.boost.org/LICENSE_1_0.txt)
sl@0
     8
=============================================================================*/
sl@0
     9
#ifndef BOOST_SPIRIT_SWITCH_HPP
sl@0
    10
#define BOOST_SPIRIT_SWITCH_HPP
sl@0
    11
sl@0
    12
///////////////////////////////////////////////////////////////////////////////
sl@0
    13
//
sl@0
    14
//  The default_p parser generator template uses the following magic number
sl@0
    15
//  as the corresponding case label value inside the generated switch()
sl@0
    16
//  statements. If this number conflicts with your code, please pick a
sl@0
    17
//  different one.
sl@0
    18
//
sl@0
    19
///////////////////////////////////////////////////////////////////////////////
sl@0
    20
#if !defined(BOOST_SPIRIT_DEFAULTCASE_MAGIC)
sl@0
    21
#define BOOST_SPIRIT_DEFAULTCASE_MAGIC 0x15F97A7
sl@0
    22
#endif
sl@0
    23
sl@0
    24
///////////////////////////////////////////////////////////////////////////////
sl@0
    25
//
sl@0
    26
//  Spirit predefined maximum number of possible case_p/default_p case branch
sl@0
    27
//  parsers.
sl@0
    28
//
sl@0
    29
///////////////////////////////////////////////////////////////////////////////
sl@0
    30
#if !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
sl@0
    31
#define BOOST_SPIRIT_SWITCH_CASE_LIMIT 3
sl@0
    32
#endif // !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
sl@0
    33
sl@0
    34
///////////////////////////////////////////////////////////////////////////////
sl@0
    35
#include <boost/static_assert.hpp>
sl@0
    36
sl@0
    37
///////////////////////////////////////////////////////////////////////////////
sl@0
    38
//
sl@0
    39
// Ensure   BOOST_SPIRIT_SELECT_LIMIT > 0
sl@0
    40
//
sl@0
    41
///////////////////////////////////////////////////////////////////////////////
sl@0
    42
BOOST_STATIC_ASSERT(BOOST_SPIRIT_SWITCH_CASE_LIMIT > 0);
sl@0
    43
sl@0
    44
#include <boost/spirit/core/config.hpp>
sl@0
    45
#include <boost/type_traits/is_same.hpp>
sl@0
    46
#include <boost/spirit/core/parser.hpp>
sl@0
    47
#include <boost/spirit/core/composite/epsilon.hpp>
sl@0
    48
#include <boost/spirit/dynamic/impl/switch.ipp>
sl@0
    49
sl@0
    50
///////////////////////////////////////////////////////////////////////////////
sl@0
    51
namespace boost { namespace spirit {
sl@0
    52
sl@0
    53
///////////////////////////////////////////////////////////////////////////////
sl@0
    54
//
sl@0
    55
//  The switch_parser allows to build switch like parsing constructs, which
sl@0
    56
//  will have much better perfomance as comparable straight solutions.
sl@0
    57
//
sl@0
    58
//  Input stream driven syntax:
sl@0
    59
//
sl@0
    60
//      switch_p
sl@0
    61
//      [
sl@0
    62
//          case_p<'a'>
sl@0
    63
//              (...parser to use, if the next character is 'a'...),
sl@0
    64
//          case_p<'b'>
sl@0
    65
//              (...parser to use, if the next character is 'b'...),
sl@0
    66
//          default_p
sl@0
    67
//              (...parser to use, if nothing was matched before...)
sl@0
    68
//      ]
sl@0
    69
//
sl@0
    70
//  General syntax:
sl@0
    71
//
sl@0
    72
//      switch_p(...lazy expression returning the switch condition value...)
sl@0
    73
//      [
sl@0
    74
//          case_p<1>
sl@0
    75
//              (...parser to use, if the switch condition value is 1...),
sl@0
    76
//          case_p<2>
sl@0
    77
//              (...parser to use, if the switch condition value is 2...),
sl@0
    78
//          default_p
sl@0
    79
//              (...parser to use, if nothing was matched before...)
sl@0
    80
//      ]
sl@0
    81
//
sl@0
    82
//  The maximum number of possible case_p branches is defined by the p constant
sl@0
    83
//  BOOST_SPIRIT_SWITCH_CASE_LIMIT (this value defaults to 3 if not otherwise
sl@0
    84
//  defined).
sl@0
    85
//
sl@0
    86
///////////////////////////////////////////////////////////////////////////////
sl@0
    87
template <typename CaseT, typename CondT = impl::get_next_token_cond>
sl@0
    88
struct switch_parser
sl@0
    89
:   public unary<CaseT, parser<switch_parser<CaseT, CondT> > >
sl@0
    90
{
sl@0
    91
    typedef switch_parser<CaseT, CondT>     self_t;
sl@0
    92
    typedef unary_parser_category           parser_category_t;
sl@0
    93
    typedef unary<CaseT, parser<self_t> >   base_t;
sl@0
    94
sl@0
    95
    switch_parser(CaseT const &case_)
sl@0
    96
    :   base_t(case_), cond(CondT())
sl@0
    97
    {}
sl@0
    98
sl@0
    99
    switch_parser(CaseT const &case_, CondT const &cond_)
sl@0
   100
    :   base_t(case_), cond(cond_)
sl@0
   101
    {}
sl@0
   102
sl@0
   103
    template <typename ScannerT>
sl@0
   104
    struct result
sl@0
   105
    {
sl@0
   106
        typedef typename match_result<ScannerT, nil_t>::type type;
sl@0
   107
    };
sl@0
   108
sl@0
   109
    template <typename ScannerT>
sl@0
   110
    typename parser_result<self_t, ScannerT>::type
sl@0
   111
    parse(ScannerT const& scan) const
sl@0
   112
    {
sl@0
   113
        return this->subject().parse(scan,
sl@0
   114
            impl::make_cond_functor<CondT>::do_(cond));
sl@0
   115
    }
sl@0
   116
sl@0
   117
    CondT cond;
sl@0
   118
};
sl@0
   119
sl@0
   120
///////////////////////////////////////////////////////////////////////////////
sl@0
   121
template <typename CondT>
sl@0
   122
struct switch_cond_parser
sl@0
   123
{
sl@0
   124
    switch_cond_parser(CondT const &cond_)
sl@0
   125
    :   cond(cond_)
sl@0
   126
    {}
sl@0
   127
sl@0
   128
    template <typename ParserT>
sl@0
   129
    switch_parser<ParserT, CondT>
sl@0
   130
    operator[](parser<ParserT> const &p) const
sl@0
   131
    {
sl@0
   132
        return switch_parser<ParserT, CondT>(p.derived(), cond);
sl@0
   133
    }
sl@0
   134
sl@0
   135
    CondT const &cond;
sl@0
   136
};
sl@0
   137
sl@0
   138
///////////////////////////////////////////////////////////////////////////////
sl@0
   139
template <int N, typename ParserT, bool IsDefault>
sl@0
   140
struct case_parser
sl@0
   141
:   public unary<ParserT, parser<case_parser<N, ParserT, IsDefault> > >
sl@0
   142
{
sl@0
   143
    typedef case_parser<N, ParserT, IsDefault> self_t;
sl@0
   144
    typedef unary_parser_category               parser_category_t;
sl@0
   145
    typedef unary<ParserT, parser<self_t> >     base_t;
sl@0
   146
sl@0
   147
    typedef typename base_t::subject_t          self_subject_t;
sl@0
   148
sl@0
   149
    BOOST_STATIC_CONSTANT(int, value = N);
sl@0
   150
    BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
sl@0
   151
    BOOST_STATIC_CONSTANT(bool, is_simple = true);
sl@0
   152
    BOOST_STATIC_CONSTANT(bool, is_epsilon = (
sl@0
   153
        is_default && boost::is_same<self_subject_t, epsilon_parser>::value
sl@0
   154
    ));
sl@0
   155
sl@0
   156
    case_parser(parser<ParserT> const &p)
sl@0
   157
    :   base_t(p.derived())
sl@0
   158
    {}
sl@0
   159
sl@0
   160
    template <typename ScannerT>
sl@0
   161
    struct result
sl@0
   162
    {
sl@0
   163
        typedef typename match_result<ScannerT, nil_t>::type type;
sl@0
   164
    };
sl@0
   165
sl@0
   166
    template <typename ScannerT, typename CondT>
sl@0
   167
    typename parser_result<self_t, ScannerT>::type
sl@0
   168
    parse(ScannerT const& scan, CondT const &cond) const
sl@0
   169
    {
sl@0
   170
        typedef impl::default_case<self_t> default_t;
sl@0
   171
sl@0
   172
        if (!scan.at_end()) {
sl@0
   173
            typedef impl::default_delegate_parse<
sl@0
   174
                value, is_default, default_t::value> default_parse_t;
sl@0
   175
sl@0
   176
            typename ScannerT::iterator_t const save(scan.first);
sl@0
   177
            return default_parse_t::parse(cond(scan), *this,
sl@0
   178
                *this, scan, save);
sl@0
   179
        }
sl@0
   180
sl@0
   181
        return default_t::is_epsilon ? scan.empty_match() : scan.no_match();
sl@0
   182
    }
sl@0
   183
sl@0
   184
    template <int N1, typename ParserT1, bool IsDefault1>
sl@0
   185
    impl::compound_case_parser<
sl@0
   186
        self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
sl@0
   187
    >
sl@0
   188
    operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
sl@0
   189
    {
sl@0
   190
        //  If the following compile time assertion fires, you've probably used
sl@0
   191
        //  more than one default_p case inside the switch_p parser construct.
sl@0
   192
        BOOST_STATIC_ASSERT(!is_default || !IsDefault1);
sl@0
   193
sl@0
   194
        typedef case_parser<N1, ParserT1, IsDefault1> right_t;
sl@0
   195
        return impl::compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
sl@0
   196
    }
sl@0
   197
};
sl@0
   198
sl@0
   199
///////////////////////////////////////////////////////////////////////////////
sl@0
   200
struct switch_parser_gen {
sl@0
   201
sl@0
   202
//  This generates a switch parser, which is driven by the condition value
sl@0
   203
//  returned by the lazy parameter expression 'cond'. This may be a parser,
sl@0
   204
//  which result is used or a phoenix actor, which will be dereferenced to
sl@0
   205
//  obtain the switch condition value.
sl@0
   206
    template <typename CondT>
sl@0
   207
    switch_cond_parser<CondT>
sl@0
   208
    operator()(CondT const &cond) const
sl@0
   209
    {
sl@0
   210
        return switch_cond_parser<CondT>(cond);
sl@0
   211
    }
sl@0
   212
sl@0
   213
//  This generates a switch parser, which is driven by the next character/token
sl@0
   214
//  found in the input stream.
sl@0
   215
    template <typename CaseT>
sl@0
   216
    switch_parser<CaseT>
sl@0
   217
    operator[](parser<CaseT> const &p) const
sl@0
   218
    {
sl@0
   219
        return switch_parser<CaseT>(p.derived());
sl@0
   220
    }
sl@0
   221
};
sl@0
   222
sl@0
   223
switch_parser_gen const switch_p = switch_parser_gen();
sl@0
   224
sl@0
   225
///////////////////////////////////////////////////////////////////////////////
sl@0
   226
template <int N, typename ParserT>
sl@0
   227
inline case_parser<N, ParserT, false>
sl@0
   228
case_p(parser<ParserT> const &p)
sl@0
   229
{
sl@0
   230
    return case_parser<N, ParserT, false>(p);
sl@0
   231
}
sl@0
   232
sl@0
   233
///////////////////////////////////////////////////////////////////////////////
sl@0
   234
struct default_parser_gen
sl@0
   235
:   public case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
sl@0
   236
{
sl@0
   237
    default_parser_gen()
sl@0
   238
    :   case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
sl@0
   239
            (epsilon_p)
sl@0
   240
    {}
sl@0
   241
sl@0
   242
    template <typename ParserT>
sl@0
   243
    case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>
sl@0
   244
    operator()(parser<ParserT> const &p) const
sl@0
   245
    {
sl@0
   246
        return case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>(p);
sl@0
   247
    }
sl@0
   248
};
sl@0
   249
sl@0
   250
default_parser_gen const default_p = default_parser_gen();
sl@0
   251
sl@0
   252
///////////////////////////////////////////////////////////////////////////////
sl@0
   253
}}  // namespace boost::spirit
sl@0
   254
sl@0
   255
#endif // BOOST_SPIRIT_SWITCH_HPP