c++boost-spirit-qiunicode-string

Error compiling a boost qi parser to skip all comments and spaces in a php code string


Following my previous question, and applying the suggestions, I have created this boost qi spirit grammar to get only 'non-comments' from a piece of PHP code in the string contents:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/qi_string.hpp>
#include <boost/spirit/include/qi_operator.hpp>
#include <boost/spirit/include/qi_action.hpp>
#include <boost/spirit/include/qi_auxiliary.hpp>
namespace qi = boost::spirit::qi;
using namespace std;

int main(int argc, char *argv[])
{
    std::string contents = "<?php echo \"Soy español\";?>";
    using Iterator = std::string::const_iterator;
    struct StripCommentParser : qi::grammar<Iterator, std::string()> {
        StripCommentParser() : StripCommentParser::base_type(start) {
            using namespace qi;
            single_line_comment = "//" >> *(qi::char_ - eol) >> (eol | eoi);
            block_comment       = ("/*" >> *(block_comment | qi::char_ - "*/")) > ("*/" | eoi);
            php_comment         = '#' >> *(qi::char_ - eol) >> (eol | eoi);
            start = qi::skip(space | single_line_comment | block_comment | php_comment)[*qi::char_];
        }

    private:
        qi::rule<Iterator, std::string()> start;
        qi::rule<Iterator> block_comment, single_line_comment, php_comment;
    };
    string non_comments_code;
    // This is the line that triggers the compiler error
    parse(begin(contents), end(contents), StripCommentParser{}, non_comments_code);
}

But I get this compiler error:

In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
                from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
                from /usr/include/boost/spirit/home/qi.hpp:21,
                from /usr/include/boost/spirit/include/qi.hpp:16,
                from ../../src/capel-tool.cpp:4:
/usr/include/boost/spirit/home/qi/reference.hpp: In instantiation of ‘bool boost::spirit::qi::reference<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::__cxx11::basic_string<char>&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::__cxx11::basic_string<char>; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>]’:
/usr/include/boost/spirit/home/qi/parse.hpp:88:47:   required from ‘bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = main(int, char**)::StripCommentParser; Attr = std::__cxx11::basic_string<char>]’
/usr/include/boost/spirit/home/qi/parse.hpp:100:25:   required from ‘bool boost::spirit::qi::parse(const Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = main(int, char**)::StripCommentParser; Attr = std::__cxx11::basic_string<char>]’
../../src/capel-tool.cpp:106:80:   required from here
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: error: no matching function for call to ‘boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::parse(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<std::__cxx11::basic_string<char>&, boost::fusion::nil_>, boost::spirit::locals<> >&, const boost::spirit::unused_type&, std::__cxx11::basic_string<char>&) const’
43 |             return ref.get().parse(first, last, context, skipper, attr_);
    |                    ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
                from /usr/include/boost/spirit/home/qi.hpp:21,
                from /usr/include/boost/spirit/include/qi.hpp:16,
                from ../../src/capel-tool.cpp:4:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:282:14: note: candidate: ‘template<class Context, class Skipper, class Attribute> bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Context = Context; Skipper = Skipper; Attribute = Attribute; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
282 |         bool parse(Iterator& first, Iterator const& last
    |              ^~~~~
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:282:14: note:   template argument deduction/substitution failed:
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
                from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
                from /usr/include/boost/spirit/home/qi.hpp:21,
                from /usr/include/boost/spirit/include/qi.hpp:16,
                from ../../src/capel-tool.cpp:4:
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: note:   cannot convert ‘first’ (type ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >’) to type ‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&’
43 |             return ref.get().parse(first, last, context, skipper, attr_);
    |                    ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
                from /usr/include/boost/spirit/home/qi.hpp:21,
                from /usr/include/boost/spirit/include/qi.hpp:16,
                from ../../src/capel-tool.cpp:4:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:333:14: note: candidate: ‘template<class Context, class Skipper, class Attribute, class Params> bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&, const Params&) const [with Context = Context; Skipper = Skipper; Attribute = Attribute; Params = Params; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = std::__cxx11::basic_string<char>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
333 |         bool parse(Iterator& first, Iterator const& last
    |              ^~~~~
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:333:14: note:   template argument deduction/substitution failed:
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
                from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
                from /usr/include/boost/spirit/home/qi.hpp:21,
                from /usr/include/boost/spirit/include/qi.hpp:16,
                from ../../src/capel-tool.cpp:4:
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: note:   candidate expects 6 arguments, 5 provided
43 |             return ref.get().parse(first, last, context, skipper, attr_);
    |                    ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Solution

  • I am not near a computer, so can’t test. However, try with constant std::string contents; (or indeed using cbegin and cend) to match the expected iterator type.