...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
When having more and more expressions, you start to realize that this is a very repetetive task. Phoenix provides boilerplate macros that make defining Phoenix Expressions as you have seen in the previous section look like a piece of cake.
BOOST_PHOENIX_DEFINE_EXPRESSION
is a macro that can be used to generate all the necessary boilerplate
to create Phoenix Expressions
BOOST_PHOENIX_DEFINE_EXPRESSION( (namespace_seq)(name) , (child_grammar0) (child_grammar1) ... )
The above macro generates the necessary code for an expression name
in namespace namespace_seq
.
The sequence of (child_grammarN)
declares how many children the expression
will have and what proto::grammar
they match.
The macro should be used at global scope. namespace_seq
shall be the sequence of namespaces under which the following symbols
will be defined:
namespace tag { struct name; } namespace expression { template <typename A0, typename A1 ... typename AN> struct name : boost::phoenix::expr< tag::name , A0 , A1 ... , AN > } namespace rule { struct name : boost::phoenix::expr< child_grammar0 , child_grammar1 ... , child_grammarN > {}; } namespace functional { struct make_name; // A polymorphic function object that can be called to create the expression node } namespace result_of { template <typename A0, typename A1 ... typename AN> struct make_name; // The result type of the expression node } // convenience polymorphic function to create an expression node template <typename A0, typename A1 ... typename AN> result_of::make_name<A0, A1 ... AN> make_name(A0 const & a0, A1 const & a1 ... AN const & an);
This macros also adds a specialization for meta_grammar::case_<tag::name>
to enable the rule for further use
in actions.
#include <boost/phoenix/core/expression.hpp>
The example from the previous section can be rewritten as:
BOOST_PHOENIX_DEFINE_EXPRESSION( (plus) , (meta_grammar) // Lhs (meta_grammar) // Rhs ) template <typename Lhs, typename Rhs> typename plus<Lhs, Rhs>::type plus(Lhs const & lhs, Rhs const & rhs) { return expression::plus<Lhs, Rhs>::make(lhs, rhs); }
BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG
is a macro that can be used to generate all the necessary boilerplate
to create Phoenix Expressions
BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( (namespace_seq)(name) , (child_grammar0) (child_grammar1) ... (child_grammarN) , N )
The above macro generates the necessary code for an expression name
in namespace namespace_seq
.
N
is the maximum number
of variable children. All but the last elements in the grammar sequence
are required children of the expression, and the last denotes a variable
number of children. The number of children an expression of this kind
can hold is therefor N-1
plus
the size of the sequence
The macro should be used at global scope. namespace_seq
shall be the sequence of namespaces under which the following symbols
will be defined:
namespace tag { struct name; } namespace expression { template <typename A0, typename A1 ... typename AN> struct name : boost::phoenix::expr< tag::name , A0 , A1 ... , AN > {}; } namespace rule { struct name : expression::name< child_grammar0 , child_grammar1 ... , proto::vararg<child_grammarN> > {}; } namespace functional { struct make_name; // A polymorphic function object that can be called to create the expression node } namespace result_of { template <typename A0, typename A1 ... typename AN> struct make_name; // The result type of the expression node } // convenience polymorphic function to create an expression node template <typename A0, typename A1 ... typename AN> result_of::make_name<A0, A1 ... AN> make_name(A0 const & a0, A1 const & a1 ... AN const & an);
This macros also adds a specialization for meta_grammar::case_<tag::name>
to enable the rule for further use
in actions.
#include <boost/phoenix/core/expression.hpp>
BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( (boost)(phoenix)(mem_fun_ptr) , (meta_grammar) // Pointer to Object (meta_grammar) // Member pointer (meta_grammar) // Variable number of arguments , BOOST_PHOENIX_LIMIT )
This defines the member function pointer operator expression as described in operators.
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT
is a macro that can be used to generate all the necessary boilerplate
to create Phoenix Expressions
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( actor , (namespace_seq)(name) , (child_grammar0) (child_grammar1) ... (child_grammarN) , N )
The above macro generates the necessary code for an expression name
in namespace namespace_seq
.
The sequence of (child_grammarN)
declares how many children the expression
will have and what proto::grammar
they match.
The macro should be used at global scope. namespace_seq
shall be the sequence of namespaces under which the following symbols
will be defined:
namespace tag { struct name; } namespace expression { template <typename A0, typename A1 ... typename AN> struct name : boost::phoenix::expr_ext< actor , tag::name , A0 , A1 ... , AN > } namespace rule { struct name : boost::phoenix::expr< child_grammar0 , child_grammar1 ... , child_grammarN > {}; } namespace functional { struct make_name; // A polymorphic function object that can be called to create the expression node } namespace result_of { template <typename A0, typename A1 ... typename AN> struct make_name; // The result type of the expression node } // convenience polymorphic function to create an expression node template <typename A0, typename A1 ... typename AN> result_of::make_name<A0, A1 ... AN> make_name(A0 const & a0, A1 const & a1 ... AN const & an);
This macros also adds a specialization for meta_grammar::case_<tag::name>
to enable the rule for further use
in actions.
#include <boost/phoenix/core/expression.hpp>
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( if_actor , (boost)(phoenix)(if_) , (meta_grammar) // Cond (meta_grammar) // Then )
This defines the if_ expression. The custom actor defines else_
as a member.
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG
is a macro that can be used to generate all the necessary boilerplate
to create Phoenix Expressions
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG( actor , (namespace_seq)(name) , (child_grammar0) (child_grammar1) ... (child_grammarN) , N )
The above macro generates the necessary code for an expression name
in namespace namespace_seq
.
N
is the maximum number
of variable children. All but the last elements in the grammar sequence
are required children of the expression, and the last denotes a variable
number of children. The number of children an expression of this kind
can hold is therefor N-1
plus
the size of the sequence
The macro should be used at global scope. namespace_seq
shall be the sequence of namespaces under which the following symbols
will be defined:
namespace tag { struct name; } namespace expression { template <typename A0, typename A1 ... typename AN> struct name : boost::phoenix::expr_ext< actor , tag::name , A0 , A1 ... , AN > {}; } namespace rule { struct name : expression::name< child_grammar0 , child_grammar1 ... , proto::vararg<child_grammarN> > {}; } namespace functional { struct make_name; // A polymorphic function object that can be called to create the expression node } namespace result_of { template <typename A0, typename A1 ... typename AN> struct make_name; // The result type of the expression node } // convenience polymorphic function to create an expression node template <typename A0, typename A1 ... typename AN> result_of::make_name<A0, A1 ... AN> make_name(A0 const & a0, A1 const & a1 ... AN const & an);
This macros also adds a specialization for meta_grammar::case_<tag::name>
to enable the rule for further use
in actions.
#include <boost/phoenix/core/expression.hpp>
TBD