Итак, я начал играть с библиотекой 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 — сработало, но вывод был пустым. И вот я здесь. озадачен.
Что-то я не понимаю в распространении атрибутов? Или, может быть, что-то об атрибутах в целом. Может быть, даже метод, чтобы вернуть строку из не пропущенной последовательности?
Может ли кто-нибудь объяснить мне мои ошибки? & Какие-нибудь будущие советы по атрибутам?
Большое спасибо, Адам.
Решение лексемы работает.
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('_')
будет предотвращать добавление подчеркивания к атрибуту строки.
Других решений пока нет …