Spirit QI 解析器端 eom
Spirit QI parser end eom
我的数据定义为:
std::string data("START34*23*43**");
我的语法:
"START" >> boost::spirit::hex % '*'
问题:
如何解析有两颗星的消息结尾?
目前还不清楚你在问什么。假设您只想 "ignore"(或接受)尾随星号,这就是您的罪魁祸首:
if (first != last) // fail if we did not get a full match
return false;
只需删除这些行即可:
Live On Coliru(注释大大简化):
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
template <typename Iterator>
bool parse_numbers(Iterator& first, Iterator last, std::vector<unsigned>& v) {
return qi::phrase_parse(first, last, ("START" >> qi::hex % '*'), qi::space, v);
}
int main() {
for (std::string const data : {
"START34*23*43",
"START34 * 23 * 43",
"START34 * 23 * 43 *",
"START34 * 23 * 43**",
"START34 * 23 * 43* *",
})
{
auto f = data.begin(), l = data.end();
std::vector<unsigned> v;
if (parse_numbers(f, l, v)) {
std::cout << std::quoted(data) << " Parses OK: " << std::endl;
for (auto i = 0u; i < v.size(); ++i)
std::cout << i << ": " << v[i] << std::endl;
} else {
std::cout << "Parsing failed\n";
}
if (f != l) {
std::cout << "Remaining unparsed: "
<< std::quoted(std::string(f, l)) << "\n";
}
}
}
版画
"START34*23*43" Parses OK:
0: 52
1: 35
2: 67
"START34 * 23 * 43" Parses OK:
0: 52
1: 35
2: 67
"START34 * 23 * 43 *" Parses OK:
0: 52
1: 35
2: 67
Remaining unparsed: "*"
"START34 * 23 * 43**" Parses OK:
0: 52
1: 35
2: 67
Remaining unparsed: "**"
"START34 * 23 * 43* *" Parses OK:
0: 52
1: 35
2: 67
Remaining unparsed: "* *"
或者
如果您真的想忽略相邻的 ** 但仍继续解析,那么有用的更改是说 -qi::hex % '*'
而不是 qi::hex % '*'
,这只会使 hex
可选。
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
template <typename Iterator>
bool parse_numbers(Iterator& first, Iterator last, std::vector<unsigned>& v) {
return qi::phrase_parse(first, last,
("START" >> -qi::hex % '*'), qi::space, v);
}
int main() {
for (std::string const data : {
"START34**23*43",
"START34 * 23 * 43**",
"START*******",
"START*******1 BOGUS",
})
{
auto f = data.begin(), l = data.end();
std::vector<unsigned> v;
if (parse_numbers(f, l, v)) {
std::cout << std::quoted(data) << " Parses OK: " << std::endl;
for (auto i = 0u; i < v.size(); ++i)
std::cout << i << ": " << v[i] << std::endl;
} else {
std::cout << "Parsing failed\n";
}
if (f != l) {
std::cout << "Remaining unparsed: "
<< std::quoted(std::string(f, l)) << "\n";
}
}
}
版画
"START34**23*43" Parses OK:
0: 52
1: 35
2: 67
"START34 * 23 * 43**" Parses OK:
0: 52
1: 35
2: 67
"START*******" Parses OK:
"START*******1 BOGUS" Parses OK:
0: 1
Remaining unparsed: "BOGUS"
In this case you might want to re-assert that all input is parsed with >> qi::eoi
(which beats checking the iterators manually), see Live On Coliru:
"START34**23*43" OK:
0: 52
1: 35
2: 67
"START34 * 23 * 43**" OK:
0: 52
1: 35
2: 67
"START*******" OK:
"START*******1 BOGUS" Failed
更新
对于您 中的更新问题:
@sehe So someting like this: coliru.stacked-crooked.com/a/5ecc5462a8dc0081 – user3314011
您需要进行负面预测以排除 **
:
"START" >> (qi::hex % (qi::lit('*') - "**")) >> "**"
实际上,让我们添加一些期望点(>
而不是>>
):
try {
return qi::parse(first, last, "START" > (qi::hex % (qi::lit('*') - "**")) > "**" > qi::eoi, v);
} catch (qi::expectation_failure<Iterator> const& ef) {
std::ostringstream msg;
msg << "Expected " << ef.what_ << " at " << std::quoted(std::string(ef.first, ef.last), '\'');
throw ParseError(msg.str());
}
现在您也可以看到一些不错的错误消息:
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
struct ParseError : std::runtime_error {
ParseError(std::string msg) : std::runtime_error(std::move(msg)) {}
};
template <typename Iterator>
bool parse_numbers(Iterator& first, Iterator last, std::vector<unsigned>& v) {
try {
return qi::parse(first, last, "START" > (qi::hex % (qi::lit('*') - "**")) > "**" > qi::eoi, v);
} catch (qi::expectation_failure<Iterator> const& ef) {
std::ostringstream msg;
msg << "Expected " << ef.what_ << " at " << std::quoted(std::string(ef.first, ef.last), '\'');
throw ParseError(msg.str());
}
}
int main() {
for (std::string const data : {
"START34*23*43", // Fail no EOM
"START34 * 23 * 43", // Fail spaces
"START34*23*43*", // Fail no EOM
"START34*23*43**", // OK
"START34*23*43**1", // Fail extra number
})
{
std::cout << std::quoted(data) << " -> ";
auto f = data.begin(), l = data.end();
std::vector<unsigned> v;
try {
if (parse_numbers(f, l, v)) {
std::cout << " OK:";
for (auto i : v)
std::cout << " " << i;
std::cout << "\n";
} else {
std::cout << "Not matched\n";
}
} catch(ParseError const& pe) {
std::cout << "Error: " << pe.what() << "\n";
}
}
}
正在打印:
"START34*23*43" -> Error: Expected "**" at ''
"START34 * 23 * 43" -> Error: Expected "**" at ' * 23 * 43'
"START34*23*43*" -> Error: Expected "**" at '*'
"START34*23*43**" -> OK: 52 35 67
"START34*23*43**1" -> Error: Expected <eoi> at '1'
我的数据定义为:
std::string data("START34*23*43**");
我的语法:
"START" >> boost::spirit::hex % '*'
问题: 如何解析有两颗星的消息结尾?
目前还不清楚你在问什么。假设您只想 "ignore"(或接受)尾随星号,这就是您的罪魁祸首:
if (first != last) // fail if we did not get a full match
return false;
只需删除这些行即可:
Live On Coliru(注释大大简化):
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
template <typename Iterator>
bool parse_numbers(Iterator& first, Iterator last, std::vector<unsigned>& v) {
return qi::phrase_parse(first, last, ("START" >> qi::hex % '*'), qi::space, v);
}
int main() {
for (std::string const data : {
"START34*23*43",
"START34 * 23 * 43",
"START34 * 23 * 43 *",
"START34 * 23 * 43**",
"START34 * 23 * 43* *",
})
{
auto f = data.begin(), l = data.end();
std::vector<unsigned> v;
if (parse_numbers(f, l, v)) {
std::cout << std::quoted(data) << " Parses OK: " << std::endl;
for (auto i = 0u; i < v.size(); ++i)
std::cout << i << ": " << v[i] << std::endl;
} else {
std::cout << "Parsing failed\n";
}
if (f != l) {
std::cout << "Remaining unparsed: "
<< std::quoted(std::string(f, l)) << "\n";
}
}
}
版画
"START34*23*43" Parses OK:
0: 52
1: 35
2: 67
"START34 * 23 * 43" Parses OK:
0: 52
1: 35
2: 67
"START34 * 23 * 43 *" Parses OK:
0: 52
1: 35
2: 67
Remaining unparsed: "*"
"START34 * 23 * 43**" Parses OK:
0: 52
1: 35
2: 67
Remaining unparsed: "**"
"START34 * 23 * 43* *" Parses OK:
0: 52
1: 35
2: 67
Remaining unparsed: "* *"
或者
如果您真的想忽略相邻的 ** 但仍继续解析,那么有用的更改是说 -qi::hex % '*'
而不是 qi::hex % '*'
,这只会使 hex
可选。
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
template <typename Iterator>
bool parse_numbers(Iterator& first, Iterator last, std::vector<unsigned>& v) {
return qi::phrase_parse(first, last,
("START" >> -qi::hex % '*'), qi::space, v);
}
int main() {
for (std::string const data : {
"START34**23*43",
"START34 * 23 * 43**",
"START*******",
"START*******1 BOGUS",
})
{
auto f = data.begin(), l = data.end();
std::vector<unsigned> v;
if (parse_numbers(f, l, v)) {
std::cout << std::quoted(data) << " Parses OK: " << std::endl;
for (auto i = 0u; i < v.size(); ++i)
std::cout << i << ": " << v[i] << std::endl;
} else {
std::cout << "Parsing failed\n";
}
if (f != l) {
std::cout << "Remaining unparsed: "
<< std::quoted(std::string(f, l)) << "\n";
}
}
}
版画
"START34**23*43" Parses OK:
0: 52
1: 35
2: 67
"START34 * 23 * 43**" Parses OK:
0: 52
1: 35
2: 67
"START*******" Parses OK:
"START*******1 BOGUS" Parses OK:
0: 1
Remaining unparsed: "BOGUS"
In this case you might want to re-assert that all input is parsed with
>> qi::eoi
(which beats checking the iterators manually), see Live On Coliru:"START34**23*43" OK: 0: 52 1: 35 2: 67 "START34 * 23 * 43**" OK: 0: 52 1: 35 2: 67 "START*******" OK: "START*******1 BOGUS" Failed
更新
对于您
@sehe So someting like this: coliru.stacked-crooked.com/a/5ecc5462a8dc0081 – user3314011
您需要进行负面预测以排除 **
:
"START" >> (qi::hex % (qi::lit('*') - "**")) >> "**"
实际上,让我们添加一些期望点(>
而不是>>
):
try {
return qi::parse(first, last, "START" > (qi::hex % (qi::lit('*') - "**")) > "**" > qi::eoi, v);
} catch (qi::expectation_failure<Iterator> const& ef) {
std::ostringstream msg;
msg << "Expected " << ef.what_ << " at " << std::quoted(std::string(ef.first, ef.last), '\'');
throw ParseError(msg.str());
}
现在您也可以看到一些不错的错误消息:
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
struct ParseError : std::runtime_error {
ParseError(std::string msg) : std::runtime_error(std::move(msg)) {}
};
template <typename Iterator>
bool parse_numbers(Iterator& first, Iterator last, std::vector<unsigned>& v) {
try {
return qi::parse(first, last, "START" > (qi::hex % (qi::lit('*') - "**")) > "**" > qi::eoi, v);
} catch (qi::expectation_failure<Iterator> const& ef) {
std::ostringstream msg;
msg << "Expected " << ef.what_ << " at " << std::quoted(std::string(ef.first, ef.last), '\'');
throw ParseError(msg.str());
}
}
int main() {
for (std::string const data : {
"START34*23*43", // Fail no EOM
"START34 * 23 * 43", // Fail spaces
"START34*23*43*", // Fail no EOM
"START34*23*43**", // OK
"START34*23*43**1", // Fail extra number
})
{
std::cout << std::quoted(data) << " -> ";
auto f = data.begin(), l = data.end();
std::vector<unsigned> v;
try {
if (parse_numbers(f, l, v)) {
std::cout << " OK:";
for (auto i : v)
std::cout << " " << i;
std::cout << "\n";
} else {
std::cout << "Not matched\n";
}
} catch(ParseError const& pe) {
std::cout << "Error: " << pe.what() << "\n";
}
}
}
正在打印:
"START34*23*43" -> Error: Expected "**" at ''
"START34 * 23 * 43" -> Error: Expected "**" at ' * 23 * 43'
"START34*23*43*" -> Error: Expected "**" at '*'
"START34*23*43**" -> OK: 52 35 67
"START34*23*43**1" -> Error: Expected <eoi> at '1'