When I parse an input as a std::string, I get the string, but when I parse this as a double_, the fusion struct contains some very small number rather than what is expected.
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <string>
// http://www.boost.org/doc/libs/1_57_0/libs/spirit/example/qi/employee.cpp
namespace FormatConverter {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
// TODO: should this have an initializer?
struct asc {
double timestamp;
};
}
BOOST_FUSION_ADAPT_STRUCT(
FormatConverter::asc,
(double, timestamp)
)
namespace FormatConverter {
template <typename Iterator>
struct asc_parser : qi::grammar< Iterator, asc(), ascii::space_type >
{
asc_parser()
: asc_parser::base_type(start) {
timestamp %= qi::double_ ;
start %= timestamp ;
;
}
qi::rule< Iterator, double, ascii::space_type > timestamp;
qi::rule< Iterator, asc(), ascii::space_type > start;
};
}
And I am testing this with:
#define BOOST_TEST_MODULE parser
#include <boost/test/included/unit_test.hpp>
#include "../FormatConverter/FormatConverter.h"
#include <string>
BOOST_AUTO_TEST_SUITE( TestSuite1 )
BOOST_AUTO_TEST_CASE( timestamp ) {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using iterator_type = std::string::iterator;
using parser_type = FormatConverter::asc_parser<iterator_type>;
parser_type grammar;
FormatConverter::asc record;
std::string str("161.096841 ");
auto beg = str.begin();
auto end = str.end();
auto success = qi::phrase_parse(beg, end, grammar, ascii::space, record);
BOOST_REQUIRE(success);
BOOST_REQUIRE(beg==end);
std::cout << "timestamp: " << boost::fusion::as_vector(record) << std::endl;
}
BOOST_AUTO_TEST_SUITE_END()
You missed a ()
in the attribute:
qi::rule< Iterator, double, ascii::space_type > timestamp;
should be
qi::rule< Iterator, double(), ascii::space_type > timestamp;
Because the params order in qi::rule
can be arbitrary (except Iterator), internally the lib uses some traits to recognize which is attr, which is skipper, ...etc. The attr field has to be in the form of function-sig, i.e. synthesized(inherited)
, if you write double
, it won't be recognized as an attr, so your timestamp
rule will actually have unused_type
instead of double
as its attr, that means, record.timestamp
won't be filled by the parser, it's uninitialized.