I've been using spirit::qi
quite often for the past several months. However, this time I got a segfault that I really can't make any sense out of.
I have reduced it to an extremely minimal test case, the grammar definition is 12 lines of code.
This feels a lot like an earlier question but the solution there, of adding .alias()
to some of the terminals so that qi
doesn't make copies of them, doesn't seem to fix this.
I'm concerned that there's something fundamental I'm missing here, since I've managed to make way more complicated grammars than this that test out exactly the way I expect.
The only thing that occurs to me now is that, maybe qi just doesn't like for the main grammar return type to be a boost variant? I don't know if I have made any grammars that do that before. I guess I'll test this next but honestly I've been spinning my wheels fiddling with things like that for a while.
I can confirm that, if the line that sets up the mod_
rule is commented out, then no segfault occurs and the program runs normally to completion.
Edit: Actually, it segfaults even if all of the grammar attributions are deleted.
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <iostream>
typedef unsigned int uint;
namespace qi = boost::spirit::qi;
/***
* Grammar
*/
template <typename Iterator>
struct op_grammar : qi::grammar<Iterator> {
qi::rule<Iterator> constant_;
qi::rule<Iterator> mod_;
qi::rule<Iterator> expr_;
op_grammar() : op_grammar::base_type(expr_) {
constant_ = qi::uint_;
expr_ = mod_ | constant_;
mod_ = expr_ >> qi::lit('%') >> expr_;
}
};
/***
* Test
*/
int main() {
// std::string str{"n % 2"};
std::string str{"2"};
typedef std::string::const_iterator str_it;
str_it it = str.begin();
str_it end = str.end();
op_grammar<str_it> grammar;
if (qi::parse(it, end, grammar) && it == end) {
std::cerr << "Good\n";
} else {
std::cerr << "Bad\n";
}
}