Как избежать создания исключения, когда анализатор ожидания не работает?
У меня есть правило "function" > (!x3::lexeme[keyword >> !(x3::alnum | '_')] >> symbol) > ('(' > -lvalue_list > ')') > statements > "end"
проанализировать код как:
function a() return one end
keyword
s есть (zero
, one
, function
, return
, end
так далее).
Если я буду кормить парсер function one() return zero end
код, затем в функции expect_directive::parse
Исключение выдается отсюда:
if (!r)
{
boost::throw_exception(
expectation_failure<Iterator>(
first, what(this->subject)));
}
Когда это произойдет, я получил Программа неожиданно завершилась. или же Прервано (ядро сброшено) (в зависимости от используемого терминала).
При отладке кода GDB автоматически разрывается при закрывающей скобке ‘}’ в boost::throw_exception
функция с сообщением:
The inferior stopped because it received a signal from the Operating System.
Signal name :
SIGABRT
Signal meaning :
Aborted
При пошаговом выполнении упомянутой функции видно, что throw enable_current_exception(enable_error_info(e));
строка — последняя строка, выполненная перед выдачей сигнала. Почему для поиска в обработчике исключений нет разматывания стека? Почему прервать мгновенно подняли (выглядит как boost::throw_exception
иметь noexcept
Спецификатор)?
Я обнял в try { ... } catch (x3::expectation_failure< input_iterator_type > const & ef) { ... }
x3::phrase_parse
вызов функции. x3::expectation_failure< input_iterator_type >
именно ожидание, выброшенное из boost::throw_exception
, Все это не имеет значения.
Есть ли способ полностью избежать x3::expectation_failure
исключение в Boost.Spirit X3, но все же прервать парсинг кода в целом и сделать x3::phrase_parse
возвращать false
на провал ожидания?
Мои подозрения следующие:
Из-за обычного возвращаемого значения parse()
функция-член всех парсеров (как концепция в X3) является bool
Я подозреваю, что есть только два способа сообщить о сбое: исключение xor код возврата (который может быть только true
или же false
, а также true
уже занят для Разбор успешен отчет о результатах). Это присуще реализации рекурсивных нисходящих парсеров в C ++. Но если мы изменим тип результата parse
от bool
что-то более широкое, мы можем более гибко различать сообщения о сложных или мягких ошибках (или что-то еще) во время синтаксического анализа — с помощью различных значений кода возврата.
Вы не можете избежать сбоя ожидания при использовании синтаксического анализатора ожидания. Это цель этого оператора.
использование operator>>
для «отслеживаемых ожиданий» (то есть альтернатив).
Когда вы используете точки ожидания (operator>
) просто обработай исключение тоже.
Заметка Это выглядит как опечатка
('(' > -lvalue_list > '>')
должно быть
('(' > -lvalue_list > ')')
Также return one end
не совпадает "begin" >> statements >> "end"
независимо от того, что statements
определяется как…
Исправление вещей:
Жить с отладкой правил (только c ++ 14)
#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace SO {
namespace x3 = boost::spirit::x3;
x3::symbols<char> const keyword = []{
x3::symbols<char> kw;
kw += "for","begin","end","function","while","break","switch";
return kw;
}();
x3::rule<struct symbol_tag> const symbol ("symbol");
x3::rule<struct identifier_tag> const identifier ("identifier");
x3::rule<struct lvalue_list_tag> const lvalue_list("lvalue_list");
x3::rule<struct statements_tag> const statements ("statements");
x3::rule<struct rule_tag> const rule ("rule");
auto symbol_def = x3::lexeme[x3::alnum >> *(x3::alnum | '_')];
auto identifier_def = (!(x3::lexeme[keyword >> !(x3::alnum | '_')]) >> symbol);
auto lvalue_list_def = identifier % ',';
auto statements_def = *identifier;
auto rule_def = "function">> identifier
>> ('(' > -lvalue_list > ')')
>> ("begin" > statements > "end")
;
BOOST_SPIRIT_DEFINE(symbol, identifier, lvalue_list, statements, rule)
}
int main() {
std::string const sample = "function a() begin return one end";
auto f = sample.begin(), l = sample.end();
bool ok = phrase_parse(f, l, SO::rule, SO::x3::space);
if (ok)
std::cout << "Parse success\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
Печать:
<rule>
<try>function a() begin r</try>
<identifier>
<try> a() begin return on</try>
<symbol>
<try> a() begin return on</try>
<success>() begin return one </success>
</symbol>
<success>() begin return one </success>
</identifier>
<lvalue_list>
<try>) begin return one e</try>
<identifier>
<try>) begin return one e</try>
<symbol>
<try>) begin return one e</try>
<fail/>
</symbol>
<fail/>
</identifier>
<fail/>
</lvalue_list>
<statements>
<try> return one end</try>
<identifier>
<try> return one end</try>
<symbol>
<try> return one end</try>
<success> one end</success>
</symbol>
<success> one end</success>
</identifier>
<identifier>
<try> one end</try>
<symbol>
<try> one end</try>
<success> end</success>
</symbol>
<success> end</success>
</identifier>
<identifier>
<try> end</try>
<fail/>
</identifier>
<success> end</success>
</statements>
<success></success>
</rule>
Parse success
Это становится намного проще:
Жить на Колиру (Г ++ / лязг ++)
#include <boost/spirit/home/x3.hpp>
#include <iostream>
int main() {
namespace x3 = boost::spirit::x3;
x3::symbols<char> keyword;
keyword += "for","begin","end","function","while","break","switch";
static auto symbol = x3::lexeme[x3::alnum >> *(x3::alnum | '_')];
static auto identifier = (!(x3::lexeme[keyword >> !(x3::alnum | '_')]) >> symbol);
static auto lvalue_list = identifier % ',';
static auto statements = *identifier;
static auto rule = "function">> identifier
>> ('(' > -lvalue_list > ')')
>> ("begin" > statements > "end")
;
std::string const sample = "function a() begin return one end";
auto f = sample.begin(), l = sample.end();
bool ok = phrase_parse(f, l, rule, x3::space);
if (ok)
std::cout << "Parse success\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
Просто печатает
Parse success
Just И просто чтобы показать вам, Можно справиться с ошибкой ожидания просто отлично: Ожидание обработки ошибок