Ожидается последовательность и чередование парсеров char_ для синтеза строки - PullRequest
1 голос
/ 29 октября 2019

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

#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;
}

1 Ответ

1 голос
/ 01 ноября 2019

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

Честно говоря, я не всегда знаю, как его "исправить", хотя

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

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

Live On 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
...