| /*============================================================================= |
| Copyright (c) 2002-2003 Joel de Guzman |
| Copyright (c) 2002 Juan Carlos Arevalo-Baeza |
| 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_IF_HPP |
| #define BOOST_SPIRIT_IF_HPP |
| |
| #include <boost/spirit/home/classic/namespace.hpp> |
| #include <boost/spirit/home/classic/core/parser.hpp> |
| #include <boost/spirit/home/classic/core/composite/composite.hpp> |
| #include <boost/spirit/home/classic/dynamic/impl/conditions.ipp> |
| |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| namespace impl { |
| |
| ////////////////////////////////// |
| // if-else-parser, holds two alternative parsers and a conditional functor |
| // that selects between them. |
| template <typename ParsableTrueT, typename ParsableFalseT, typename CondT> |
| struct if_else_parser |
| : public condition_evaluator<typename as_parser<CondT>::type> |
| , public binary |
| < |
| typename as_parser<ParsableTrueT>::type, |
| typename as_parser<ParsableFalseT>::type, |
| parser< if_else_parser<ParsableTrueT, ParsableFalseT, CondT> > |
| > |
| { |
| typedef if_else_parser<ParsableTrueT, ParsableFalseT, CondT> self_t; |
| |
| typedef as_parser<ParsableTrueT> as_parser_true_t; |
| typedef as_parser<ParsableFalseT> as_parser_false_t; |
| typedef typename as_parser_true_t::type parser_true_t; |
| typedef typename as_parser_false_t::type parser_false_t; |
| typedef as_parser<CondT> cond_as_parser_t; |
| typedef typename cond_as_parser_t::type condition_t; |
| |
| typedef binary<parser_true_t, parser_false_t, parser<self_t> > base_t; |
| typedef condition_evaluator<condition_t> eval_t; |
| |
| if_else_parser |
| ( |
| ParsableTrueT const& p_true, |
| ParsableFalseT const& p_false, |
| CondT const& cond_ |
| ) |
| : eval_t(cond_as_parser_t::convert(cond_)) |
| , base_t |
| ( |
| as_parser_true_t::convert(p_true), |
| as_parser_false_t::convert(p_false) |
| ) |
| { } |
| |
| template <typename ScannerT> |
| struct result |
| { |
| typedef typename match_result<ScannerT, nil_t>::type type; |
| }; |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| typedef typename parser_result |
| <parser_true_t, ScannerT>::type then_result_t; |
| typedef typename parser_result |
| <parser_false_t, ScannerT>::type else_result_t; |
| |
| typename ScannerT::iterator_t const save(scan.first); |
| |
| std::ptrdiff_t length = this->evaluate(scan); |
| if (length >= 0) |
| { |
| then_result_t then_result(this->left().parse(scan)); |
| if (then_result) |
| { |
| length += then_result.length(); |
| return scan.create_match(std::size_t(length), nil_t(), save, scan.first); |
| } |
| } |
| else |
| { |
| else_result_t else_result(this->right().parse(scan)); |
| if (else_result) |
| { |
| length = else_result.length(); |
| return scan.create_match(std::size_t(length), nil_t(), save, scan.first); |
| } |
| } |
| return scan.no_match(); |
| } |
| }; |
| |
| ////////////////////////////////// |
| // if-else-parser generator, takes the false-parser in brackets |
| // and returns the if-else-parser. |
| template <typename ParsableTrueT, typename CondT> |
| struct if_else_parser_gen |
| { |
| if_else_parser_gen(ParsableTrueT const& p_true_, CondT const& cond_) |
| : p_true(p_true_) |
| , cond(cond_) {} |
| |
| template <typename ParsableFalseT> |
| if_else_parser |
| < |
| ParsableTrueT, |
| ParsableFalseT, |
| CondT |
| > |
| operator[](ParsableFalseT const& p_false) const |
| { |
| return if_else_parser<ParsableTrueT, ParsableFalseT, CondT> |
| ( |
| p_true, |
| p_false, |
| cond |
| ); |
| } |
| |
| ParsableTrueT const &p_true; |
| CondT const &cond; |
| }; |
| |
| ////////////////////////////////// |
| // if-parser, conditionally runs a parser is a functor condition is true. |
| // If the condition is fales, it fails the parse. |
| // It can optionally become an if-else-parser through the member else_p. |
| template <typename ParsableT, typename CondT> |
| struct if_parser |
| : public condition_evaluator<typename as_parser<CondT>::type> |
| , public unary |
| < |
| typename as_parser<ParsableT>::type, |
| parser<if_parser<ParsableT, CondT> > > |
| { |
| typedef if_parser<ParsableT, CondT> self_t; |
| typedef as_parser<ParsableT> as_parser_t; |
| typedef typename as_parser_t::type parser_t; |
| |
| typedef as_parser<CondT> cond_as_parser_t; |
| typedef typename cond_as_parser_t::type condition_t; |
| typedef condition_evaluator<condition_t> eval_t; |
| typedef unary<parser_t, parser<self_t> > base_t; |
| |
| if_parser(ParsableT const& p, CondT const& cond_) |
| : eval_t(cond_as_parser_t::convert(cond_)) |
| , base_t(as_parser_t::convert(p)) |
| , else_p(p, cond_) |
| {} |
| |
| template <typename ScannerT> |
| struct result |
| { |
| typedef typename match_result<ScannerT, nil_t>::type type; |
| }; |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| typedef typename parser_result<parser_t, ScannerT>::type t_result_t; |
| typename ScannerT::iterator_t const save(scan.first); |
| |
| std::ptrdiff_t length = this->evaluate(scan); |
| if (length >= 0) |
| { |
| t_result_t then_result(this->subject().parse(scan)); |
| if (then_result) |
| { |
| length += then_result.length(); |
| return scan.create_match(std::size_t(length), nil_t(), save, scan.first); |
| } |
| return scan.no_match(); |
| } |
| return scan.empty_match(); |
| } |
| |
| if_else_parser_gen<ParsableT, CondT> else_p; |
| }; |
| |
| ////////////////////////////////// |
| // if-parser generator, takes the true-parser in brackets and returns the |
| // if-parser. |
| template <typename CondT> |
| struct if_parser_gen |
| { |
| if_parser_gen(CondT const& cond_) : cond(cond_) {} |
| |
| template <typename ParsableT> |
| if_parser |
| < |
| ParsableT, |
| CondT |
| > |
| operator[](ParsableT const& subject) const |
| { |
| return if_parser<ParsableT, CondT>(subject, cond); |
| } |
| |
| CondT const &cond; |
| }; |
| |
| } // namespace impl |
| |
| ////////////////////////////////// |
| // if_p function, returns "if" parser generator |
| |
| template <typename CondT> |
| impl::if_parser_gen<CondT> |
| if_p(CondT const& cond) |
| { |
| return impl::if_parser_gen<CondT>(cond); |
| } |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace BOOST_SPIRIT_CLASSIC_NS |
| |
| #endif // BOOST_SPIRIT_IF_HPP |