Boost Spirit QI проблемы со строками и пропуском

Итак, я начал играть с библиотекой Boost Spirit, и это абсолютно потрясающе! Но по пути я столкнулся с множеством ошибок — многие от моего имени за то, что я не полностью прочитал документацию. Но, пройдя столько, сколько смог найти, я озадачен атрибутами — строками в отношении пропуска.

На данный момент я хотел бы обнаружить похожую метку ASM и распечатать ее в консоли следующим образом:

    Identifier = qi::lexeme[qi::alpha >> (*qi::alnum | qi::lit("_"))]
Label      = Identifier >> ":"Syntax     = Label[phx::bind(&Grammar::print, this, qi::_1)];

где phx :: bind вызывает простую функцию вывода строки для cout. Правила определены так:

    qi::rule<Iterator, std::string(), ascii::space_type> Identifier;
qi::rule<Iterator, std::string(), ascii::space_type> Label;
qi::rule<Iterator,                ascii::space_type> Syntax;

Это работает, НО проблема в том, что я не хочу, чтобы шкипер пропускал между Идентификатором и литералом «:».

Я пытался:

    Label = qi::lexeme [Identifier >> ":"]
Label = qi::no_skip[.................]
etc

Но я получаю сообщения об ошибках, такие как преобразование в параметр 4 — не могу преобразовать unused_skipper<..> to char_class<..> в этом есть какой-то смысл. Я также попытался удалить тип шкипера в определении правила, которое не сработало. Затем я попытался смешать его и создать некоторые строки атрибутов правил, в то время как другие нет, — и преобразовать их в строки с использованием as_string — сработало, но вывод был пустым. И вот я здесь. озадачен.

Что-то я не понимаю в распространении атрибутов? Или, может быть, что-то об атрибутах в целом. Может быть, даже метод, чтобы вернуть строку из не пропущенной последовательности?

Может ли кто-нибудь объяснить мне мои ошибки? & Какие-нибудь будущие советы по атрибутам?

Большое спасибо, Адам.

2

Решение

Решение лексемы работает.

no_skip а также lexeme Директива требует, чтобы содержащиеся парсеры не использовали шкипер, поэтому вам нужно изменить Identifier в

qi::rule<Iterator, std::string()> Identifier;

Кстати тогда lexeme внутри это становится излишним:

qi::rule<It, std::string()                > Identifier = qi::alpha >> *(qi::alnum | qi::char_("_"));
qi::rule<It, std::string(), qi::space_type> Label      = qi::lexeme [ Identifier >> ':' ];
qi::rule<It,                qi::space_type> Syntax     = Label [ handle_label_(qi::_1) ];

На самом деле вы можете уменьшить его (полагаясь на предварительный пропуск в Syntax правило):

static const rule<std::string::const_iterator, std::string()>
Identifier = alpha >> *(alnum | char_("_")),
Label      = Identifier >> ':';

Полная программа испытаний: посмотреть Жить на Колиру

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/phoenix/function/adapt_function.hpp>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

void handle_label(std::string const& s) { std::cout << "Parsed label '" << s << ":'\n"; }
BOOST_PHOENIX_ADAPT_FUNCTION(void, handle_label_, handle_label, 1)

bool using_lexeme(std::string const& input)
{
using namespace qi;
static const rule<std::string::const_iterator, std::string()>
Identifier = alpha >> *(alnum | char_("_")),
Label      = Identifier >> ':';

auto f(input.begin()), l(input.end());
return phrase_parse(f, l, Label [ handle_label_(_1) ], space);
}

int main()
{
assert( using_lexeme("some_id:"));
assert( using_lexeme("some_id: "));
assert( using_lexeme(" some_id:"));
assert(!using_lexeme("some_id :"));
}

Еще два примечания:

  • no_skip не пропускает заранее (lexeme значит больше как «держаться вместе»). Попробуйте разницу и посмотрите, как провалится третий тест

  • Ваше использование lit('_') будет предотвращать добавление подчеркивания к атрибуту строки.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]