Boost Spirit x3 - 解析器无法识别行尾
Boost Spirit x3 - parser doesn't recognize end of line
我正在尝试解析 .obj 文件,但我不知道如何让 x3 在行尾停止。
我的代码如下所示:
#include <iostream>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/support/iterators/istream_iterator.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
#include <fstream>
#include <sstream>
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
namespace objParser
{
template <typename Iterator>
bool parse_obj(Iterator first, Iterator last)
{
using boost::spirit::x3::char_;
using boost::spirit::x3::eol;
using boost::spirit::x3::eps;
using boost::spirit::x3::_attr;
using boost::spirit::x3::phrase_parse;
auto printText = [&](auto& ctx) { std::cout << _attr(ctx) << std::endl; };
bool result = phrase_parse(first, last,
// Begin grammar
(
*( char_('#') >> *(~char_('\r\n'))[printText] >> eol)
),
// End grammar
eps(false));
if (!result || first != last) // fail if we did not get a full match
return false;
return result;
}
}
int main()
{
std::string modelPath = "file.obj";
std::ifstream inFile(modelPath, std::ifstream::in);
if (inFile.good()) {
std::cout << "input found" << std::endl;
}
typedef std::istreambuf_iterator<char> base_iterator_type;
typedef boost::spirit::multi_pass<base_iterator_type> forward_iterator_type;
base_iterator_type in_begin(inFile);
base_iterator_type in_end;
forward_iterator_type fwd_begin = boost::spirit::make_default_multi_pass(in_begin);
forward_iterator_type fwd_end = boost::spirit::make_default_multi_pass(in_end);
objParser::parse_obj(fwd_begin, fwd_end);
return 0;
}
语法应该以“#”开头的注释并打印所有内容直到行尾。相反,解析器会打印所有内容,直到文件末尾。
另外,我如何打包 *(~char_('\r\n'))[printText] 以便将行内容作为字符串?目前每个字符都是单独打印的。
正如评论者所说。这就是为什么 you enable warnings:
<source>:33:43: warning: multi-character character constant [-Wmultichar]
33 | *( char_('#') >> *(~char_('\r\n'))[printText] >> eol)
| ^~~~~~
接下来,simplify-time:https://compiler-explorer.com/z/hdWhsndMe
return parse(first, last, //
*('#' >> *(~x3::char_("\r\n"))[printText] >> x3::eol) //
>> x3::eoi //
);
改用 eoi
指令,如果不打算跳过,则不使用 phrase_parse
。
Also how can I pack the *(~char_('\r\n'))[printText] so, that it takes the line content as a string? currently every char is printed separately.
就这么说吧:https://compiler-explorer.com/z/GaPMdzoGr
return parse(first, last, //
*('#' >> (*~x3::char_("\r\n"))[printText] >> x3::eol) //
>> x3::eoi);
演示
#include <boost/spirit/home/support/iterators/istream_iterator.hpp>
#include <boost/spirit/home/x3.hpp>
#include <sstream>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
namespace objParser {
template <typename Iterator> bool parse_obj(Iterator first, Iterator last) {
auto printText = [&](auto& ctx) {
std::cout << _attr(ctx) << std::endl;
};
return parse(first, last, //
*('#' >> (*~x3::char_("\r\n"))[printText] >> x3::eol) //
>> x3::eoi);
}
} // namespace objParser
int main() {
std::istringstream inFile(R"(# this is presumably a comment
# and so is this
)");
boost::spirit::istream_iterator b(inFile >> std::noskipws), e;
objParser::parse_obj(b, e);
}
版画
this is presumably a comment
and so is this
我正在尝试解析 .obj 文件,但我不知道如何让 x3 在行尾停止。
我的代码如下所示:
#include <iostream>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/support/iterators/istream_iterator.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
#include <fstream>
#include <sstream>
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
namespace objParser
{
template <typename Iterator>
bool parse_obj(Iterator first, Iterator last)
{
using boost::spirit::x3::char_;
using boost::spirit::x3::eol;
using boost::spirit::x3::eps;
using boost::spirit::x3::_attr;
using boost::spirit::x3::phrase_parse;
auto printText = [&](auto& ctx) { std::cout << _attr(ctx) << std::endl; };
bool result = phrase_parse(first, last,
// Begin grammar
(
*( char_('#') >> *(~char_('\r\n'))[printText] >> eol)
),
// End grammar
eps(false));
if (!result || first != last) // fail if we did not get a full match
return false;
return result;
}
}
int main()
{
std::string modelPath = "file.obj";
std::ifstream inFile(modelPath, std::ifstream::in);
if (inFile.good()) {
std::cout << "input found" << std::endl;
}
typedef std::istreambuf_iterator<char> base_iterator_type;
typedef boost::spirit::multi_pass<base_iterator_type> forward_iterator_type;
base_iterator_type in_begin(inFile);
base_iterator_type in_end;
forward_iterator_type fwd_begin = boost::spirit::make_default_multi_pass(in_begin);
forward_iterator_type fwd_end = boost::spirit::make_default_multi_pass(in_end);
objParser::parse_obj(fwd_begin, fwd_end);
return 0;
}
语法应该以“#”开头的注释并打印所有内容直到行尾。相反,解析器会打印所有内容,直到文件末尾。 另外,我如何打包 *(~char_('\r\n'))[printText] 以便将行内容作为字符串?目前每个字符都是单独打印的。
正如评论者所说。这就是为什么 you enable warnings:
<source>:33:43: warning: multi-character character constant [-Wmultichar]
33 | *( char_('#') >> *(~char_('\r\n'))[printText] >> eol)
| ^~~~~~
接下来,simplify-time:https://compiler-explorer.com/z/hdWhsndMe
return parse(first, last, //
*('#' >> *(~x3::char_("\r\n"))[printText] >> x3::eol) //
>> x3::eoi //
);
改用 eoi
指令,如果不打算跳过,则不使用 phrase_parse
。
Also how can I pack the *(~char_('\r\n'))[printText] so, that it takes the line content as a string? currently every char is printed separately.
就这么说吧:https://compiler-explorer.com/z/GaPMdzoGr
return parse(first, last, //
*('#' >> (*~x3::char_("\r\n"))[printText] >> x3::eol) //
>> x3::eoi);
演示
#include <boost/spirit/home/support/iterators/istream_iterator.hpp>
#include <boost/spirit/home/x3.hpp>
#include <sstream>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
namespace objParser {
template <typename Iterator> bool parse_obj(Iterator first, Iterator last) {
auto printText = [&](auto& ctx) {
std::cout << _attr(ctx) << std::endl;
};
return parse(first, last, //
*('#' >> (*~x3::char_("\r\n"))[printText] >> x3::eol) //
>> x3::eoi);
}
} // namespace objParser
int main() {
std::istringstream inFile(R"(# this is presumably a comment
# and so is this
)");
boost::spirit::istream_iterator b(inFile >> std::noskipws), e;
objParser::parse_obj(b, e);
}
版画
this is presumably a comment
and so is this