#include <iostream>
#include <boost/mpl/int.hpp>
#include <boost/proto/fusion.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
#include <boost/mpl/assert.hpp>

namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace fusion = boost::fusion;
using proto::_;

struct my_grammar : proto::or_<
  proto::terminal< int >,
  proto::binary_expr<_, my_grammar, my_grammar>
  >
{};

struct my_lhs_grammar : proto::or_<
  proto::terminal< int& >,
  proto::binary_expr<_, my_grammar, my_grammar>
  >
{};

template<typename Expr>
struct my_expr;

struct my_domain : proto::domain<proto::generator<my_expr>, my_grammar>
{};

template<typename Expr>
struct my_expr
  : proto::extends<Expr, my_expr<Expr>, my_domain>
{
    typedef proto::extends<Expr, my_expr<Expr>, my_domain> base_type;

    my_expr( Expr const & expr = Expr() )
      : base_type( expr )
    {}
};

struct my_int
  : my_expr< proto::terminal< int >::type >
{
  typedef my_expr< proto::terminal< int >::type > base_type;
  explicit my_int (int i = 0) : base_type (base_type::proto_base_expr::make (i)) {}
  operator int () { return proto::value (*this); }
};

int main()
{
  BOOST_MPL_ASSERT ((proto::matches<my_int, my_grammar>));
  // WHY _NOT ?
  BOOST_MPL_ASSERT_NOT ((proto::matches<my_int, my_lhs_grammar>));

  return 0;
}

/// Local Variables:
/// mode:c++
/// comment-column:60
/// fill-column:150
/// compile-command:"g++ -I. -I./boost -o testcase_lhs_grammar testcase_lhs_grammar.cpp"
/// c-macro-cppflags:"-C -I. -I./boost"
/// c-backslash-column:120
/// c-backslash-max-column:149
/// End:

