Как написать boost :: spirit :: qi parser, чтобы делать что? делает в регулярных выражениях?

Допустим, у нас есть регулярное выражение «start 🙁 ?: ([0-9] {1,2}))? ([0-9]. *)».

Будет соответствовать

std::string string1 = "start: 01 0ab";

а также

std::string string2 = "start: 0ab";

Мы также можем получить 2 подходящих строки соответственно.

Я пытаюсь использовать анализатор boost :: spirit :: qi для разбора string2, но он не может совпадать.

qi::rule<std::string::const_iterator, std::string()> rule1 = qi::repeat(1,2)[qi::digit];
qi::rule<std::string::const_iterator, std::string()> rule2 = qi::digit >> *qi::char_;
std::vector<std::string> attr;
auto it_begin = string2.begin();
auto it_end = string2.end();
if (qi::parse(
it_begin,
it_end,
qi::lit("start:")
>> -(qi::lit(" ") >> rule1)
>> qi::lit(" ") >> rule2
>> qi::eoi,
attr))
std::cout<<"match"<<std::endl;
else
std::cout<<"not match"<<std::endl;

Конечно, мы можем использовать оператор упреждения, чтобы проверить, что стоит за правилом 1, но есть ли более общий подход для реализации оператора регулярных выражений ‘?’ ? Спасибо!

2

Решение

Я не уверен, что не так с ожиданием. Это единственный способ для двусмысленных правил, так как грамматики PEG всегда жадные.

Однако, возможно, вы не пришли к самой элегантной форме, так как вы искали что-то «лучше». Вот что я сделаю.

Я бы использовал шкипер, чтобы соответствовать пробелам:

    if (qi::phrase_parse(it_begin, it_end,
"start:" >> -rule1 >> rule2 >> qi::eoi,
qi::space, attr))

Где правила по-прежнему лексемы (потому что там были объявлены без шкипера):

qi::rule<It, std::string()> const
rule1 = qi::digit >> qi::digit >> &qi::space,
rule2 = qi::digit >> *qi::graph;

Заметка qi::graph не соответствует пробелу, где *qi::char_ просто соответствует вообще ничего жадно.

Жить на Колиру

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;

int main() {
using It = std::string::const_iterator;

// implicitly lexemes (no skipper in rule declaration)
qi::rule<It, std::string()> const
rule1 = qi::digit >> qi::digit >> &qi::space,
rule2 = qi::digit >> *qi::graph;

for (std::string const input : { "start: 01 0ab", "start: 0ab", }) {
std::vector<std::string> attr;

auto it_begin = input.begin();
auto it_end   = input.end();

if (qi::phrase_parse(it_begin, it_end, "start:" >> -rule1 >> rule2 >> qi::eoi, qi::space, attr))
std::cout << "match\n";
else
std::cout << "not match\n";

if (it_begin!=it_end)
std::cout<<"Remaining unparsed input: '" << std::string(it_begin, it_end) << "'\n";
}
}

Печать

match
match

¹ это предполагает, что множественные / разные пробелы в порядке. Если переводы строк не должны считаться пробелами, используйте qi::blank вместо qi::space

3

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

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

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