Chris@16: /*============================================================================= Chris@16: Copyright (c) 2002-2003 Joel de Guzman 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_WHILE_HPP Chris@16: #define BOOST_SPIRIT_WHILE_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: 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: // while parser Chris@16: // object are created by while_parser_gen and do_parser_gen Chris@16: template Chris@16: struct while_parser Chris@16: : public condition_evaluator< typename as_parser::type > Chris@16: , public unary // the parent stores a copy of the body parser Chris@16: < Chris@16: typename as_parser::type, Chris@16: parser > Chris@16: > Chris@16: { Chris@16: typedef while_parser self_t; Chris@16: Chris@16: typedef as_parser as_parser_t; Chris@16: typedef typename as_parser_t::type parser_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 unary > base_t; Chris@16: typedef condition_evaluator eval_t; Chris@16: Chris@16: Chris@16: ////////////////////////////// Chris@16: // constructor, saves condition and body parser Chris@16: while_parser(ParsableT const &body, CondT const &cond) Chris@16: : eval_t(cond_as_parser_t::convert(cond)) Chris@16: , base_t(as_parser_t::convert(body)) Chris@16: {} Chris@16: Chris@16: ////////////////////////////// Chris@16: // result type computer. Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename match_result Chris@16: ::type type; Chris@16: }; Chris@16: Chris@16: ////////////////////////////// Chris@16: // parse member function 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 sresult_t; Chris@16: typedef typename ScannerT::iterator_t iterator_t; Chris@16: Chris@16: iterator_t save(scan.first); Chris@16: std::size_t length = 0; Chris@16: int eval_length = 0; Chris@16: Chris@16: bool dont_check_condition = is_do_parser; Chris@16: Chris@16: while (dont_check_condition || (eval_length=this->evaluate(scan))>=0) Chris@16: { Chris@16: dont_check_condition = false; Chris@16: length += eval_length; Chris@16: sresult_t tmp(this->subject().parse(scan)); Chris@16: if (tmp) Chris@16: { Chris@16: length+=tmp.length(); Chris@16: } Chris@16: else Chris@16: { Chris@16: return scan.no_match(); Chris@16: } Chris@16: } Chris@16: return scan.create_match(length, nil_t(), save, scan.first); Chris@16: } Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: // while-parser generator, takes the body-parser in brackets Chris@16: // and returns the actual while-parser. Chris@16: template Chris@16: struct while_parser_gen Chris@16: { Chris@16: ////////////////////////////// Chris@16: // constructor, saves the condition for use by operator[] Chris@16: while_parser_gen(CondT const& cond_) : cond(cond_) {} Chris@16: Chris@16: ////////////////////////////// Chris@16: // operator[] returns the actual while-parser object Chris@16: template Chris@16: while_parser Chris@16: operator[](ParsableT const &subject) const Chris@16: { Chris@16: return while_parser(subject, cond); Chris@16: } Chris@16: private: Chris@16: Chris@16: ////////////////////////////// Chris@16: // the condition is stored by reference here. Chris@16: // this should not cause any harm since object of type Chris@16: // while_parser_gen<> are only used as temporaries Chris@16: // the while-parser object constructed by the operator[] Chris@16: // stores a copy of the condition. Chris@16: CondT const &cond; Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: // do-while-parser generator, takes the condition as Chris@16: // parameter to while_p member function and returns the Chris@16: // actual do-while-parser. Chris@16: template Chris@16: struct do_while_parser_gen Chris@16: { Chris@16: ////////////////////////////// Chris@16: // constructor. saves the body parser for use by while_p. Chris@16: explicit do_while_parser_gen(ParsableT const &body_parser) Chris@16: : body(body_parser) Chris@16: {} Chris@16: Chris@16: ////////////////////////////// Chris@16: // while_p returns the actual while-parser object Chris@16: template Chris@16: while_parser Chris@16: while_p(CondT cond) const Chris@16: { Chris@16: return while_parser(body, cond); Chris@16: } Chris@16: private: Chris@16: Chris@16: ////////////////////////////// Chris@16: // the body is stored by reference here Chris@16: // this should not cause any harm since object of type Chris@16: // do_while_parser_gen<> are only used as temporaries Chris@16: // the while-parser object constructed by the while_p Chris@16: // member function stores a copy of the body parser. Chris@16: ParsableT const &body; Chris@16: }; Chris@16: Chris@16: struct do_parser_gen Chris@16: { Chris@16: inline do_parser_gen() {} Chris@16: Chris@16: template Chris@16: impl::do_while_parser_gen Chris@16: operator[](ParsableT const& body) const Chris@16: { Chris@16: return impl::do_while_parser_gen(body); Chris@16: } Chris@16: }; Chris@16: } // namespace impl Chris@16: Chris@16: ////////////////////////////////// Chris@16: // while_p function, while-parser generator Chris@16: // Usage: spirit::while_p(Condition)[Body] Chris@16: template Chris@16: impl::while_parser_gen Chris@16: while_p(CondT const& cond) Chris@16: { Chris@16: return impl::while_parser_gen(cond); Chris@16: } Chris@16: Chris@16: ////////////////////////////////// Chris@16: // do_p functor, do-while-parser generator Chris@16: // Usage: spirit::do_p[Body].while_p(Condition) Chris@16: impl::do_parser_gen const do_p = impl::do_parser_gen(); 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_WHILE_HPP