blob: a6738c71d99827cdb45582fc934cc3aea9527a5b [file] [log] [blame]
/*=============================================================================
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_FOR_HPP
#define BOOST_SPIRIT_FOR_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
{
template <typename FuncT>
struct for_functor
{
typedef typename boost::call_traits<FuncT>::param_type param_t;
for_functor(param_t f) : func(f) {}
for_functor() {}
FuncT func;
};
template <typename InitF>
struct for_init_functor : for_functor<InitF>
{
typedef for_functor<InitF> base_t;
typedef typename base_t::param_t param_t;
for_init_functor(param_t f) : base_t(f) {}
for_init_functor() : base_t() {}
void init() const { /*return*/ this->func(); }
};
template <typename StepF>
struct for_step_functor : for_functor<StepF>
{
typedef for_functor<StepF> base_t;
typedef typename base_t::param_t param_t;
for_step_functor(param_t f) : base_t(f) {}
for_step_functor() : base_t() {}
void step() const { /*return*/ this->func(); }
};
//////////////////////////////////
// for_parser
template
<
typename InitF, typename CondT, typename StepF,
typename ParsableT
>
struct for_parser
: private for_init_functor<InitF>
, private for_step_functor<StepF>
, private condition_evaluator<typename as_parser<CondT>::type>
, public unary
<
typename as_parser<ParsableT>::type,
parser< for_parser<InitF, CondT, StepF, ParsableT> >
>
{
typedef for_parser<InitF, CondT, StepF, ParsableT> self_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 as_parser<ParsableT> as_parser_t;
typedef typename as_parser_t::type parser_t;
typedef unary< parser_t, parser< self_t > > base_t;
//////////////////////////////
// constructor, saves init, condition and step functors
// for later use the parse member function
for_parser
(
InitF const &i, CondT const &c, StepF const &s,
ParsableT const &p
)
: for_init_functor<InitF>(i)
, for_step_functor<StepF>(s)
, eval_t(cond_as_parser_t::convert(c))
, base_t(as_parser_t::convert(p))
{ }
for_parser()
: for_init_functor<InitF>()
, for_step_functor<StepF>()
, eval_t()
, base_t()
{}
//////////////////////////////
// parse member function
template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const &scan) const
{
typedef typename parser_result<self_t, ScannerT>::type
result_t;
typedef typename parser_result<parser_t, ScannerT>::type
body_result_t;
typename ScannerT::iterator_t save(scan.first);
std::size_t length = 0;
int eval_length = 0;
this->init();
while ((eval_length = this->evaluate(scan))>=0)
{
length += eval_length;
body_result_t tmp(this->subject().parse(scan));
if (tmp)
{
length+=tmp.length();
}
else
{
return scan.no_match();
}
this->step();
}
BOOST_SPIRIT_CLASSIC_NS::nil_t attr;
return scan.create_match
(length, attr, save, scan.first);
}
};
//////////////////////////////////
// for_parser_gen generates takes the body parser in brackets
// and returns the for_parser
template <typename InitF, typename CondT, typename StepF>
struct for_parser_gen
{
for_parser_gen(InitF const &i, CondT const &c, StepF const &s)
: init(i)
, condition(c)
, step(s)
{}
template <typename ParsableT>
for_parser<InitF, CondT, StepF, ParsableT>
operator[](ParsableT const &p) const
{
return for_parser<InitF, CondT, StepF, ParsableT>
(init, condition, step, p);
}
InitF const &init;
CondT const &condition;
StepF const &step;
};
} // namespace impl
//////////////////////////////
// for_p, returns for-parser generator
// Usage: spirit::for_p(init-ftor, condition, step-ftor)[body]
template
<
typename InitF, typename ConditionT, typename StepF
>
impl::for_parser_gen<InitF, ConditionT, StepF>
for_p(InitF const &init_f, ConditionT const &condition, StepF const &step_f)
{
return impl::for_parser_gen<InitF, ConditionT, StepF>
(init_f, condition, step_f);
}
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace BOOST_SPIRIT_CLASSIC_NS
#endif // BOOST_SPIRIT_FOR_HPP