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"'
我最终遇到了很多这些移动错误,除了与我解析字符串的方式有关外,我不太清楚为什么。删除与 '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"'