Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

11.2. Defining custom errors

To be able to return custom error messages (like missing_primary_expression) to the user, we need to define those error messages first. The error messages are represented by classes with some requirements:

These classes are called parsing error messages. To make it easy to implement such classes and to make it difficult (if not impossible) to forget to fulfill a requirement, Metaparse provides a macro for defining these classes. To get this macro, include the following header:

> #include <boost/metaparse/define_error.hpp>

Let's define the parsing error message:

> BOOST_METAPARSE_DEFINE_ERROR(missing_primary_expression, "Missing primary expression");

This defines a class called missing_primary_expression representing this error message. What we need to do is making our parser return this error message when one_of fails.

Let's define plus_exp and paren_exp first. Their definition does not change:

> struct plus_exp3;
> using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;

copy-paste friendly version

When the input contains no number (parsed by int_token) and no paren expression (parsed by paren_exp4), we should return the missing_primary_expression error message. We can do it by adding a third parser to one_of<int_token, paren_exp4, ...> which always fails with this error message. Metaparse provides fail for this:

> #include <boost/metaparse/fail.hpp>

Now we can define the primary_exp parser using it:

> using primary_exp3 = one_of<int_token, paren_exp4, fail<missing_primary_expression>>;

It adds fail<missing_primary_expression> to one_of as the last element. Therefore if none of the "real" cases parse the input and none of them makes any progress before failing, the error message will be missing_primary_expression.

We need to define the rest of the parsers. Their definition is the same as before:

> using unary_exp3 = \
...> foldr_start_with_parser< \
...>   minus_token, \
...>   primary_exp3, \
...>   boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
...> >;
> using mult_exp6 = \
...> foldl_start_with_parser< \
...>   sequence<one_of<times_token, divides_token>, unary_exp3>, \
...>   unary_exp3, \
...>   boost::mpl::quote2<binary_op> \
...> >;
> struct plus_exp3 : \
...> foldl_start_with_parser< \
...>   sequence<one_of<plus_token, minus_token>, mult_exp6>, \
...>   mult_exp6, \
...>   boost::mpl::quote2<binary_op> \
...> > {};
> using exp_parser20 = build_parser<plus_exp3>;

copy-paste friendly version

We can can try to give our new parser an invalid input:

> exp_parser20::apply<BOOST_METAPARSE_STRING("hello")>::type
<< compilation error >>
..... x__________________PARSING_FAILED__________________x<1, 1, missing_primary_expression> ....
<< compilation error >>

The error message is now more specific to the calculator language. This covers only one case, where the error messages can be improved. Other cases (eg. missing closing parens, missing operators, etc) can be covered in a similar way.


PrevUpHomeNext