Compiling this simple Spirit grammar results in what seems to be a single error (despite the huge error message), possibly having to do with my skipper or some other template parameter that I have mistakenly used.
I experimented with a variety of attribute definitions for the grammar and the start rule, but it had no effect on the error.
#include <string>
#include "/usr/local/boost/include/boost/spirit/include/qi.hpp"
#include "/usr/local/boost/include/boost/spirit/include/qi_symbols.hpp"
using std::string;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
boost::spirit::qi::rule<string::const_iterator>
skipper_rule = qi::space | '#' >> *(qi::char_ - qi::eol) >> qi::eol;
typedef BOOST_TYPEOF(skipper_rule) skipper_T;
template <typename Iterator, typename Skipper>
class Grammar1 : boost::spirit::qi::grammar<Iterator, Skipper>
{
public:
typedef boost::spirit::qi::rule<Iterator, Skipper> rule_nil_T;
typedef boost::spirit::qi::rule<Iterator, string()> rule_str_T;
rule_nil_T under = qi::char_('_');
rule_nil_T dot = qi::char_('.');
rule_nil_T star = qi::char_('*');
rule_str_T file_name_star = qi::lexeme [ (qi::alpha | under) >> *(qi::alnum | under) >> dot >> star ];
rule_nil_T start = +file_name_star;
Grammar1(void) : Grammar1::base_type(start) { };
~Grammar1(void) { };
void parseInputFile(Iterator itr, Iterator itr_end)
{
bool b;
bool r = phrase_parse(itr, itr_end, start, skipper_rule);
if (r && itr == itr_end)
{
std::cout << "Parsing succeeded\n";
} else
{
string rest(itr, itr_end);
std::cout << "stopped at: \": " << rest << "\"\n";
}
}
};
int main(int argc, char **argv)
{
Grammar1<string::const_iterator, skipper_T> g;
string input("input1.* input2.*");
g.parseInputFile(input.cbegin(), input.cend());
}
The important parts of the error message seem to be:
/usr/local/boost/include/boost/spirit/home/qi/nonterminal/rule.hpp:304:17:
error: no match for call to ‘(const function_type *REMOVED*)’
if (f(first, last, context, skipper))
^
The comment at line 304 in the above-mentioned Spirit file states that I may be using an incompatible skipper, but I've tried the much simpler ascii::space_type skipper to no avail.
The rest of the error message:
usr/local/boost/include/boost/function/function_template.hpp:1048:7: note:
candidate is:
class function<BOOST_FUNCTION_PARTIAL_SPEC>
^
/usr/local/boost/include/boost/function/function_template.hpp:758:17: note:
boost::function4<R, T1, T2, T3, T4>:: *REMOVED*
result_type operator()(BOOST_FUNCTION_PARMS) const
^
/usr/local/boost/include/boost/function/function_template.hpp:758:17: note:
no known conversion for argument 4 from ‘const
boost::spirit::unused_type’ to ‘const boost::spirit::qi::reference<const
boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char> > > >&’
Any idea what I am doing wrong? My compiler is gcc 4.8.5.
You are trying to use rule_nil_T
rule which has skipper inside rule_str_T
rule which does not. For internal reasons Spirit can only lose skipper when calling a rule. The problem can be easily solved by inlining under
, dot
, and star
at use site.
Note: a rule call in Qi has an overhead. Creating a rule for such a simple parser and then using it inside repeating parser is not a good idea.
Hint: you can utilize raw
directive and use literal parsers inside it to get more performant and cleaner to look parser. Consider this: qi::lexeme[qi::raw[(qi::alpha | '_') >> qi::alnum % '.'] >> ".*"]
.