A few years ago, I asked how to define a grammar with
Proto to match something like this:
if_(expr) [
stmt,
stmt,
...
].else [
stmt,
stmt,
...
];
The answer was to do this:
struct Grammar;
struct ExpressionGrammar;
struct StatementGrammar;
struct Domain;
template<typename Expr>
struct Expression
: proto::extends {
typedef proto::extends
base_type;
Expression(Expr const & expr = Expr())
: base_type( expr )
{}
};
struct Domain
: proto::domain< proto::generator< Expression >, Grammar>
{};
struct If {};
BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE(
1
, if_
, Domain
, (If)
, BOOST_PP_SEQ_NIL
);
// Here is the grammar for if_ statements
// matches if_(e1)[e2]
struct IfGrammar
: boost::proto::subscript<
boost::proto::arg<
boost::proto::unary_expr<
If,
ExpressionGrammar
>,
>,
StatementGrammar
> {};
// An else_ "operator"
template<typename Expr>
struct Expression<
Expr
, typename enable_if >::type
>
: proto::extends
{
Expression()
: else_(proto::make_expr<Else>(*this)) {};
proto::result_of::make_expr<
Else, // else is now an "operator"
Expression<Expr> const
>::type const else_;
};
// matches if_(e1)[e2].else_[e3]
struct IfElseGrammar
: boost:proto::subscript<
boost::proto::arg<
boost::proto::unary_expr<
Else,
IfGrammar
>,
>,
StatementGrammar
> {};
I didn't understand it then and I don't now. :) However, it seems to
be obsolete since BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE doesn't
seem to exist anymore (it's not documented, anyway).
So how would this be formulated in modern Boost.Proto? I'm guessing
I will need an expression template wrapper (called Expression<> above) that
uses some combination of BOOST_PROTO_BASIC_EXTENDS,
BOOST_PROTO_EXTENDS_SUBSCRIPT and BOOST_PROTO_EXTENDS_FUNCTION. But of course
not all statements have a valid operator() overload and no expressions do.
I guess the grammar will take care of that, yes?
I'm really puzzled about how to do the ".else_" part. I was hoping I could
look to Phoenix to get a clue but it doesn't seem to use Proto.
Any help? Thanks!
-Dave