annotate DEPENDENCIES/generic/include/boost/spirit/home/classic/dynamic/switch.hpp @ 133:4acb5d8d80b6 tip

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