Как зарегистрировать обработчик ошибок с boost Spirit x3? - PullRequest
0 голосов
/ 06 июня 2019

У меня проблемы с настройкой обработчика ошибок на буст-спирит x3.Я просматривал документацию (https://www.boost.org/doc/libs/1_70_0/libs/spirit/doc/x3/html/spirit_x3/tutorials/error_handling.html), но я не понимаю части: «Обратите внимание, что мы подклассифицируем employee_class из нашего обработчика error_handler. Таким образом, мы сообщаем X3, что мы хотим вызывать наш error_handler всякий раз, когдаИсключение выдается где-то внутри правила работника и того, что он вызывает (т. е. правила person и quoted_string). "

Что имеет тип <ruleID>_class для выполнения с регистрацией?

Я начал сфункциональная композиция описана в ответе Spirit X3: анализатор с внутренним состоянием . Но я не могу зарегистрировать обработчик ошибок. Вот мой пример:

#include <iostream>
#include <iomanip>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>

namespace Parser {
    namespace x3 = boost::spirit::x3;
    namespace ascii = boost::spirit::x3::ascii;

    struct error_handler {
        template<typename Iterator, typename Exception, typename Context>
        x3::error_handler_result on_error(
                Iterator &first, Iterator const &last, Exception const &x, Context const &context) {
            auto &error_handler = x3::get<x3::error_handler_tag>(context).get();
            std::string message = "Error! Expecting: " + x.which() + " here:";
            error_handler(x.where(), message);
            return x3::error_handler_result::fail;
        }
    };

    struct CSVLine;

    static inline auto line_parser() {
        auto delim = ',' | &(x3::eoi | x3::eol);
        return x3::rule<CSVLine>{"line"} = (as_parser(x3::int_) > delim > as_parser(x3::int_) > x3::eps);
    }
    struct CSVLine_class : error_handler, x3::annotate_on_success {};
}

void parse(std::string const &input) {
    using iterator_type = std::string::const_iterator;

    iterator_type iter = input.begin();
    iterator_type const end = input.end();

    using boost::spirit::x3::with;
    using boost::spirit::x3::error_handler_tag;
    using error_handler_type = boost::spirit::x3::error_handler<iterator_type>;

    // Our error handler
    error_handler_type error_handler(iter, end, std::cout);

    // Our parser
    const auto p = Parser::line_parser();
    auto const parser =
            // we pass our error handler to the parser so we can access
            // it later in our on_error and on_sucess handlers
            with<error_handler_tag>(std::ref(error_handler))
            [
                    p
            ];

    if (parse(iter, end, parser))
        std::cout << "Parsed" << std::endl;
    else
        std::cout << "Failed" << std::endl;

    if (iter!=end)
        std::cout << "Remaining: " << std::quoted(std::string(iter,end)) << std::endl;
}

int main() {
    parse("1,x2.6");
    return 0;
}

Поскольку обработчик ошибок непризнал это дает:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::spirit::x3::expectation_failure<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >'
  what():  boost::spirit::x3::expectation_failure
...