Spirit X3 не бросает ожидание провала

В документации сказано, что когда я использую оператор ожидания, я должен получить expectation_failure, когда оператор не соответствует. Я хочу поймать исключение, чтобы указать пользователю, где находится ошибочный ввод. Но, похоже, вместо этого я получаю какое-то завернутое исключение:

 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*, std::string> > > >'
  what():  boost::spirit::x3::expectation_failure
Aborted

Мои операторы catch:

try {
    r = parse(iter, end, wctl_parser::entry, root);
} catch (x3::expectation_failure<char const*> const& x) {
    std::cout << "Never runs,";
} catch (x3::expectation_failure<std::string::const_iterator> const& e) {
    std::cout << "me neither" << std::endl;
}

Обновление: вот небольшая программа, демонстрирующая поведение:

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <iostream>
#include <string>
#include <vector>

namespace wccs_parser {

namespace x3 = boost::spirit::x3;
namespace ascii = x3::ascii;
namespace qi = boost::spirit::qi;

struct AstNullProcess;
struct AstChoiceProcess;

using AstAnyProcess = x3::variant<
     x3::forward_ast<AstNullProcess>,
     x3::forward_ast<AstChoiceProcess>
>;

struct AstNullProcess {};
struct AstChoiceProcess {
    AstAnyProcess left;
    AstAnyProcess right;
};


} // End namespace

BOOST_FUSION_ADAPT_STRUCT(wccs_parser::AstChoiceProcess, left, right)

namespace wccs_parser {

template <typename T> auto rule = [](const char* name = typeid(T).name()) {
     struct _{};
     return x3::rule<_, T> {name};
};

template <typename T> auto as = [](auto p) { return rule<T>() = p; };

auto nullProcess  = as<AstNullProcess>(x3::omit['0']);

auto const choiceActual = as<AstChoiceProcess> (nullProcess > '+' > nullProcess);
auto const choice = rule<AstAnyProcess> ("choice")
     = nullProcess >> !x3::lit('+')
     | choiceActual;

auto const entry = x3::skip(ascii::space) [choice];


} //End namespace

namespace x3 = boost::spirit::x3;

int main() {
    std::string str("0 + ");
    wccs_parser::AstAnyProcess root;
    auto iter = str.begin();
    auto end = str.end();
    bool r = false;
    try {
        r = parse(iter, end, wccs_parser::entry, root);
    } catch (x3::expectation_failure<char const*> const& x) {
        std::cout << "Never runs," << std::endl;
    } catch (x3::expectation_failure<std::string::const_iterator> const& e) {
        std::cout << "me neither" << std::endl;
    }
    if (r) {
        std::cout << str << std::endl << std::endl << " Parses OK: " << std::endl;
        std::cout << "\n-------------------------\n";
    } else {
        std::cout << "Parsing failed\n";
        std::cout << "-------------------------\n";
    }
    if (iter != end) std::cout << "Partial match" << std::endl;
    return 0;
}

person senevoldsen    schedule 07.11.2017    source источник
comment
Вы пробовали область, о которой он сообщает? boost::spirit::x3::expectation_failure Я бы попробовал поймать это, чтобы посмотреть, работает ли это.   -  person 9Breaker    schedule 07.11.2017
comment
Можете ли вы сделать самодостаточный пример, демонстрирующий проблему?   -  person sehe    schedule 07.11.2017
comment
Я добавил небольшую программу в исходный пост, в которой есть проблема.   -  person senevoldsen    schedule 07.11.2017
comment
Если вы хотите привлечь внимание, добавьте уведомление @senevoldsen @name   -  person sehe    schedule 07.11.2017


Ответы (1)


Если вы поймаете const_iterator, вы захотите убедиться, что const_iterator это то, что вы передаете для синтаксического анализа:

std::string const str("0 + ");

Смотрите Прямой эфир на Coliru

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <iostream>
#include <string>
#include <vector>

namespace wccs_parser {
    using boost::spirit::x3::variant;
    using boost::spirit::x3::forward_ast;

    struct AstNullProcess;
    struct AstChoiceProcess;

    using AstAnyProcess = variant<
        forward_ast<AstNullProcess>,
        forward_ast<AstChoiceProcess>
    >;

    struct AstNullProcess {};
    struct AstChoiceProcess {
        AstAnyProcess left;
        AstAnyProcess right;
    };

} // End namespace

BOOST_FUSION_ADAPT_STRUCT(wccs_parser::AstChoiceProcess, left, right)

namespace wccs_parser {
    namespace x3 = boost::spirit::x3;
    using x3::expectation_failure;

    template <typename T> auto rule = [](const char* name = typeid(T).name()) {
         struct _{};
         return x3::rule<_, T> {name};
    };

    template <typename T> auto as = [](auto p, const char* name = typeid(T).name()) { return rule<T>(name) = p; };

    auto nullProcess  = as<AstNullProcess>(x3::omit['0'], "nullProcess");

    auto const choiceActual = as<AstChoiceProcess> (nullProcess > '+' > nullProcess, "choiceActual");
    auto const choice = rule<AstAnyProcess> ("choice")
         = nullProcess >> !x3::lit('+')
         | choiceActual;

    auto const entry = x3::skip(x3::ascii::space) [choice];
}

int main() {

    std::string const str("0 + ");

    try {
        auto iter = str.cbegin();
        auto end = str.cend();

        wccs_parser::AstAnyProcess root;
        bool const r = parse(iter, end, wccs_parser::entry, root);
        if (r) {
            std::cout << str << "\n\n Parses OK: \n";
            std::cout << "\n-------------------------\n";
        } else {
            std::cout << "Parsing failed\n";
            std::cout << "-------------------------\n";
        }

        if (iter != end) {
            std::cout << "Partial match, leaving '" << std::string(iter,end) << "'\n";
        }
    } catch (wccs_parser::expectation_failure<std::string::const_iterator> const& e) {
        std::cout << "Expected: " << e.which() << " at '" << std::string(e.where(), str.end()) << "'\n";
        return 1;
    }
}

Отпечатки

Expected: nullProcess at ' '
person sehe    schedule 07.11.2017
comment
Улучшен образец кода (именование правил, область действия, связь пространств имен) - person sehe; 07.11.2017