blob: de03fa6969cc11c3b0c0585be9c434860e797e45 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2007 Joel de Guzman
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)
==============================================================================*/
#if !defined(BOOST_SPIRIT_RULE_FEB_12_2007_1020AM)
#define BOOST_SPIRIT_RULE_FEB_12_2007_1020AM
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/qi/nonterminal/nonterminal.hpp>
#include <boost/spirit/home/qi/nonterminal/grammar_fwd.hpp>
#include <boost/spirit/home/qi/nonterminal/detail/rule.hpp>
#include <boost/spirit/home/qi/nonterminal/detail/error_handler.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
#endif
namespace boost { namespace spirit { namespace qi
{
namespace detail { struct rule_decorator; }
template <
typename Iterator
, typename T0 = unused_type
, typename T1 = unused_type
, typename T2 = unused_type
>
struct rule
: make_nonterminal<rule<Iterator, T0, T1, T2>, T0, T1, T2>::type
{
typedef
make_nonterminal<rule<Iterator, T0, T1, T2>, T0, T1, T2>
make_nonterminal_;
typedef typename make_nonterminal_::skipper_type skipper_type;
typedef typename make_nonterminal_::type base_type;
typedef Iterator iterator_type;
typedef rule<Iterator, T0, T1, T2> self_type;
typedef
virtual_component_base<
Iterator
, typename base_type::context_type
, skipper_type
>
virtual_component;
typedef intrusive_ptr<virtual_component> pointer_type;
rule(std::string const& name_ = std::string())
: name_(name_) {}
~rule() {}
rule(rule const& rhs)
: ptr(rhs.ptr)
, name_(rhs.name_)
{
}
rule& operator=(rule const& rhs)
{
ptr = rhs.ptr;
name_ = rhs.name_;
return *this;
}
template <typename Expr>
rule& operator=(Expr const& xpr)
{
typedef spirit::traits::is_component<qi::domain, Expr> is_component;
// report invalid expression error as early as possible
// BOOST_MPL_ASSERT_MSG(
// is_component::value,
// xpr_is_not_convertible_to_a_parser, ());
// temp workaround for mpl problem
BOOST_STATIC_ASSERT(is_component::value);
define(xpr, mpl::false_());
return *this;
}
template <typename Expr>
friend rule& operator%=(rule& r, Expr const& xpr)
{
typedef spirit::traits::is_component<qi::domain, Expr> is_component;
// report invalid expression error as early as possible
//~ BOOST_MPL_ASSERT_MSG(
//~ is_component::value,
//~ xpr_is_not_convertible_to_a_parser, ());
// temp workaround for mpl problem
BOOST_STATIC_ASSERT(is_component::value);
r.define(xpr, mpl::true_());
return r;
}
self_type alias() const
{
self_type result;
result.define(*this, mpl::false_());
return result;
}
typename
make_nonterminal_holder<
nonterminal_object<self_type>
, self_type
>::type
copy() const
{
typename
make_nonterminal_holder<
nonterminal_object<self_type>
, self_type
>::type
result = {{*this}};
return result;
}
std::string const& name() const
{
return name_;
}
void name(std::string const& str)
{
name_ = str;
}
private:
template <typename Iterator_, typename T0_, typename T1_, typename T2_>
friend struct grammar;
friend struct detail::rule_decorator;
template <typename Expr, typename Auto>
void define(Expr const& xpr, Auto)
{
typedef typename
result_of::as_component<qi::domain, Expr>::type
component;
typedef
detail::virtual_component<
Iterator
, component
, typename base_type::context_type
, skipper_type
, Auto
>
virtual_component;
ptr = new virtual_component(spirit::as_component(qi::domain(), xpr));
}
template <typename Iterator_, typename Context, typename Skipper>
bool parse(
Iterator_& first, Iterator_ const& last
, Context& context, Skipper const& skipper) const
{
// If the following line produces a compilation error stating the
// 4th parameter is not convertible to the expected type, then you
// are probably trying to use this rule instance with a skipper
// which is not compatible with the skipper type used while
// defining the type of this rule instance.
return ptr->parse(first, last, context, skipper);
}
std::string what() const
{
if (name_.empty())
{
if (ptr)
{
return "unnamed-rule";
}
else
{
return "empty-rule";
}
}
else
{
return name_;
}
}
friend struct nonterminal_director;
pointer_type ptr;
std::string name_;
};
// Decoration support: create a new virtual component and link it as
// first element in the chain of virtual components associated with this
// rule. Returns the previous topmost virtual component in the chain.
// We provide support from 1 to 5 arguments.
namespace detail
{
struct rule_decorator
{
template <typename Decorator, typename Rule, typename A1>
typename Rule::pointer_type
static call(Rule& r, A1 const& a1)
{
typename Rule::pointer_type old (r.ptr);
r.ptr.reset(new Decorator(r.ptr, a1));
return old;
}
template <typename Decorator, typename Rule, typename A1, typename A2>
typename Rule::pointer_type
static call(Rule& r, A1 const& a1, A2 const& a2)
{
typename Rule::pointer_type old (r.ptr);
r.ptr.reset(new Decorator(r.ptr, a1, a2));
return old;
}
template <typename Decorator, typename Rule
, typename A1, typename A2, typename A3
>
typename Rule::pointer_type
static call(Rule& r
, A1 const& a1, A2 const& a2, A3 const& a3)
{
typename Rule::pointer_type old (r.ptr);
r.ptr.reset(new Decorator(r.ptr, a1, a2, a3));
return old;
}
template <typename Decorator, typename Rule
, typename A1, typename A2, typename A3, typename A4
>
typename Rule::pointer_type
static call(Rule& r
, A1 const& a1, A2 const& a2
, A3 const& a3, A4 const& a4)
{
typename Rule::pointer_type old (r.ptr);
r.ptr.reset(new Decorator(r.ptr, a1, a2, a3, a4));
return old;
}
template <typename Decorator, typename Rule
, typename A1, typename A2, typename A3, typename A4, typename A5
>
typename Rule::pointer_type
static call(Rule& r
, A1 const& a1, A2 const& a2
, A3 const& a3, A4 const& a4, A5 const& a5)
{
typename Rule::pointer_type old (r.ptr);
r.ptr.reset(new Decorator(r.ptr, a1, a2, a3, a4, a5));
return old;
}
};
}
template <typename Decorator
, typename Iterator, typename T0, typename T1, typename T2
, typename A1>
typename rule<Iterator, T0, T1, T2>::pointer_type
decorate(rule<Iterator, T0, T1, T2>& r
, A1 const& a1)
{
return detail::rule_decorator::
template call<Decorator>(r, a1);
}
template <typename Decorator
, typename Iterator, typename T0, typename T1, typename T2
, typename A1, typename A2
>
typename rule<Iterator, T0, T1, T2>::pointer_type
decorate(rule<Iterator, T0, T1, T2>& r
, A1 const& a1, A2 const& a2)
{
return detail::rule_decorator::
template call<Decorator>(r, a1, a2);
}
template <typename Decorator
, typename Iterator, typename T0, typename T1, typename T2
, typename A1, typename A2, typename A3
>
typename rule<Iterator, T0, T1, T2>::pointer_type
decorate(rule<Iterator, T0, T1, T2>& r
, A1 const& a1, A2 const& a2, A3 const& a3)
{
return detail::rule_decorator::
template call<Decorator>(r, a1, a2, a3);
}
template <typename Decorator
, typename Iterator, typename T0, typename T1, typename T2
, typename A1, typename A2, typename A3, typename A4
>
typename rule<Iterator, T0, T1, T2>::pointer_type
decorate(rule<Iterator, T0, T1, T2>& r
, A1 const& a1, A2 const& a2
, A3 const& a3, A4 const& a4)
{
return detail::rule_decorator::
template call<Decorator>(r, a1, a2, a3, a4);
}
template <typename Decorator
, typename Iterator, typename T0, typename T1, typename T2
, typename A1, typename A2, typename A3, typename A4, typename A5
>
typename rule<Iterator, T0, T1, T2>::pointer_type
decorate(rule<Iterator, T0, T1, T2>& r
, A1 const& a1, A2 const& a2
, A3 const& a3, A4 const& a4, A5 const& a5)
{
return detail::rule_decorator::
template call<Decorator>(r, a1, a2, a3, a4, a5);
}
// Error handling support
template <
error_handler_result action
, typename Iterator, typename T0, typename T1, typename T2
, typename F>
void on_error(rule<Iterator, T0, T1, T2>& r, F f)
{
typedef
rule<Iterator, T0, T1, T2>
rule_type;
typedef
detail::error_handler<
Iterator
, typename rule_type::base_type::context_type
, typename rule_type::skipper_type
, F
, action>
error_handler;
decorate<error_handler>(r, f);
}
// Error handling support when <action> is not
// specified. We will default to <fail>.
template <typename Iterator, typename T0, typename T1
, typename T2, typename F>
void on_error(rule<Iterator, T0, T1, T2>& r, F f)
{
on_error<fail>(r, f);
}
}}}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#endif