$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-users] Defining Statements with Proto
From: David A. Greene (greened_at_[hidden])
Date: 2009-12-31 12:29:25
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<Expr, Expression<Expr>, Domain> {
         typedef proto::extends<Expr, Expression<Expr>, Domain>
         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<proto::matches<Expr, IfGrammar> >::type
      >
      : proto::extends<Expr, Expression<Expr>, Domain>
      {
         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