Ожидание последовательностей и чередований парсеров char_ для синтеза строки

В следующем тестовом примере чередование одной альфы и последовательности бомб с длинным дампом ошибки, в основном говорящим static assertion failed: The parser expects tuple-like attribute type. Интуитивно я ожидал, что все правило создаст строку, но этого не происходит. Я либо должен изменить левую часть чередования на +alpha (сделав обе стороны векторами), либо пойти по пути семантических действий, по крайней мере, для одинокого символа в чередовании (дописать к _val). Или измените одинокую левую сторону char_ на string. В любом случае, я не могу понять, каков правильный простой способ разбора такой тривиальной строки, любой намек приветствуется. ТИА.

#include <iostream>

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

namespace grammar {

using x3::char_;
using x3::alpha;
using x3::xdigit;

const auto x =
    x3::rule< struct x_class, std::string > { "x" } =
    char_('/') > alpha >> *(alpha | (char_('#') > xdigit));

} // namespace grammar

int main () {
    std::string input{ "/Foobar#F" }, attr;
    auto iter = input.begin ();

    if (phrase_parse (iter, input.end (), grammar::x, x3::space, attr)) {
        std::cout << attr << std::endl;
    }

    return 0;
}

person Engineerist    schedule 29.10.2019    source источник


Ответы (1)


Я тоже ненавижу такое поведение. Ци был гораздо более естественным в этом отношении.

Я, честно говоря, не всегда знаю, как это «исправить», хотя

  • в этом случае кажется, что вы можете использовать raw[] - также упрощая грамматику
  • иногда помогает не смешивать operator> и operator>>

Вот что я бы сделал для вашей грамматики:

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

#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;

namespace grammar {
    const auto x =
        x3::rule<struct x_class, std::string> { "x" } =
        x3::raw [ '/' > x3::alpha >> *(x3::alpha | ('#' > x3::xdigit)) ];
}

int main () {
    std::string input{ "/Foobar#F" }, attr;
    auto iter = input.begin ();

    if (phrase_parse (iter, input.end (), grammar::x, x3::space, attr)) {
        std::cout << attr << std::endl;
    }
}

Отпечатки

/Foobar#F
person sehe    schedule 31.10.2019
comment
Очень признателен. Я ничего не знаю о внутренних деталях духа. IIUC, такое поведение одинаково во всех парсерах, а согласованность — отличный дизайн. Но мне просто кажется, что интуитивное поведение, то, что ожидается, если вообще возможно, здесь должно присутствовать. - person Engineerist; 01.11.2019
comment
TBH Я думаю, что это связано с (случайным?) фундаментальным изменением в понимании совместимости атрибутов и распространения с помощью правил в X3. Похоже, что от открытых и синтезированных типов атрибутов ожидается гораздо более строгое соответствие, и я полагаю это должно было помочь с получением более качественных сообщений об ошибках. Я чувствую, что это непреднамеренно удалило возможности расширения/преобразования. Если бы я лучше понимал код и цели его разработки, я мог бы подать заявку по этому поводу. - person sehe; 01.11.2019