370 lines
12 KiB
C++
Executable File
370 lines
12 KiB
C++
Executable File
/*=============================================================================
|
|
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
|