Chris@16: /*============================================================================= Chris@16: Copyright (c) 2002-2003 Joel de Guzman Chris@16: Copyright (c) 2002 Juan Carlos Arevalo-Baeza Chris@16: Copyright (c) 2002-2003 Martin Wille Chris@16: http://spirit.sourceforge.net/ Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: #ifndef BOOST_SPIRIT_IF_HPP Chris@16: #define BOOST_SPIRIT_IF_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit { Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN Chris@16: Chris@16: namespace impl { Chris@16: Chris@16: ////////////////////////////////// Chris@16: // if-else-parser, holds two alternative parsers and a conditional functor Chris@16: // that selects between them. Chris@16: template Chris@16: struct if_else_parser Chris@16: : public condition_evaluator::type> Chris@16: , public binary Chris@16: < Chris@16: typename as_parser::type, Chris@16: typename as_parser::type, Chris@16: parser< if_else_parser > Chris@16: > Chris@16: { Chris@16: typedef if_else_parser self_t; Chris@16: Chris@16: typedef as_parser as_parser_true_t; Chris@16: typedef as_parser as_parser_false_t; Chris@16: typedef typename as_parser_true_t::type parser_true_t; Chris@16: typedef typename as_parser_false_t::type parser_false_t; Chris@16: typedef as_parser cond_as_parser_t; Chris@16: typedef typename cond_as_parser_t::type condition_t; Chris@16: Chris@16: typedef binary > base_t; Chris@16: typedef condition_evaluator eval_t; Chris@16: Chris@16: if_else_parser Chris@16: ( Chris@16: ParsableTrueT const& p_true, Chris@16: ParsableFalseT const& p_false, Chris@16: CondT const& cond_ Chris@16: ) Chris@16: : eval_t(cond_as_parser_t::convert(cond_)) Chris@16: , base_t Chris@16: ( Chris@16: as_parser_true_t::convert(p_true), Chris@16: as_parser_false_t::convert(p_false) Chris@16: ) Chris@16: { } Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename match_result::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: typename parser_result::type Chris@16: parse(ScannerT const& scan) const Chris@16: { Chris@16: typedef typename parser_result Chris@16: ::type then_result_t; Chris@16: typedef typename parser_result Chris@16: ::type else_result_t; Chris@16: Chris@16: typename ScannerT::iterator_t const save(scan.first); Chris@16: Chris@16: std::ptrdiff_t length = this->evaluate(scan); Chris@16: if (length >= 0) Chris@16: { Chris@16: then_result_t then_result(this->left().parse(scan)); Chris@16: if (then_result) Chris@16: { Chris@16: length += then_result.length(); Chris@16: return scan.create_match(std::size_t(length), nil_t(), save, scan.first); Chris@16: } Chris@16: } Chris@16: else Chris@16: { Chris@16: else_result_t else_result(this->right().parse(scan)); Chris@16: if (else_result) Chris@16: { Chris@16: length = else_result.length(); Chris@16: return scan.create_match(std::size_t(length), nil_t(), save, scan.first); Chris@16: } Chris@16: } Chris@16: return scan.no_match(); Chris@16: } Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: // if-else-parser generator, takes the false-parser in brackets Chris@16: // and returns the if-else-parser. Chris@16: template Chris@16: struct if_else_parser_gen Chris@16: { Chris@16: if_else_parser_gen(ParsableTrueT const& p_true_, CondT const& cond_) Chris@16: : p_true(p_true_) Chris@16: , cond(cond_) {} Chris@16: Chris@16: template Chris@16: if_else_parser Chris@16: < Chris@16: ParsableTrueT, Chris@16: ParsableFalseT, Chris@16: CondT Chris@16: > Chris@16: operator[](ParsableFalseT const& p_false) const Chris@16: { Chris@16: return if_else_parser Chris@16: ( Chris@16: p_true, Chris@16: p_false, Chris@16: cond Chris@16: ); Chris@16: } Chris@16: Chris@16: ParsableTrueT const &p_true; Chris@16: CondT const &cond; Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: // if-parser, conditionally runs a parser is a functor condition is true. Chris@16: // If the condition is fales, it fails the parse. Chris@16: // It can optionally become an if-else-parser through the member else_p. Chris@16: template Chris@16: struct if_parser Chris@16: : public condition_evaluator::type> Chris@16: , public unary Chris@16: < Chris@16: typename as_parser::type, Chris@16: parser > > Chris@16: { Chris@16: typedef if_parser self_t; Chris@16: typedef as_parser as_parser_t; Chris@16: typedef typename as_parser_t::type parser_t; Chris@16: Chris@16: typedef as_parser cond_as_parser_t; Chris@16: typedef typename cond_as_parser_t::type condition_t; Chris@16: typedef condition_evaluator eval_t; Chris@16: typedef unary > base_t; Chris@16: Chris@16: if_parser(ParsableT const& p, CondT const& cond_) Chris@16: : eval_t(cond_as_parser_t::convert(cond_)) Chris@16: , base_t(as_parser_t::convert(p)) Chris@16: , else_p(p, cond_) Chris@16: {} Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename match_result::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: typename parser_result::type Chris@16: parse(ScannerT const& scan) const Chris@16: { Chris@16: typedef typename parser_result::type t_result_t; Chris@16: typename ScannerT::iterator_t const save(scan.first); Chris@16: Chris@16: std::ptrdiff_t length = this->evaluate(scan); Chris@16: if (length >= 0) Chris@16: { Chris@16: t_result_t then_result(this->subject().parse(scan)); Chris@16: if (then_result) Chris@16: { Chris@16: length += then_result.length(); Chris@16: return scan.create_match(std::size_t(length), nil_t(), save, scan.first); Chris@16: } Chris@16: return scan.no_match(); Chris@16: } Chris@16: return scan.empty_match(); Chris@16: } Chris@16: Chris@16: if_else_parser_gen else_p; Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: // if-parser generator, takes the true-parser in brackets and returns the Chris@16: // if-parser. Chris@16: template Chris@16: struct if_parser_gen Chris@16: { Chris@16: if_parser_gen(CondT const& cond_) : cond(cond_) {} Chris@16: Chris@16: template Chris@16: if_parser Chris@16: < Chris@16: ParsableT, Chris@16: CondT Chris@16: > Chris@16: operator[](ParsableT const& subject) const Chris@16: { Chris@16: return if_parser(subject, cond); Chris@16: } Chris@16: Chris@16: CondT const &cond; Chris@16: }; Chris@16: Chris@16: } // namespace impl Chris@16: Chris@16: ////////////////////////////////// Chris@16: // if_p function, returns "if" parser generator Chris@16: Chris@16: template Chris@16: impl::if_parser_gen Chris@16: if_p(CondT const& cond) Chris@16: { Chris@16: return impl::if_parser_gen(cond); Chris@16: } Chris@16: Chris@16: BOOST_SPIRIT_CLASSIC_NAMESPACE_END Chris@16: Chris@16: }} // namespace BOOST_SPIRIT_CLASSIC_NS Chris@16: Chris@16: #endif // BOOST_SPIRIT_IF_HPP