
Hello, I wrote a small DSEL with proto. An example program can be found in the main function below. I use BOOST_MPL_ASSERT_MSG to check an expression against a grammar, and can make the compiler output a small string if the syntax is wrong. But I can do it only for the entire program. Is there a way to do finer grain grammar checking with proto? For example, I haven't defined the "<" operator for expressions, but when I use it in the DSEL code, I get 10 pages of error messages from g++, with the SYNTAX_NOT_CORRECT string somewhere. I would like to get somewhat more accurate than this. Any pointers? Thanks, Manjunath #include <boost/proto/proto.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 VarName : proto::callable { typedef string result_type; template<typename T> result_type operator()(const Var<T> &v) { stringstream s; s << "V" << v.id; return string(s.str()); } result_type construct(string &l, string op, string &r) { return string(l + op + r); } result_type operator()(proto::tag::plus, string l, string r) { return construct(l, string(" + "), r); } result_type operator()(proto::tag::minus, string l, string r) { return construct(l, string(" - "), r); } result_type operator()(proto::tag::divides, string l, string r) { return construct(l, string(" / "), r); } result_type operator()(proto::tag::multiplies, string l, string r) { return construct(l, string(" * "), r); } result_type operator()(proto::tag::assign, string l, string r) { return string(construct(l, string(" = "), r) + string(";")); } result_type operator()(const int &x) { stringstream s; s << x; return string(s.str()); } result_type operator()(const if_fun&) { return string("if"); } result_type operator()(const program&) { return string("program"); } result_type operator()(proto::tag::function, string l, string r) { stringstream s; s << l << "(" << r << ")"; return string(s.str()); } result_type operator()(proto::tag::subscript, string l, string r) { stringstream s; s << l << " [\n"; s << r; s << "\n]\n"; return string(s.str()); } result_type operator()(proto::tag::comma, string l, string r) { stringstream s; s << l << "\n"; s << r; return string(s.str()); } }; struct napl_grammar; struct expr_grammar; struct bb_grammar; struct if_grammar : proto::or_< proto::when<proto::terminal<if_fun>, VarName(proto::_value)>, proto::when<proto::function<proto::terminal<if_fun>, expr_grammar>, VarName(proto::tag_of<proto::_expr>(), if_grammar(proto::_left), expr_grammar(proto::_right))>
{ };
struct expr_grammar : proto::or_< proto::when<proto::plus< expr_grammar, expr_grammar>, VarName(proto::tag_of<proto::_expr>(), expr_grammar(proto::_left), expr_grammar(proto::_right))>, proto::when<proto::minus< expr_grammar, expr_grammar>, VarName(proto::tag_of<proto::_expr>(), expr_grammar(proto::_left), expr_grammar(proto::_right))>, proto::when<proto::multiplies< expr_grammar, expr_grammar>, VarName(proto::tag_of<proto::_expr>(), expr_grammar(proto::_left), expr_grammar(proto::_right))>, proto::when<proto::divides< expr_grammar, expr_grammar>, VarName(proto::tag_of<proto::_expr>(), expr_grammar(proto::_left), expr_grammar(proto::_right))>, proto::when<proto::assign< proto::terminal<Var<int> >, expr_grammar>, VarName(proto::tag_of<proto::_expr>(), expr_grammar(proto::_left), expr_grammar(proto::_right))>, proto::when<proto::terminal<Var<int> >, VarName(proto::_value)>, proto::when<proto::terminal<int>, VarName(proto::_value)>, proto::when<proto::subscript<if_grammar, bb_grammar>, VarName(proto::tag_of<proto::_expr>(), if_grammar(proto::_left), bb_grammar(proto::_right))>
{ };
struct bb_grammar : proto::or_< proto::when<expr_grammar, expr_grammar(proto::_expr)>, proto::when<proto::comma<bb_grammar, expr_grammar>, VarName(proto::tag_of<proto::_expr>(), bb_grammar(proto::_left), expr_grammar(proto::_right))>
{ };
struct napl_grammar : proto::or_< proto::when<proto::terminal<program>, VarName(proto::_value)>, proto::when<proto::subscript<proto::terminal<program>, bb_grammar>, VarName(proto::tag_of<proto::_expr>(), napl_grammar(proto::_left), bb_grammar(proto::_right))>
{ };
template<typename Expr> void check_grammar(const Expr &e) { BOOST_MPL_ASSERT_MSG((proto::matches<Expr, napl_grammar>::value), SYNTAX_NOT_CORRECT, (void)); cout << napl_grammar()(e) << "\n"; } template<typename Expr> void check_if_grammar(const Expr&) { BOOST_MPL_ASSERT_MSG((proto::matches<Expr, if_grammar>::value), IF_SYNTAX_NOT_CORRECT, (if_grammar)); } template<typename Expr> void check_expr_grammar(const Expr &e) { BOOST_MPL_ASSERT_MSG((proto::matches<Expr, expr_grammar>::value), EXPR_SYNTAX_NOT_CORRECT, (expr_grammar)); cout << expr_grammar()(e) << "\n"; } template<typename Expr> void check_bb_grammar(const Expr &e) { BOOST_MPL_ASSERT_MSG((proto::matches<Expr, bb_grammar>::value), BB_SYNTAX_NOT_CORRECT, (bb_grammar)); cout << bb_grammar()(e) << "\n"; } int main() { proto::terminal<Var<int> >::type i1, i2, i3, i4, i5; proto::terminal<program>::type Program; proto::terminal<if_fun>::type if_; check_grammar( Program[ i2 = 1 + i2, i3 = i3 * i3, i3=i4/i4, i3=i5-23, if_(i1) [ i2=1, i2, if_(i2) [ i3=1, i3=i5, if_(i3) [ i1=1, i4=42+i4 ] ] ] ] ); /* check_if_grammar( if_(i1)); check_bb_grammar((i4=i1+i2+42, i2=2, i3=i2/42, if_(i1)[i2=3, i3=0])); */ }