X3,什么是attr_gen?

X3, what is attr_gen?

我最终遇到了很多这些移动错误,除了与我解析字符串的方式有关外,我不太清楚为什么。删除与 'dummy' 有关的所有内容,然后错误又回来了。

有人提到使用 attr_gen(无法在文档中找到它),通过这样做,我可以克服这些 "traits::move_to" 编译错误,但解析器仍然失败。我已经标记了我添加的行以使其编译,但认为“<---”不是必需的。

#define BOOST_SPIRIT_X3_DEBUG

#include <complex>
#include <iostream>
#include <string>
#include <vector>

#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

namespace client { 
    namespace ast {
        struct number {
            int num1;
            int num2;  
        };

        struct comment {
            std::string text;
            bool dummy;     // <---
        };

        struct input {
            std::vector<comment> comments;  
            std::vector<number> numbers;
        };
    } 
}

BOOST_FUSION_ADAPT_STRUCT(client::ast::comment, text, dummy)    // <---
BOOST_FUSION_ADAPT_STRUCT(client::ast::number, num1, num2)
BOOST_FUSION_ADAPT_STRUCT(client::ast::input, comments, numbers)

namespace client {      
    namespace parser {

        namespace x3 = boost::spirit::x3;
        namespace ascii = boost::spirit::x3::ascii;

        using namespace x3;
        x3::attr_gen dummy;   // <---                   

        auto const comment = char_ % ' ' >> dummy(false);       // <---
        //auto const comment = lexeme[+graph] >> dummy(false);
        auto const number = int_ >> int_;

        auto lines = [](auto p) { return *(p >> eol); };

        auto const input = skip(blank) [
            lines(comment) >> 
            lines(number)
        ];
    }
}

int main()
{
    namespace x3 = boost::spirit::x3;
    using boost::spirit::x3::ascii::blank;
    using x3::char_;

    std::string const iss(R"(this is a test
    1 2)");

    auto iter = iss.begin(), eof = iss.end();

    client::ast::input types;

    bool ok = parse(iter, eof, client::parser::input, types);

    if (iter != eof) {
        std::cout << "Remaining unparsed: '" << std::string(iter, eof) << "'\n";
    }
    std::cout << "Parsed: " << (100.0 * std::distance(iss.begin(), iter) / iss.size()) << "%\n";
    std::cout << "ok = " << ok << std::endl;

    for (auto& item : types.comments)    { std::cout << boost::fusion::as_deque(item) << "\n"; }
    for (auto& item : types.numbers)    { std::cout << boost::fusion::as_deque(item) << "\n"; }
}

x3::attr() 非常好 documented(它背后的生成器类型是一个实现细节,很像你使用 x3::int_,而不是 x3::int_gen)。

之前已经回答了您需要它的事实。关键是单元素融合序列。

  • Spirit Qi attribute propagation issue with single-member struct
comment = char_ % ' ';

这会解析 1 个或多个由单个 space 文字分隔的任意字符。在你的情况下,它可能只匹配 't' 因为后面是 'h',而不是 ' '.

我自然会拼写那个

comment = *(char_ - eol);

所以它将匹配 eol 之前的任何内容。如果硬要配"wordy"的东西,一定要

comment = skip(blank) [ *lexeme[+graph_] ];

要将匹配的输入合成为字符串属性,将其包装在raw[]:

comment = raw [ skip(blank) [ *graph_ ] ];

或者,如果您确实不想要 ' ' 以外的其他白色space,那就这样吧

comment = raw[ skip(' ') [ *graph_ ] ];

这样拼写有点奇怪

comment = raw[ (+graph_) % ' ' ];

因为

  • 不匹配空行
  • 它不匹配 "hello world" 或 `"hello\tworld"'