1 /*============================================================================= 2 Copyright (c) 1998-2003 Joel de Guzman 3 Copyright (c) 2002-2003 Martin Wille 4 http://spirit.sourceforge.net/ 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 =============================================================================*/ 9 #ifndef BOOST_SPIRIT_EPSILON_HPP 10 #define BOOST_SPIRIT_EPSILON_HPP 11 12 //////////////////////////////////////////////////////////////////////////////// 13 #include <boost/spirit/home/classic/namespace.hpp> 14 #include <boost/spirit/home/classic/core/parser.hpp> 15 #include <boost/spirit/home/classic/meta/parser_traits.hpp> 16 #include <boost/spirit/home/classic/core/composite/composite.hpp> 17 #include <boost/spirit/home/classic/core/composite/no_actions.hpp> 18 19 #if defined(BOOST_MSVC) 20 # pragma warning(push) 21 # pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' 22 #endif 23 24 //////////////////////////////////////////////////////////////////////////////// 25 namespace boost { namespace spirit { 26 27 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 28 29 /////////////////////////////////////////////////////////////////////////////// 30 // 31 // condition_parser class 32 // 33 // handles expressions of the form 34 // 35 // epsilon_p(cond) 36 // 37 // where cond is a function or a functor that returns a value suitable 38 // to be used in boolean context. The expression returns a parser that 39 // returns an empty match when the condition evaluates to true. 40 // 41 /////////////////////////////////////////////////////////////////////////////// 42 template <typename CondT, bool positive_ = true> 43 struct condition_parser : parser<condition_parser<CondT, positive_> > 44 { 45 typedef condition_parser<CondT, positive_> self_t; 46 47 // not explicit! (needed for implementation of if_p et al.) condition_parserboost::spirit::condition_parser48 condition_parser(CondT const& cond_) : cond(cond_) {} 49 50 template <typename ScannerT> 51 typename parser_result<self_t, ScannerT>::type parseboost::spirit::condition_parser52 parse(ScannerT const& scan) const 53 { 54 if (positive_ == bool(cond())) // allow cond to return int 55 return scan.empty_match(); 56 else 57 return scan.no_match(); 58 } 59 60 condition_parser<CondT, !positive_> negateboost::spirit::condition_parser61 negate() const 62 { return condition_parser<CondT, !positive_>(cond); } 63 64 private: 65 66 CondT cond; 67 }; 68 69 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) || \ 70 BOOST_WORKAROUND(BOOST_MSVC, == 1400) || \ 71 BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) 72 // VC 7.1, VC8 and Sun CC <= 5.8 do not support general 73 // expressions of non-type template parameters in instantiations 74 template <typename CondT> 75 inline condition_parser<CondT, false> operator ~(condition_parser<CondT,true> const & p)76 operator~(condition_parser<CondT, true> const& p) 77 { return p.negate(); } 78 79 template <typename CondT> 80 inline condition_parser<CondT, true> operator ~(condition_parser<CondT,false> const & p)81 operator~(condition_parser<CondT, false> const& p) 82 { return p.negate(); } 83 #else // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400 84 template <typename CondT, bool positive> 85 inline condition_parser<CondT, !positive> operator ~(condition_parser<CondT,positive> const & p)86 operator~(condition_parser<CondT, positive> const& p) 87 { return p.negate(); } 88 #endif // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400 89 90 /////////////////////////////////////////////////////////////////////////////// 91 // 92 // empty_match_parser class 93 // 94 // handles expressions of the form 95 // epsilon_p(subject) 96 // where subject is a parser. The expression returns a composite 97 // parser that returns an empty match if the subject parser matches. 98 // 99 /////////////////////////////////////////////////////////////////////////////// 100 struct empty_match_parser_gen; 101 struct negated_empty_match_parser_gen; 102 103 template <typename SubjectT> 104 struct negated_empty_match_parser; // Forward declaration 105 106 template<typename SubjectT> 107 struct empty_match_parser 108 : unary<SubjectT, parser<empty_match_parser<SubjectT> > > 109 { 110 typedef empty_match_parser<SubjectT> self_t; 111 typedef unary<SubjectT, parser<self_t> > base_t; 112 typedef unary_parser_category parser_category_t; 113 typedef empty_match_parser_gen parser_genererator_t; 114 typedef self_t embed_t; 115 empty_match_parserboost::spirit::empty_match_parser116 explicit empty_match_parser(SubjectT const& p) : base_t(p) {} 117 118 template <typename ScannerT> 119 struct result 120 { typedef typename match_result<ScannerT, nil_t>::type type; }; 121 122 template <typename ScannerT> 123 typename parser_result<self_t, ScannerT>::type parseboost::spirit::empty_match_parser124 parse(ScannerT const& scan) const 125 { 126 typename ScannerT::iterator_t save(scan.first); 127 128 typedef typename no_actions_scanner<ScannerT>::policies_t 129 policies_t; 130 131 bool matches = this->subject().parse( 132 scan.change_policies(policies_t(scan))); 133 if (matches) 134 { 135 scan.first = save; // reset the position 136 return scan.empty_match(); 137 } 138 else 139 { 140 return scan.no_match(); 141 } 142 } 143 144 negated_empty_match_parser<SubjectT> negateboost::spirit::empty_match_parser145 negate() const 146 { return negated_empty_match_parser<SubjectT>(this->subject()); } 147 }; 148 149 template<typename SubjectT> 150 struct negated_empty_match_parser 151 : public unary<SubjectT, parser<negated_empty_match_parser<SubjectT> > > 152 { 153 typedef negated_empty_match_parser<SubjectT> self_t; 154 typedef unary<SubjectT, parser<self_t> > base_t; 155 typedef unary_parser_category parser_category_t; 156 typedef negated_empty_match_parser_gen parser_genererator_t; 157 negated_empty_match_parserboost::spirit::negated_empty_match_parser158 explicit negated_empty_match_parser(SubjectT const& p) : base_t(p) {} 159 160 template <typename ScannerT> 161 struct result 162 { typedef typename match_result<ScannerT, nil_t>::type type; }; 163 164 template <typename ScannerT> 165 typename parser_result<self_t, ScannerT>::type parseboost::spirit::negated_empty_match_parser166 parse(ScannerT const& scan) const 167 { 168 typename ScannerT::iterator_t save(scan.first); 169 170 typedef typename no_actions_scanner<ScannerT>::policies_t 171 policies_t; 172 173 bool matches = this->subject().parse( 174 scan.change_policies(policies_t(scan))); 175 if (!matches) 176 { 177 scan.first = save; // reset the position 178 return scan.empty_match(); 179 } 180 else 181 { 182 return scan.no_match(); 183 } 184 } 185 186 empty_match_parser<SubjectT> negateboost::spirit::negated_empty_match_parser187 negate() const 188 { return empty_match_parser<SubjectT>(this->subject()); } 189 }; 190 191 struct empty_match_parser_gen 192 { 193 template <typename SubjectT> 194 struct result 195 { typedef empty_match_parser<SubjectT> type; }; 196 197 template <typename SubjectT> 198 static empty_match_parser<SubjectT> generateboost::spirit::empty_match_parser_gen199 generate(parser<SubjectT> const& subject) 200 { return empty_match_parser<SubjectT>(subject.derived()); } 201 }; 202 203 struct negated_empty_match_parser_gen 204 { 205 template <typename SubjectT> 206 struct result 207 { typedef negated_empty_match_parser<SubjectT> type; }; 208 209 template <typename SubjectT> 210 static negated_empty_match_parser<SubjectT> generateboost::spirit::negated_empty_match_parser_gen211 generate(parser<SubjectT> const& subject) 212 { return negated_empty_match_parser<SubjectT>(subject.derived()); } 213 }; 214 215 ////////////////////////////// 216 template <typename SubjectT> 217 inline negated_empty_match_parser<SubjectT> operator ~(empty_match_parser<SubjectT> const & p)218 operator~(empty_match_parser<SubjectT> const& p) 219 { return p.negate(); } 220 221 template <typename SubjectT> 222 inline empty_match_parser<SubjectT> operator ~(negated_empty_match_parser<SubjectT> const & p)223 operator~(negated_empty_match_parser<SubjectT> const& p) 224 { return p.negate(); } 225 226 /////////////////////////////////////////////////////////////////////////////// 227 // 228 // epsilon_ parser and parser generator class 229 // 230 // Operates as primitive parser that always matches an empty sequence. 231 // 232 // Also operates as a parser generator. According to the type of the 233 // argument an instance of empty_match_parser<> (when the argument is 234 // a parser) or condition_parser<> (when the argument is not a parser) 235 // is returned by operator(). 236 // 237 /////////////////////////////////////////////////////////////////////////////// 238 namespace impl 239 { 240 template <typename SubjectT> 241 struct epsilon_selector 242 { 243 typedef typename as_parser<SubjectT>::type subject_t; 244 typedef typename 245 mpl::if_< 246 is_parser<subject_t> 247 ,empty_match_parser<subject_t> 248 ,condition_parser<subject_t> 249 >::type type; 250 }; 251 } 252 253 struct epsilon_parser : public parser<epsilon_parser> 254 { 255 typedef epsilon_parser self_t; 256 epsilon_parserboost::spirit::epsilon_parser257 epsilon_parser() {} 258 259 template <typename ScannerT> 260 typename parser_result<self_t, ScannerT>::type parseboost::spirit::epsilon_parser261 parse(ScannerT const& scan) const 262 { return scan.empty_match(); } 263 264 template <typename SubjectT> 265 typename impl::epsilon_selector<SubjectT>::type operator ()boost::spirit::epsilon_parser266 operator()(SubjectT const& subject) const 267 { 268 typedef typename impl::epsilon_selector<SubjectT>::type result_t; 269 return result_t(subject); 270 } 271 }; 272 273 epsilon_parser const epsilon_p = epsilon_parser(); 274 epsilon_parser const eps_p = epsilon_parser(); 275 276 /////////////////////////////////////////////////////////////////////////////// 277 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 278 279 }} // namespace BOOST_SPIRIT_CLASSIC_NS 280 281 #ifdef BOOST_MSVC 282 # pragma warning (pop) 283 #endif 284 285 #endif 286