/*============================================================================= Copyright (c) 1998-2003 Joel de Guzman Copyright (c) 2002-2003 Martin Wille http://spirit.sourceforge.net/ Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef BOOST_SPIRIT_EPSILON_HPP #define BOOST_SPIRIT_EPSILON_HPP //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include //////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN /////////////////////////////////////////////////////////////////////////////// // // condition_parser class // // handles expresions of the form // // epsilon_p(cond) // // where cond is a function or a functor that returns a value suitable // to be used in boolean context. The expression returns a parser that // returns an empty match when the condition evaluates to true. // /////////////////////////////////////////////////////////////////////////////// template struct condition_parser : parser > { typedef condition_parser self_t; // not explicit! (needed for implementation of if_p et al.) condition_parser(CondT const& cond_) : cond(cond_) {} template typename parser_result::type parse(ScannerT const& scan) const { if (positive_ == bool(cond())) // allow cond to return int return scan.empty_match(); else return scan.no_match(); } condition_parser negate() const { return condition_parser(cond); } private: CondT cond; }; #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) || \ BOOST_WORKAROUND(BOOST_MSVC, == 1400) || \ BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) // VC 7.1, VC8 and Sun CC <= 5.8 do not support general // expressions of non-type template parameters in instantiations template inline condition_parser operator~(condition_parser const& p) { return p.negate(); } template inline condition_parser operator~(condition_parser const& p) { return p.negate(); } #else // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400 template inline condition_parser operator~(condition_parser const& p) { return p.negate(); } #endif // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400 /////////////////////////////////////////////////////////////////////////////// // // empty_match_parser class // // handles expressions of the form // epsilon_p(subject) // where subject is a parser. The expresion returns a composite // parser that returns an empty match if the subject parser matches. // /////////////////////////////////////////////////////////////////////////////// struct empty_match_parser_gen; struct negated_empty_match_parser_gen; template struct negated_empty_match_parser; // Forward declaration template struct empty_match_parser : unary > > { typedef empty_match_parser self_t; typedef unary > base_t; typedef unary_parser_category parser_category_t; typedef empty_match_parser_gen parser_genererator_t; typedef self_t embed_t; explicit empty_match_parser(SubjectT const& p) : base_t(p) {} template struct result { typedef typename match_result::type type; }; template typename parser_result::type parse(ScannerT const& scan) const { typename ScannerT::iterator_t save(scan.first); typedef typename no_actions_scanner::policies_t policies_t; bool matches = this->subject().parse( scan.change_policies(policies_t(scan))); if (matches) { scan.first = save; // reset the position return scan.empty_match(); } else { return scan.no_match(); } } negated_empty_match_parser negate() const { return negated_empty_match_parser(this->subject()); } }; template struct negated_empty_match_parser : public unary > > { typedef negated_empty_match_parser self_t; typedef unary > base_t; typedef unary_parser_category parser_category_t; typedef negated_empty_match_parser_gen parser_genererator_t; explicit negated_empty_match_parser(SubjectT const& p) : base_t(p) {} template struct result { typedef typename match_result::type type; }; template typename parser_result::type parse(ScannerT const& scan) const { typename ScannerT::iterator_t save(scan.first); typedef typename no_actions_scanner::policies_t policies_t; bool matches = this->subject().parse( scan.change_policies(policies_t(scan))); if (!matches) { scan.first = save; // reset the position return scan.empty_match(); } else { return scan.no_match(); } } empty_match_parser negate() const { return empty_match_parser(this->subject()); } }; struct empty_match_parser_gen { template struct result { typedef empty_match_parser type; }; template static empty_match_parser generate(parser const& subject) { return empty_match_parser(subject.derived()); } }; struct negated_empty_match_parser_gen { template struct result { typedef negated_empty_match_parser type; }; template static negated_empty_match_parser generate(parser const& subject) { return negated_empty_match_parser(subject.derived()); } }; ////////////////////////////// template inline negated_empty_match_parser operator~(empty_match_parser const& p) { return p.negate(); } template inline empty_match_parser operator~(negated_empty_match_parser const& p) { return p.negate(); } /////////////////////////////////////////////////////////////////////////////// // // epsilon_ parser and parser generator class // // Operates as primitive parser that always matches an empty sequence. // // Also operates as a parser generator. According to the type of the // argument an instance of empty_match_parser<> (when the argument is // a parser) or condition_parser<> (when the argument is not a parser) // is returned by operator(). // /////////////////////////////////////////////////////////////////////////////// namespace impl { template struct epsilon_selector { typedef typename as_parser::type subject_t; typedef typename mpl::if_< is_parser ,empty_match_parser ,condition_parser >::type type; }; } struct epsilon_parser : public parser { typedef epsilon_parser self_t; epsilon_parser() {} template typename parser_result::type parse(ScannerT const& scan) const { return scan.empty_match(); } template typename impl::epsilon_selector::type operator()(SubjectT const& subject) const { typedef typename impl::epsilon_selector::type result_t; return result_t(subject); } }; epsilon_parser const epsilon_p = epsilon_parser(); epsilon_parser const eps_p = epsilon_parser(); /////////////////////////////////////////////////////////////////////////////// BOOST_SPIRIT_CLASSIC_NAMESPACE_END }} // namespace BOOST_SPIRIT_CLASSIC_NS #endif