blob: 0c41a10dd31db3d389287966ff27d8fe9ae5895e [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2007 Joel de Guzman
Copyright (c) 2001-2009 Hartmut Kaiser
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_BASIC_TRANSFORMS_JAN_14_2007_1222PM)
#define BOOST_SPIRIT_BASIC_TRANSFORMS_JAN_14_2007_1222PM
#include <boost/spirit/home/support/meta_grammar/grammar.hpp>
#include <boost/spirit/home/support/component.hpp>
#include <boost/spirit/home/support/modifier.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/transform.hpp>
#include <boost/fusion/include/cons.hpp>
#include <boost/fusion/include/list.hpp>
#include <boost/fusion/include/make_cons.hpp>
#include <boost/fusion/include/make_list.hpp>
#include <boost/mpl/apply.hpp>
namespace boost { namespace spirit { namespace meta_grammar
{
///////////////////////////////////////////////////////////////////////////
// Invoke the specified grammar in the "Proto v2" way, dropping top
// level const and reference on the three parameters
//template<typename Grammar, typename Expr, typename State, typename Data>
//typename Grammar::template impl<Expr, State, Data>::result_type
//invoke_grammar(Expr const &expr, State const &state, Data &data)
//{
// return typename Grammar::template impl<Expr, State, Data>()(expr, state, data);
//}
template<typename Grammar, typename Expr, typename State, typename Data>
struct invoke_grammar
: Grammar::template impl<Expr, State, Data>
{};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating empty component meta descriptions
// (proto expressions) usable for defining meta grammars. Additionally,
// this is used to make the corresponding spirit component.
//
// Grammar: the proto grammar to use as the base for this component
// meta description (i.e.: proto::terminal<Tag>)
// Domain: the domain this proto transform is defined for
// (i.e.: qi::domain)
// DirectorF: the director is the real component form the specified
// domain (i.e.: any_char)
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_empty : proto::transform<compose_empty<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename proto::result_of::child<Expr>::type arg_type;
typedef
traits::make_component<
Domain
, typename mpl::apply1<DirectorF, arg_type>::type
, fusion::nil
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param
, typename impl::state_param
, typename impl::data_param
) const
{
return make_component::call(fusion::nil());
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating single-element component meta
// descriptions (proto expressions) usable for defining meta grammars.
//
// Grammar: the proto grammar to use as the base for this component
// meta description (i.e.: proto::unary_expr<Tag, ...>)
// Domain: the domain this proto transform is defined for
// (i.e.: qi::domain)
// DirectorF: the director is the real component from the specified
// domain (i.e.: negated_char_parser<...>)
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_single : proto::transform<compose_single<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
proto::result_of::child<
typename Grammar::template impl<Expr, State, Data>::result_type
>::type
arg_type;
typedef
traits::make_component<
Domain
, typename mpl::apply1<DirectorF, arg_type>::type
, typename fusion::result_of::make_cons<arg_type>::type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return make_component::call(
fusion::make_cons(
proto::child(invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data))
)
);
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating double-element component meta
// descriptions (proto expressions) usable for defining meta grammars.
//
// Grammar: the proto grammar to use as the base for this component
// meta description (i.e.: proto::binary_expr<Tag, ...>)
// Domain: the domain this proto transform is defined for
// (for instance: qi::domain)
// DirectorF: the director is the real component form the specified
// domain (i.e.: difference)
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_double : proto::transform<compose_double<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
Grammar::template impl<Expr, State, Data>::result_type
trans;
typedef typename proto::result_of::left<trans>::type left_type;
typedef typename proto::result_of::right<trans>::type right_type;
typedef typename
fusion::result_of::make_list<left_type, right_type>::type
list_type;
typedef
traits::make_component<
Domain
, typename mpl::apply1<DirectorF, list_type>::type
, list_type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
return make_component::call(
fusion::make_list(proto::left(t), proto::right(t))
);
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating triple-element component meta
// descriptions (proto expressions) usable for defining meta grammars.
//
// Grammar: the proto grammar to use as the base for this component
// meta description (i.e.: proto::nary_expr<Tag,a,b,c>)
// Domain: the domain this proto transform is defined for
// (for instance: qi::domain)
// DirectorF: the director is the real component form the specified
// domain (i.e.: difference)
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_triple : proto::transform<compose_triple<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
Grammar::template impl<Expr, State, Data>::result_type
trans;
typedef typename proto::result_of::child_c<trans, 0>::type arg0_type;
typedef typename proto::result_of::child_c<trans, 1>::type arg1_type;
typedef typename proto::result_of::child_c<trans, 2>::type arg2_type;
typedef typename
fusion::result_of::make_list<arg0_type, arg1_type, arg2_type>::type
list_type;
typedef
traits::make_component<
Domain
, typename mpl::apply1<DirectorF, list_type>::type
, list_type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
return make_component::call(
fusion::make_list(proto::child_c<0>(t), proto::child_c<1>(t), proto::child_c<2>(t))
);
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating single-element component meta
// descriptions (proto expressions) usable for defining meta grammars
// Only the RHS is stored.
//
// Grammar: the proto grammar to use as the base for this component
// meta description (i.e.: proto::binary_expr<Tag, ...>)
// Domain: the domain this proto transform is defined for
// (for instance: qi::domain)
// DirectorF: the director is the real component form the specified
// domain (i.e.: difference)
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_right : proto::transform<compose_right<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
Grammar::template impl<Expr, State, Data>::result_type
trans;
typedef typename proto::result_of::right<trans>::type right_type;
typedef typename
fusion::result_of::make_list<right_type>::type
list_type;
typedef
traits::make_component<
Domain
, typename mpl::apply1<DirectorF, list_type>::type
, list_type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
return make_component::call(
fusion::make_list(proto::right(t))
);
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform that accepts a proto::if_ predicate and
// applies a supplied indirect transform if the predicate is true.
///////////////////////////////////////////////////////////////////////////
template <typename Pred, typename TransformF>
struct if_transform
: proto::when<proto::if_<Pred>, proto::lazy<TransformF> >
{
};
///////////////////////////////////////////////////////////////////////////
// A proto transform that composes components from a fusion::list
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename Director>
struct compose_list : proto::transform<compose_list<Grammar, Domain, Director> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef
traits::make_component<
Domain, Director
, typename Grammar::template impl<Expr, State, Data>::result_type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return make_component::call(invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data));
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform that composes a single-element component
// from a 1-arity proto function expression (e.g. f(x))
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename Director>
struct compose_function1 : proto::transform<compose_function1<Grammar, Domain, Director> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 1>::type
>::type
arg1;
typedef
traits::make_component<
Domain, Director
, typename fusion::result_of::make_cons<arg1>::type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return make_component::call(fusion::make_cons(proto::child(proto::child_c<1>(expr))));
}
};
};
// Same as compose_function1, except that DirectorF is a meta-function to
// be evaluated to get the director
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_function1_eval : proto::transform<compose_function1_eval<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 0>::type
>::type
function;
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 1>::type
>::type
arg1;
typedef
traits::make_component<
Domain
, typename mpl::apply2<DirectorF, function, arg1>::type
, typename fusion::result_of::make_cons<arg1>::type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return make_component::call(
fusion::make_cons(proto::child(proto::child_c<1>(expr))));
}
};
};
// Same as compose_function1, except that the generated component holds
// not only the function argument, but the function tag as well
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_function1_full : proto::transform<compose_function1_full<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 0>::type
>::type
function;
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 1>::type
>::type
arg1;
typedef
traits::make_component<
Domain
, typename mpl::apply2<DirectorF, function, arg1>::type
, typename fusion::result_of::make_list<function, arg1>::type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param
, typename impl::data_param
) const
{
return make_component::call(fusion::make_list(
proto::child(proto::child_c<0>(expr)),
proto::child(proto::child_c<1>(expr))
));
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform that composes a 2-element component
// from a 2-arity proto function expression (e.g. f(x, y))
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename Director>
struct compose_function2 : proto::transform<compose_function2<Grammar, Domain, Director> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 1>::type
>::type
arg1;
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 2>::type
>::type
arg2;
typedef
traits::make_component<
Domain, Director
, typename fusion::result_of::make_list<arg1, arg2>::type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param
, typename impl::data_param
) const
{
return make_component::call(fusion::make_list(
proto::child(proto::child_c<1>(expr))
, proto::child(proto::child_c<2>(expr))
));
}
};
};
// Same as compose_function2, except that DirectorF is a meta-function to
// be evaluated to get the director
template <typename Grammar, typename Domain, typename DirectorF>
struct compose_function2_eval : proto::transform<compose_function2_eval<Grammar, Domain, DirectorF> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 0>::type
>::type
function;
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 1>::type
>::type
arg1;
typedef typename
proto::result_of::child<
typename proto::result_of::child_c<Expr, 2>::type
>::type
arg2;
typedef
traits::make_component<
Domain
, typename mpl::apply2<DirectorF, function, arg1>::type
, typename fusion::result_of::make_list<arg1, arg2>::type
, Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param
, typename impl::data_param
) const
{
return make_component::call(fusion::make_list(
proto::child(proto::child_c<1>(expr))
, proto::child(proto::child_c<2>(expr))
));
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for directives. The directive (terminal) tag
// is pushed into the modifier state (the Data).
///////////////////////////////////////////////////////////////////////////
template <typename Grammar>
struct compose_deep_directive : proto::transform<compose_deep_directive<Grammar> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename
add_modifier<
Data
, typename proto::result_of::child<
typename proto::result_of::child_c<Expr, 0>::type
>::type
>::type
modifier_type;
typedef typename
Grammar::template impl<Expr, State, modifier_type>::result_type
result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param
) const
{
modifier_type modifier;
return invoke_grammar<Grammar, Expr, State, modifier_type>()(expr, state, modifier);
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating double-element component meta
// descriptions (proto expressions) usable for defining meta grammars.
// This can be used to handle constructs like:
//
// directive[p]
//
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename Director>
struct compose_subscript : proto::transform<compose_subscript<Grammar, Domain, Director> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
// apply all grammar transformations mandated for the whole
// expression
typedef typename
Grammar::template impl<Expr, State, Data>::result_type
trans;
// this calculates the type of the directive
typedef typename proto::result_of::child_c<trans, 0>::type directive;
// this calculates the type of the embedded expression
typedef typename proto::result_of::child_c<trans, 1>::type embedded;
// this is the type of the contained data
typedef fusion::list<embedded, directive> list_type;
typedef
traits::make_component<Domain, Director, list_type, Data>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
return make_component::call(
list_type(proto::child_c<1>(t), proto::child_c<0>(t)));
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating double-element component meta
// descriptions (proto expressions) usable for defining meta grammars.
// This can be used to handle constructs like:
//
// directive(a)[p]
//
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename Director>
struct compose_subscript_function1 : proto::transform<compose_subscript_function1<Grammar, Domain, Director> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
// apply all grammar transformations mandated for the whole
// expression
typedef typename
Grammar::template impl<Expr, State, Data>::result_type
trans;
// this calculates the type of the embedded expression
typedef typename proto::result_of::child_c<trans, 1>::type embedded;
// this calculates the type of the argument of the function
typedef typename
proto::result_of::child_c<
typename proto::result_of::child_c<trans, 0>::type, 1
>::type
arg1;
// this is the type of the contained data
typedef fusion::list<embedded, arg1> list_type;
typedef
traits::make_component<
Domain, Director,
list_type,
Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
return make_component::call(list_type(
proto::child_c<1>(t),
proto::child_c<1>(proto::child_c<0>(t))));
}
};
};
///////////////////////////////////////////////////////////////////////////
// A proto transform for creating triple-element component meta
// descriptions (proto expressions) usable for defining meta grammars.
// This can be used to handle constructs like:
//
// directive(a, b)[p]
//
///////////////////////////////////////////////////////////////////////////
template <typename Grammar, typename Domain, typename Director>
struct compose_subscript_function2 : proto::transform<compose_subscript_function2<Grammar, Domain, Director> >, Grammar
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
// apply all grammar transformations mandated for the whole
// expression
typedef typename
Grammar::template impl<Expr, State, Data>::result_type
trans;
// this calculates the types of the arguments of the function
typedef typename proto::result_of::child_c<trans, 0>::type arg0;
typedef typename proto::result_of::child_c<arg0, 1>::type arg1;
typedef typename proto::result_of::child_c<arg0, 2>::type arg2;
// this calculates the type of the embedded expression
typedef typename proto::result_of::child_c<trans, 1>::type embedded;
typedef fusion::list<embedded, arg1, arg2> list_type;
typedef
traits::make_component<
Domain, Director,
list_type,
Data
>
make_component;
typedef typename make_component::type result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
trans t = invoke_grammar<Grammar, Expr, State, Data>()(expr, state, data);
arg0 a0 = proto::child_c<0>(t);
return make_component::call(list_type(
proto::child_c<1>(t), proto::child_c<1>(a0),
proto::child_c<2>(a0)));
}
};
};
}}}
#endif