Boost logo

Boost Users :

Subject: [Boost-users] Question on grammar
From: Manjunath Kudlur (keveman_at_[hidden])
Date: 2010-01-26 22:31:09


I am sure this has been asked before, but I am not able to find an
answer to my specific question in the archives. I wanted to create a
grammar that can accept statements like if_(expr)[ statement-list
].else_[statement-list]. I created a if_expr type using
proto::extends, and added a member called else_ to it, of type
proto::function<proto::terminal<if_then_else>, Expr const&>. The code
is given below. I am trying to match statements of the above form.
Look for if_only_grammar and if_grammar below. The main function has 2
cases, one with just if_ and another with if_ and else_. My grammar
matches neither of them. What am I doing wrong? I am quite the newbie
to proto, so I am not still able to parse the compiler error message
and understand it yet. I will be grateful for any help.

Thanks,
Manjunath

#include <boost/proto/proto.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>

#include <iostream>
#include <sstream>
#include <string>

using namespace boost;
using namespace std;

unsigned int ids;

template<typename VT>
struct Var {
  unsigned int id;
  Var() {
    id = ++ids;
  }
};

struct if_fun {};
struct program {};

struct if_then_else {};

struct if_domain;

template <typename Expr>
struct if_expr
  : proto::extends<Expr, if_expr<Expr>, if_domain> {

  typedef proto::extends<Expr, if_expr<Expr>, if_domain> base_type;

  using base_type::operator =;

  typedef typename proto::result_of::make_expr<proto::tag::function,
  if_then_else, Expr const &>::type else_type;
  else_type else_;

  if_expr(Expr const &e = Expr())
    : base_type(e)
      , else_(proto::make_expr<proto::tag::function>(if_then_else(),
boost::ref(e)))
  {}

};

struct if_domain
  : proto::domain<proto::generator<if_expr> > {
};

struct napl_grammar;

struct arith_expr_grammar;
struct rel_expr_grammar;
struct assign_grammar;
struct statement_grammar;
struct bb_grammar;

struct if_only_grammar :
  proto::or_<
  proto::subscript<proto::function<if_expr<proto::terminal<if_fun>::type>,
rel_expr_grammar >, bb_grammar>
> {
};

struct if_grammar :
  proto::or_<
  if_only_grammar,
  proto::subscript<proto::function<proto::terminal<if_then_else>,
if_only_grammar>, bb_grammar>
> {
};

struct arith_expr_grammar :
  proto::or_<
  proto::plus< arith_expr_grammar, arith_expr_grammar>,
  proto::minus< arith_expr_grammar, arith_expr_grammar>,
  proto::multiplies< arith_expr_grammar, arith_expr_grammar>,
  proto::divides< arith_expr_grammar, arith_expr_grammar>,
  proto::terminal<Var<int> >,
  proto::terminal<int>,
  rel_expr_grammar
> {
};

struct rel_expr_grammar :
  proto::or_<
  proto::less< arith_expr_grammar, arith_expr_grammar>,
  proto::greater< arith_expr_grammar, arith_expr_grammar>,
  proto::less_equal< arith_expr_grammar, arith_expr_grammar>,
  proto::greater_equal< arith_expr_grammar, arith_expr_grammar>,
  proto::equal_to< arith_expr_grammar, arith_expr_grammar>,
  proto::not_equal_to< arith_expr_grammar, arith_expr_grammar>,
  proto::logical_not< rel_expr_grammar>
> {
};

struct assign_grammar :
  proto::or_<
  proto::assign<proto::terminal<Var<int> >, arith_expr_grammar>,
  proto::assign<proto::terminal<Var<int> >, rel_expr_grammar>
> {
};

struct statement_grammar :
  proto::or_<
  assign_grammar,
  if_grammar
> {
};

struct bb_grammar :
  proto::or_<
  statement_grammar,
  proto::comma<bb_grammar, statement_grammar>
> {
};

struct napl_grammar :
  proto::or_<
  proto::terminal<program>,
  proto::subscript<proto::terminal<program>, bb_grammar>
> {
};

template<typename Expr>
void check_and_execute(const Expr &e, mpl::true_)
{
  cout << "Program printer TBD.\n";
}

template<typename Expr>
void check_and_execute(const Expr &e, mpl::false_)
{
  cout << "Should not be here\n";
}

template<typename Expr>
void check_grammar(const Expr &e)
{
  BOOST_MPL_ASSERT_MSG((proto::matches<Expr, napl_grammar>::value),
                       SYNTAX_NOT_CORRECT,
                       (void));
  check_and_execute(e, proto::matches<Expr, napl_grammar>());
  //cout << napl_grammar()(e) << "\n";
}

int main()
{
  proto::terminal<Var<int> >::type i1, i2, i3, i4, i5;
  proto::terminal<program>::type Program;
  if_expr<proto::terminal<if_fun>::type> if_;
  int i=4242;

  check_grammar(
    Program[
      if_(i1 < i2) [
        i2
      ]
    ]);
  /*
  check_grammar(
    Program[
      if_(i1 < i2) [
        i2
      ].else_[
        i3
      ]
    ]);
  */
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net