PageRenderTime 19ms CodeModel.GetById 1ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/classic/dynamic/switch.hpp

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