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