Three steps:
Tick โโplaceholders:
on_error<fail>(start, std::cout << val("Error! Expecting ") << qi::_4 << val(" here: \"") << construct<std::string>(qi::_3, qi::_2) << val("\"") << std::endl );
You also need to make sure that you have waiting points in order to call the error handler.
start = eps > +(lit('M') ) >> "</>";
See Boost.Spirit.Qi - Errors at the beginning of a rule for an explanation.
(optional) What are your rules
start.name("start");
Using BOOST_SPIRIT_DEBUG_NODE (S) is another way to implicitly name your rules.
See Live on Coliru (cleansed and simplified in places)
Now it prints (input iv ):
Error! Expecting <sequence>"M""</>" here: 'iv' Parsing failed stopped at: 'iv'
Full code
#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <iostream> #include <fstream> namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; template <typename Iterator> struct roman : qi::grammar<Iterator> { roman() : roman::base_type(start) { using namespace qi; start = eps > +lit('M') >> "</>"; start.name("start"); on_error<fail>(start, phx::ref(std::cout) << "Error! Expecting " << qi::_4 << " here: '" << phx::construct<std::string>(qi::_3, qi::_2) << "'\n" ); } qi::rule<Iterator> start; }; int main() { typedef std::string::const_iterator iterator_type; roman<iterator_type> roman_parser; // Our grammar std::string str; while (std::getline(std::cin, str)) { if (str.empty() || str[0] == 'q' || str[0] == 'Q') break; iterator_type iter = str.begin(), end = str.end(); unsigned result; bool r = parse(iter, end, roman_parser, result); if (r && iter == end) { std::cout << "Parsing succeeded\n"; std::cout << "result = " << result << std::endl; } else { std::string rest(iter, end); std::cout << "Parsing failed\n"; std::cout << "stopped at: '" << rest << "'\n"; } } }
In addition to the comment: This is what I tested with - I have not done it yet, but the error handler starts and feeds as it should. Maybe this can help?
static auto const at_eol = (*_1 == '\r') || (*_1 == '\n'); static auto const at_eoi = (_1 == _2); on_error<retry>(start, ( (phx::ref(std::cout) << "rule start: expecting " << _4 << " here: '" << escape_(_3, _2) << "'\n"), phx::while_ (!at_eoi && !at_eol) [ ++_1, phx::ref(std::cout) << "\nadvance to newline\n" ], phx::while_ (!at_eoi && at_eol) [ ++_1, phx::ref(std::cout) << "\neat newline\n" ], phx::if_ (at_eoi) [ _pass = fail ] ) );
See also the note in the Important section of the documentation for multi_pass <>
source share