Boost spirit x3 在直接解析时插入空字符串
Boost spirit x3 inserting empty strings while direct parsing
我正在尝试使用 boost spirit X3 解析器解析一些文本文件,我发现在使用 lambda 函数或使用 "direct" 解析规则时存在一些差异。
接下来是我的示例代码:
#include <iostream>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
namespace parsers
{
namespace lambda
{
using namespace boost::spirit::x3;
std::vector<std::string> files;
auto f = [&](const auto& ctx) { files.push_back(_attr(ctx)); };
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol
>> eol
>> (*~char_("\r\n"))[f];
auto const ignore = *~char_("\r\n");
auto const start = skip(blank)[(line | ignore) % eol];
}
namespace direct
{
using namespace boost::spirit::x3;
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol
>> eol
>> *~char_("\r\n");
auto const ignore = omit[*~char_("\r\n")];
auto const start = skip(blank)[(line | ignore) % eol];
}
}
std::string file(
" -- HEADER\n\
-- Version: 0.1.0\n\
-- Author: J. A.\n\
-- Copyright:\n\
\n\
-----------------\n\
-- Comments\n\
-----------------\n\
\n\
[FILE_TO_BE_SEARCHED]\n\
\n\
File1.txt\n\
\n\
[FILE_TO_BE_SEARCHED]\n\
\n\
File2.txt\n\
\n\
[FILE_TO_BE_SEARCHED]\n\
\n\
File3.txt\n\
\n\
-- Comments...\n\
\n\
[END]\n\
\n\
-- MD5: 0x1AF3\n"
);
const std::vector<std::string> parse_lambda()
{
x3::parse(file.begin(), file.end(), parsers::lambda::start);
return std::move(parsers::lambda::files);
}
const std::vector<std::string> parse_direct()
{
std::vector<std::string> files;
x3::parse(file.begin(), file.end(), parsers::direct::start, files);
return std::move(files);
}
void print(const std::vector<std::string> files)
{
int i = 0;
std::cout << "Files found: " << files.size() << '\n';
for (const auto& file : files)
std::cout << ++i << " - '" << file << "'\n";
}
int main()
{
std::cout << "Lambda parser:" << '\n';
const auto files_lambda = parse_lambda();
print(files_lambda);
std::cout << "\nDirect parser:" << '\n';
const auto files_direct = parse_direct();
print(files_direct);
return 0;
}
它输出这些行:
Lambda parser:
Files found: 3
1 - 'File1.txt'
2 - 'File2.txt'
3 - 'File3.txt'
Direct parser:
Files found: 21
1 - ''
2 - ''
3 - ''
4 - ''
5 - ''
6 - ''
7 - ''
8 - ''
9 - ''
10 - 'File1.txt'
11 - ''
12 - 'File2.txt'
13 - ''
14 - 'File3.txt'
15 - ''
16 - ''
17 - ''
18 - ''
19 - ''
20 - ''
21 - ''
这是同一源代码的 Coliru link:
https://coliru.stacked-crooked.com/a/bad4dd5002eb3fec 或使用下一个 Coliru 命令行:cat /Archive2/ba/d4dd5002eb3fec/main.cpp
我想请教下一个问题:
1) 如何进行直接解析(非 lambda 函数)以产生与 lambda 解析器相同的输出?
2) 为什么在访问忽略规则时省略指令失败并给出空字符串?
3) 最后但同样重要的是,X3 是否比 Qi 有了重大改进(我的意思是编译速度和 c++14 可能的语法)?它稳定且代码生产证明?
非常感谢,
巴勃罗
我只想使用 seek[]
来大大简化属性传播:
namespace direct {
using namespace boost::spirit::x3;
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol >> eol >> +~char_("\r\n") >> eol;
auto const start = *skip(blank) [ seek[line] ];
}
事不宜迟。
Note the various modernizations/simplifications here: Live On Coliru
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <iomanip>
namespace x3 = boost::spirit::x3;
namespace parsers {
namespace lambda {
using namespace boost::spirit::x3;
std::vector<std::string> files;
auto f = [&](const auto &ctx) { files.push_back(_attr(ctx)); };
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol >> eol >> (*~char_("\r\n"))[f];
auto const ignore = *~char_("\r\n");
auto const start = skip(blank)[(line | ignore) % eol];
}
namespace direct {
using namespace boost::spirit::x3;
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol >> eol >> +~char_("\r\n") >> eol;
auto const start = *skip(blank) [ seek[line] ];
}
}
std::string const file = R"( -- HEADER
-- Version: 0.1.0
-- Author: J. A.
-- Copyright:
-----------------
-- Comments
-----------------
[FILE_TO_BE_SEARCHED]
File1.txt
[FILE_TO_BE_SEARCHED]
File2.txt
[FILE_TO_BE_SEARCHED]
File3.txt
-- Comments...
[END]
-- MD5: 0x1AF3
)";
std::vector<std::string> parse_lambda() { // const is a pessimization here
x3::parse(file.begin(), file.end(), parsers::lambda::start);
return std::move(parsers::lambda::files);
}
std::vector<std::string> parse_direct() { // const is a pessimization here
std::vector<std::string> files;
x3::parse(file.begin(), file.end(), parsers::direct::start, files);
return files; // std::move is a pessimization here
}
void print(std::vector<std::string> const& files) {
int i = 0;
std::cout << "Files found: " << files.size() << "\n";
for (auto&& file : files)
std::cout << ++i << " - " << std::quoted(file) << "\n";
}
int main() {
std::cout << "Lambda parser:\n";
print(parse_lambda());
std::cout << "\nDirect parser:\n";
print(parse_direct());
}
版画
Lambda parser:
Files found: 3
1 - "File1.txt"
2 - "File2.txt"
3 - "File3.txt"
Direct parser:
Files found: 3
1 - "File1.txt"
2 - "File2.txt"
3 - "File3.txt"
其他问题:
我正在尝试使用 boost spirit X3 解析器解析一些文本文件,我发现在使用 lambda 函数或使用 "direct" 解析规则时存在一些差异。
接下来是我的示例代码:
#include <iostream>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
namespace parsers
{
namespace lambda
{
using namespace boost::spirit::x3;
std::vector<std::string> files;
auto f = [&](const auto& ctx) { files.push_back(_attr(ctx)); };
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol
>> eol
>> (*~char_("\r\n"))[f];
auto const ignore = *~char_("\r\n");
auto const start = skip(blank)[(line | ignore) % eol];
}
namespace direct
{
using namespace boost::spirit::x3;
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol
>> eol
>> *~char_("\r\n");
auto const ignore = omit[*~char_("\r\n")];
auto const start = skip(blank)[(line | ignore) % eol];
}
}
std::string file(
" -- HEADER\n\
-- Version: 0.1.0\n\
-- Author: J. A.\n\
-- Copyright:\n\
\n\
-----------------\n\
-- Comments\n\
-----------------\n\
\n\
[FILE_TO_BE_SEARCHED]\n\
\n\
File1.txt\n\
\n\
[FILE_TO_BE_SEARCHED]\n\
\n\
File2.txt\n\
\n\
[FILE_TO_BE_SEARCHED]\n\
\n\
File3.txt\n\
\n\
-- Comments...\n\
\n\
[END]\n\
\n\
-- MD5: 0x1AF3\n"
);
const std::vector<std::string> parse_lambda()
{
x3::parse(file.begin(), file.end(), parsers::lambda::start);
return std::move(parsers::lambda::files);
}
const std::vector<std::string> parse_direct()
{
std::vector<std::string> files;
x3::parse(file.begin(), file.end(), parsers::direct::start, files);
return std::move(files);
}
void print(const std::vector<std::string> files)
{
int i = 0;
std::cout << "Files found: " << files.size() << '\n';
for (const auto& file : files)
std::cout << ++i << " - '" << file << "'\n";
}
int main()
{
std::cout << "Lambda parser:" << '\n';
const auto files_lambda = parse_lambda();
print(files_lambda);
std::cout << "\nDirect parser:" << '\n';
const auto files_direct = parse_direct();
print(files_direct);
return 0;
}
它输出这些行:
Lambda parser:
Files found: 3
1 - 'File1.txt'
2 - 'File2.txt'
3 - 'File3.txt'
Direct parser:
Files found: 21
1 - ''
2 - ''
3 - ''
4 - ''
5 - ''
6 - ''
7 - ''
8 - ''
9 - ''
10 - 'File1.txt'
11 - ''
12 - 'File2.txt'
13 - ''
14 - 'File3.txt'
15 - ''
16 - ''
17 - ''
18 - ''
19 - ''
20 - ''
21 - ''
这是同一源代码的 Coliru link: https://coliru.stacked-crooked.com/a/bad4dd5002eb3fec 或使用下一个 Coliru 命令行:cat /Archive2/ba/d4dd5002eb3fec/main.cpp
我想请教下一个问题:
1) 如何进行直接解析(非 lambda 函数)以产生与 lambda 解析器相同的输出?
2) 为什么在访问忽略规则时省略指令失败并给出空字符串?
3) 最后但同样重要的是,X3 是否比 Qi 有了重大改进(我的意思是编译速度和 c++14 可能的语法)?它稳定且代码生产证明?
非常感谢, 巴勃罗
我只想使用 seek[]
来大大简化属性传播:
namespace direct {
using namespace boost::spirit::x3;
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol >> eol >> +~char_("\r\n") >> eol;
auto const start = *skip(blank) [ seek[line] ];
}
事不宜迟。
Note the various modernizations/simplifications here: Live On Coliru
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <iomanip>
namespace x3 = boost::spirit::x3;
namespace parsers {
namespace lambda {
using namespace boost::spirit::x3;
std::vector<std::string> files;
auto f = [&](const auto &ctx) { files.push_back(_attr(ctx)); };
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol >> eol >> (*~char_("\r\n"))[f];
auto const ignore = *~char_("\r\n");
auto const start = skip(blank)[(line | ignore) % eol];
}
namespace direct {
using namespace boost::spirit::x3;
auto const line = "[FILE_TO_BE_SEARCHED]" >> eol >> eol >> +~char_("\r\n") >> eol;
auto const start = *skip(blank) [ seek[line] ];
}
}
std::string const file = R"( -- HEADER
-- Version: 0.1.0
-- Author: J. A.
-- Copyright:
-----------------
-- Comments
-----------------
[FILE_TO_BE_SEARCHED]
File1.txt
[FILE_TO_BE_SEARCHED]
File2.txt
[FILE_TO_BE_SEARCHED]
File3.txt
-- Comments...
[END]
-- MD5: 0x1AF3
)";
std::vector<std::string> parse_lambda() { // const is a pessimization here
x3::parse(file.begin(), file.end(), parsers::lambda::start);
return std::move(parsers::lambda::files);
}
std::vector<std::string> parse_direct() { // const is a pessimization here
std::vector<std::string> files;
x3::parse(file.begin(), file.end(), parsers::direct::start, files);
return files; // std::move is a pessimization here
}
void print(std::vector<std::string> const& files) {
int i = 0;
std::cout << "Files found: " << files.size() << "\n";
for (auto&& file : files)
std::cout << ++i << " - " << std::quoted(file) << "\n";
}
int main() {
std::cout << "Lambda parser:\n";
print(parse_lambda());
std::cout << "\nDirect parser:\n";
print(parse_direct());
}
版画
Lambda parser:
Files found: 3
1 - "File1.txt"
2 - "File2.txt"
3 - "File3.txt"
Direct parser:
Files found: 3
1 - "File1.txt"
2 - "File2.txt"
3 - "File3.txt"
其他问题: