I've been experimenting with Qi to parse a simple, new-line delimited file of vertices. In the following format (expressed in my made-up easy to read notation):
double double double optional(either (int int int optional(int)) or (double double double optional(double)))
My test-cases start failing with repeat
and I can't find the error. The comments in the code are hopefully more enlightening:
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
qi::rule<std::string::iterator, ascii::space_type> vertexRule =
(double_ >> double_ >> double_);
qi::rule<std::string::iterator, ascii::space_type> colorRule =
(double_ >> double_ >> double_ >> -(double_)) | (uint_ >> uint_ >> uint_ >> -(uint_));
template<typename Iterator, typename Rule>
bool parseIt(Iterator begin, Iterator end, Rule rule) {
bool r = qi::phrase_parse(
begin, end,
rule,
ascii::space
);
if(begin != end) {
std::cout << "No full match!" << std::endl;
while(begin != end)
std::cout << *begin++;
return false;
}
return r;
}
int main()
{
qi::rule<std::string::iterator, ascii::space_type> rule1 =
repeat(3)[vertexRule >> -(colorRule)];
std::string t1{
"20.0 20.0 20.0\n"
"1.0 1.0 1.0 255 0 255 23\n"
"1.0 1.0 1.0 1.0 0.3 0.2 0.3\n"
};
std::cout << std::boolalpha;
// matches
std::cout << parseIt(t1.begin(), t1.end(), rule1) << std::endl;
// 3 double 3 ints
std::string test{"1.0 1.0 1.0 1 3 2\n"};
// matches individually
std::cout << parseIt(test.begin(), test.end(), vertexRule >> -(colorRule)) << std::endl;
// offending line added at the end
// but position does not matter
// also offending 3 double 3 double
std::string t2{
"20.0 20.0 20.0\n"
"1.0 1.0 1.0 255 0 255 23\n"
"1.0 1.0 1.0 1.0 0.3 0.2 0.3\n"
"1.0 1.0 1.0 1 3 2\n"
};
qi::rule<std::string::iterator, ascii::space_type> rule2 =
repeat(4)[vertexRule >> -(colorRule)];
// does not match
std::cout << parseIt(t2.begin(), t2.end(), rule2) << std::endl;
// interestingly this matches
// std::string t2{
// "1.0 1.0 1.0 1 3 2\n"
// "1.0 1.0 1.0 1 3 2\n"
// "1.0 1.0 1.0 1 3 2\n"
// "1.0 1.0 1.0 1 3 2\n"
// };
}
I'm new to parser construction and especially Boost.Spirit. So comments pointing out the obvious are also appreciated.