|
Boost Users : |
Subject: [Boost-users] concise error messages
From: Manjunath Kudlur (keveman_at_[hidden])
Date: 2010-01-22 17:46:42
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]));
*/
}
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