Как использовать Boost Spirit X3 Kleene Star? - PullRequest
0 голосов
/ 14 октября 2018

Я новичок в boost::spirit и пытаюсь написать простой парсер с использованием x3.Я получил ошибку, которую не могу объяснить.По какой-то причине я получаю сообщение об ошибке boost::spirit::x3::unused_type.Ошибка исчезает, когда я убираю клинскую звезду в строке, отмеченной ниже.Другие звезды Клини, кажется, в порядке (по некоторым причинам).Это мой код:

#include <string>
#include <iostream>
#include <boost/spirit/home/x3.hpp>

namespace x3 = boost::spirit::x3;

int main()
{
    std::string str = "qqq::qqq::qqq";

    auto begin = str.begin(), end   = str.end();
    bool r = x3::parse(begin, end,
        (        (x3::alpha | '_') >> *(x3::alnum | '_')) >>
        *                                         //this line is the problem
        ("::" >> (x3::alpha | '_') >> *(x3::alnum | '_'))
    ); // is supposed to match str

    if (r && std::distance(begin,end) < 1)
    {
        std::cout << "Parsing succeeded\n";
    }
    else
    {
        std::cout << "Parsing FAILED\n";
        std::cout << "r " << r << " d " << std::distance(begin,end) << "\n";
    }

    return 0;
}

Это ошибка:

/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:254:22: error: ‘const struct boost::spirit::x3::unused_type’ has no member named ‘empty’
254 |             if (attr.empty())
    |                 ~~~~~^~~~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:22: error: ‘const struct boost::spirit::x3::unused_type’ has no member named ‘insert’
259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
    |                 ~~~~~^~~~~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:34: error: ‘const struct boost::spirit::x3::unused_type’ has no member named ‘end’
259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
    |                             ~~~~~^~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:46: error: ‘const struct boost::spirit::x3::unused_type’ has no member named ‘begin’
259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
    |                                         ~~~~~^~~~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:60: error: ‘const struct boost::spirit::x3::unused_type’ has no member named ‘end’
259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
    |                                                       ~~~~~^~~

Я на Ubuntu 18.04 с использованием boost 1.65.1.Я прочитал этот пост (https://stackoverflow.com/a/49121776/2359966), где описана похожая проблема.

Есть ли способ исправить или обойти эту проблему без изменения системных пакетов?

1 Ответ

0 голосов
/ 14 октября 2018

Нет, это не просто исправленная ошибка.

Независимо от этого, грамматическая конструкция, такая как x3::alpha | '_', не будет отображать то, что вам нужно, потому что литерал '_' не предоставляет никаких атрибутов.

Таким образом, на практике вы можете просто захотеть упростить использование raw[]:

auto ident = x3::raw [ x3::lexeme [ (x3::alpha | '_') >> *(x3::alnum | '_') ] 

Далее вы можете сопоставить несколько идентификаторов, квалифицированных с помощью :::

x3::raw [ ident >> * ("::" >> ident) ]

Что, кстати, полностью эквивалентно просто

x3::raw [ ident % "::") ]

См.

Бонус:

Назначение атрибутам

Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <iomanip>
#include <string>

namespace x3 = boost::spirit::x3;

int main() {
    std::string str = "foo::_bar::qux_1";

    auto begin = str.begin(), end = str.end();
    auto ident = x3::raw [ x3::lexeme [ (x3::alpha | '_') >> *(x3::alnum | '_') ] ];

    std::vector<std::string> qualified;
    bool r = x3::parse(begin, end, ident % "::", qualified);

    if (r && begin==end) {
        std::cout << "Parsing succeeded\n";
        for (auto& el : qualified) {
            std::cout << " element " << std::quoted(el) << "\n";
        }
    } else {
        std::cout << "Parsing FAILED\n";
    }

    std::cout << std::boolalpha << r << " " << std::quoted(std::string(begin, end)) << "\n";
}

Отпечатки:

Parsing succeeded
 element "foo"
 element "_bar"
 element "qux_1"
true ""

И грамматика упростилась до

std::vector<std::string> qualified;
bool r = x3::parse(begin, end, ident % "::", qualified);

Обычно это хороший знак.


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...