blob: f38366118681d4bca0bbe41240f264df2d94f4b0 [file] [log] [blame]
/*=============================================================================
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