Definition of the
proto::when<>
and
proto::otherwise<>
transforms.
The type used to define the global proto::transforms
,
a key for use when creating and accessing a slot in a transform environment for
a set of external transforms.
The proto::transforms_type
type, along with the proto::transforms
global, are declared using the BOOST_PROTO_DEFINE_ENV_VAR()
macro.
env<transforms_type, see-below>
Value &
env<transforms_type, see-below>
Value const &
If Value
is a specialization boost::reference_wrapper<T>
,
this function returns env<transforms_type, T &>(value.get())
.
Else, if the type Value
is non-copyable (i.e., a function, an array, abstract, or an ostream),
this function returns env<transforms_type, Value cv &>(value)
,
where cv
is const
for the second overload, and empty
for the first.
Otherwise, this function returns env<transforms_type, Value>(value)
.
A key key for use when creating and accessing a slot in a transform environment for
a set of external transforms.
proto::transforms_type const
Grammar
A grammar element and a PrimitiveTransform that associates
a transform with the grammar.
Use proto::when<> to override a grammar's default
transform with a custom transform. It is for used when composing larger transforms by
associating smaller transforms with individual rules in your grammar, as in the following
transform which counts the number of terminals in an expression.
// Count the terminals in an expression tree.
// Must be invoked with initial state == mpl::int_<0>().
struct CountLeaves :
proto::or_<
proto::when<proto::terminal<proto::_>, mpl::next<proto::_state>()>,
proto::otherwise<proto::fold<proto::_, proto::_state, CountLeaves> >
>
{};
In proto::when<G, T>, when T
is a class type it is a PrimitiveTransform and the following equivalencies hold:
boost::result_of<proto::when<G,T>(E,S,V)>::type is the same as
boost::result_of<T(E,S,V)>::type.
proto::when<G,T>()(e,s,d) is the same as
T()(e,s,d).
PrimitiveTransform
typename Grammar::proto_grammar
Grammar
Fun *
proto::when< Grammar, Fun >
A specialization that treats function pointer Transforms as if they
were function type Transforms.
This specialization requires that Fun is actually a function type.
This specialization is required for nested transforms such as
proto::when<G, T0(T1(_))>. In C++, functions that are used
as parameters to other functions automatically decay to funtion pointer types. In other words, the
type T0(T1(_)) is indistinguishable from
T0(T1(*)(_)). This specialization is required to handle these
nested function pointer type transforms properly.
Grammar
R(A...)
proto::transform< when<Grammar, R(A...)> >
A grammar element and a Transform that associates a
transform with the grammar.
Use proto::when<> to override a grammar's default
transform with a custom transform. It is for use when composing larger transforms by associating
smaller transforms with individual rules in your grammar.
The when<G, R(A...)> form accepts either a
CallableTransform or an ObjectTransform as its
second parameter. proto::when<> uses
proto::is_callable<R>::value to
distinguish between the two, and uses
proto::call<> to evaluate
CallableTransforms and
proto::make<> to evaluate
ObjectTransforms.
proto::transform_impl< Expr, State, Data >
For exposition only
proto::call<R(A...)>
For exposition only
proto::make<R(A...)>
For exposition only
typename mpl::if_<proto::is_callable<R>,call_,make_>::type
typename boost::result_of<which(Expr, State, Data)>::type
result_type
typename impl::expr_param
The current expression
typename impl::state_param
The current state
typename impl::data_param
An arbitrary data
Evaluate R(A...) as a transform either with
proto::call<> or with
proto::make<> depending
on whether proto::is_callable<R>::value
is true or false.
proto::matches<Expr, Grammar>::value
is true.
which()(expr, state, data)
typename Grammar::proto_grammar
Grammar
R(A..., ...)
proto::transform< when<Grammar, R(A..., ...)> >
A grammar element and a Transform that associates a
transform with the grammar.
Use proto::when<> to override a grammar's default
transform with a custom transform. It is for use when composing larger transforms by associating
smaller transforms with individual rules in your grammar.
The when<G, R(A..., ...)> form accepts either a
CallableTransform or an ObjectTransform as its
second parameter. proto::when<> uses
proto::is_callable<R>::value to
distinguish between the two, and uses
proto::call<> to evaluate
CallableTransforms and
proto::make<> to evaluate
ObjectTransforms.
Note: In the specialization
when<G, R(A..., ...)>, the first ellipsis denotes a
C++11-style variadic template (which is emulated for C++98 compilers). The second ellipsis
is a C-style vararg.
proto::transform_impl< Expr, State, Data >
For exposition only
proto::call<R(A..., ...)>
For exposition only
proto::make<R(A..., ...)>
For exposition only
typename mpl::if_<proto::is_callable<R>,call_,make_>::type
typename boost::result_of<which(Expr, State, Data)>::type
result_type
typename impl::expr_param
The current expression
typename impl::state_param
The current state
typename impl::data_param
An arbitrary data
Evaluate R(A..., ...) as a transform either with
proto::call<> or with
proto::make<> depending
on whether proto::is_callable<R>::value
is true or false.
proto::matches<Expr, Grammar>::value
is true.
which()(expr, state, data)
typename Grammar::proto_grammar
Grammar
proto::external_transform
proto::transform< when<Grammar, proto::external_transform> >
A grammar element that associates an externally-specified transform with the grammar.
The transform is looked up in the Data parameter using the Grammar as a key.
Use proto::when<> to override a grammar's default
transform with a custom transform. It is for use when composing larger transforms by associating
smaller transforms with individual rules in your grammar.
The when<G, proto::external_transform>
indicates that the associated transform is not yet known. It should be looked up when the transform
is about to be applied. It is found by looking it up in the passed-in Data parameter, which
behaves like a compile-time map from grammar types to transform types. The map is indexed using
Grammar as a key. The associated value type is used as the transform
to apply. In this way, the same grammar can be used to define multiple evaluating strategies that
can be added post-hoc.
See proto::external_transforms for an example.
boost::remove_reference<
typename mpl::eval_if_c<
proto::result_of::has_env_var<Data, proto::transforms_type>::value,
proto::result_of::env_var<Data, proto::transforms_type>,
proto::result_of::env_var<Data, proto::data_type>
>::type
>::type
::template when< Grammar >
::template impl< Expr, State, Data >
The implementation of the impl
struct depends on whether the Data
parameter is a transform environment that contains a value corresponding to the
proto::transforms_type key. If so, that value is treated as a
map from rules to transforms. Otherwise, the Data
type itself is treated
as such a map.
typename Grammar::proto_grammar
proto::when< proto::_, Fun >
Syntactic sugar for proto::when< proto::_, Fun >,
for use in grammars to handle all the cases not yet handled.
Use proto::otherwise<T> in your grammars as a synonym for
proto::when< proto::_, Fun >
as in the following transform which counts the number of terminals in an expression.
// Count the terminals in an expression tree.
// Must be invoked with initial state == mpl::int_<0>().
struct CountLeaves :
proto::or_<
proto::when<proto::terminal<proto::_>, mpl::next<proto::_state>()>,
proto::otherwise<proto::fold<proto::_, proto::_state, CountLeaves> >
>
{};
A placeholder for use as the second parameter for proto::when
to indicate that the rule's transform is specified externally.
See proto::external_transforms for an example.
A map from grammars to transforms, used as a way to externally associate transforms.
For exposition only.
mpl::map< typename to_mpl_pair< When >::type... >
proto::otherwise< typename mpl::at< map_type, Grammar >::type >
It is sometimes desirable to define a grammar that can be customized with different sets of transforms.
To do that, where you would normally specify a transform within a grammar, you can instead put
proto::external_transform; for example:
proto::when< some_grammar, proto::external_transform >. Then, when
invoking the grammar, you can pass an approriately-defined instance of proto::external_transforms
as the Data parameter. When an expression matches some_grammar, Proto
will look up the approprite transform in the Data parameter using some_grammar
as a key.
struct int_terminal
: proto::terminal<int>
{};
struct char_terminal
: proto::terminal<char>
{};
struct my_grammar
: proto::or_<
// The next two grammar rules are customization points.
// The associated transforms are specified externally
// using external_transforms below.
proto::when< int_terminal, proto::external_transform >
, proto::when< char_terminal, proto::external_transform >
, proto::when<
proto::plus< my_grammar, my_grammar >
, proto::fold< proto::_, int(), my_grammar >
>
>
{};
// Here is where the transforms are associated with the
// grammar rules above.
struct my_transforms
: proto::external_transforms<
proto::when<int_terminal, print(proto::_value)>
, proto::when<char_terminal, print(proto::_value)>
>
{};
// ...
proto::literal<int> i(1);
proto::literal<char> c('a');
my_transforms trx;
// Evaluate "i+c" using my_grammar with the specified transforms:
my_grammar()(i + c, 0, trx);
// If you would also like to pass arbitrary data along with the
// transforms, you can use a transform environment, as so:
my_grammar()(i + c, 0, (proto::data = 42, proto::transforms = trx));