Open Kojoley opened 6 years ago
Oh god, there is inconsistency even in Qi itself.
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/qi.hpp>
#include <boost/fusion/include/std_tuple.hpp>
#include <vector>
#include <iostream>
template <typename F>
void test(F f)
{
std::vector<std::tuple<int, char>> v;
char s[] = "1:a\n2:b\n3:c\n---\n5:e\n---\n---\n7:h\n---";
f(std::begin(s), std::end(s), v);
for (auto [x, y] : v) std::cout << x << ':' << y << '\n';
}
int main()
{
namespace qi = boost::spirit::qi;
namespace x3 = boost::spirit::x3;
std::cout << "qi:\n"; test([](auto f, auto l, auto& v) { qi::parse(f, l, (qi::int_ >> ':' >> qi::char_ | "---") % qi::eol, v); });
std::cout << "x3:\n"; test([](auto f, auto l, auto& v) { x3::parse(f, l, (x3::int_ >> ':' >> x3::char_ | "---") % x3::eol, v); });
}
Output:
qi:
1:a
2:b
3:c
0:
5:e
0:
0:
7:h
0:
x3:
1:a
2:b
3:c
0:
5:e
0:
0:
7:h
0:
This is completely mind-blowing:
#include <boost/spirit/home/qi.hpp>
#include <boost/fusion/include/std_tuple.hpp>
#include <vector>
#include <iostream>
template <typename F>
void test(F f)
{
std::vector<std::tuple<int, char>> v;
char s[] = "1:a\n2:b\n3:c\n---\n5:e\n---\n---\n7:h\n---";
f(std::begin(s), std::end(s), v);
for (auto [x, y] : v) std::cout << ' ' << x << ':' << y;
std::cout << '\n';
}
int main()
{
namespace qi = boost::spirit::qi;
std::cout << "#1:"; test([](auto f, auto l, auto& v) {
qi::parse(f, l, ((qi::int_ >> ':' >> qi::char_) | "---") % qi::eol, v);
});
std::cout << "#2:"; test([](auto f, auto l, auto& v) {
qi::parse(f, l, (-(qi::int_ >> ':' >> qi::char_) >> -qi::lit("---")) % qi::eol, v);
});
// does not compile for some reason
//std::cout << "#3:"; test([](auto f, auto l, auto& v) {
// qi::parse(f, l, (-(qi::int_ >> ':' >> qi::char_) >> -qi::lit("---") | qi::eps) % qi::eol, v);
//});
std::cout << "#3:"; test([](auto f, auto l, auto& v) {
qi::rule<decltype(f), std::tuple<int, char>> item = (qi::int_ >> ':' >> qi::char_);
qi::parse(f, l, (-item >> -qi::lit("---") | qi::eps) % qi::eol, v);
});
// does not compile for some reason
//std::cout << "#4:\n"; test([](auto f, auto l, auto& v) {
// qi::parse(f, l, ((qi::int_ >> ':' >> qi::char_) || "---") % qi::eol, v);
//});
std::cout << "#4:"; test([](auto f, auto l, auto& v) {
qi::rule<decltype(f), std::tuple<int, char>> item = (qi::int_ >> ':' >> qi::char_);
qi::parse(f, l, (item || "---") % qi::eol, v);
});
}
Output:
#1: 1:a 2:b 3:c 0: 5:e 0: 0: 7:h 0:
#2: 1:a 2:b 3:c 0: 5:e 0: 0: 7:h 0:
#3: 1:a 2:b 3:c 5:e 7:h
#4: 1:a 2:b 3:c 5:e 7:h
That's a horrendous bug!
https://svn.boost.org/trac10/ticket/6444 looks like the same problem.
I am reopening it and retargeting to Qi
Update: https://svn.boost.org/trac10/ticket/6444 looks like the same problem.
X3 appends a default constructed value to containers if underlying parser of container handling parser (such as
kleene
,plus
orlist
) does not generate anything.Output: