c++ - Boost Spirit Qi Attribute Propagation -
i have issue boost spirit qi grammar emitting undesired type, resulting in compilation error:
error c2664: 'std::basic_string<_elem,_traits,_ax> &std::basic_string<_elem,_traits,_ax>::insert(unsigned int,const std::basic_string<_elem,_traits,_ax> &)' : cannot convert parameter 1 'std::_string_iterator<_elem,_traits,_alloc>' 'unsigned int' here grammar causing issue:
qi::rule<iterator, qi::unused_type()> gr_newline; // asmast::label() contains identifier struct emitted gr_identifier qi::rule<iterator, asmast::label(), skipper<iterator> > gr_label; gr_newline = +( char_('\r') |char_('\n') ); this fails:
gr_label = gr_identifier >> ':' > gr_newline; but following work:
// parses ok gr_label = gr_identifier > gr_newline; // parses ok gr_label = gr_identifier > ':' > gr_newline; // parses ok // **why work when parenthesized?** gr_label = gr_identifier >> (':' > skip_grammar.gr_newline ); // parses ok gr_label = gr_identifier >> omit[':' > gr_newline]; i don't understand why removing character literal or omit[]ing "fixes" problem, don't want grammar cluttered that.
according the compound attribute rules >> , > found here, , character parser attributes here, gr_label should emit asmast::label
a: a, b: b --> (a >> b): tuple<a, b> a: a, b: unused --> (a >> b): <---- 1 here 1 should match far understand a: unused, b: b --> (a >> b): b a: unused, b: unused --> (a >> b): unused expression attribute c unused or if c lazy argument, character type returned invoking it. however, somehow polluting intended attribute, , resulting in compiler error.
so questions grammar emits undesired attribute, , how rid of it.
the problem seems because mix , match > , >> here.
though correctly observe documented attribute generation rules, really appears happen unused side more fusion::vector1<qi::unused_type> (instead of qi::unused_type).
side note:
this explains "why work when parenthesized?" -altering order of expression evaluation (overruling operator precedence), getting type.
you can find out whether hunch correct using techniques e.g. detecting parameter types in spirit semantic action.
so, short answer is: how works. whether bug, omission in documentation or feature not constructive discuss on so. refer [spirit-general] mailing list (note have active #irc channel).
the slightly longer answer is: i think there more not showing.
two things:
the error message quite indicates trying
insertstring iterator* character (or convertible) expected. don't see connection of code posted, though can guess at- the use of qi::raw[] somewhere (quite likely)
- the use of iterator_pair in 1 of ast structs (quite unlikely)
i can compile "problematic" rule specimen fine embedded in "mock-up" grammar built guessing little bits exposed in previous question.
- see full program used below or see running live on coliru (i compiled locally using gcc 4.7.3 , boost 1.53)
i think maybe should try post question, while showing short self contained correct example exhibits problem really having.
be sure mention compiler version , version of boost used.
fully working sscce example
#define boost_spirit_debug #include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; namespace asmast { typedef std::string label; } template <typename it, typename skipper = qi::blank_type> struct parser : qi::grammar<it, skipper> { parser() : parser::base_type(start) { using namespace qi; start = lexeme["func" >> !(alnum | '_')] > function; function = gr_identifier >> "{" >> -( gr_instruction | gr_label //| gr_vardecl //| gr_paramdecl ) % eol > "}"; gr_instruction_names.add("mov", unused); gr_instruction_names.add("push", unused); gr_instruction_names.add("exit", unused); gr_instruction = lexeme [ gr_instruction_names >> !(alnum|"_") ] > gr_operands; gr_operands = -(gr_operand % ','); gr_identifier = lexeme [ alpha >> *(alnum | '_') ]; gr_operand = gr_identifier | gr_string; gr_string = lexeme [ '"' >> *("\"\"" | ~char_("\"")) >> '"' ]; gr_newline = +( char_('\r') |char_('\n') ); gr_label = gr_identifier >> ':' > gr_newline; boost_spirit_debug_nodes((start)(function)(gr_instruction)(gr_operands)(gr_identifier)(gr_operand)(gr_string)); } private: qi::symbols<char, qi::unused_type> gr_instruction_names; qi::rule<it, skipper> start, function, gr_instruction, gr_operands, gr_operand, gr_string; qi::rule<it, qi::unused_type()> gr_newline; qi::rule<it, asmast::label(), skipper> gr_label, gr_identifier; }; int main() { typedef boost::spirit::istream_iterator it; std::cin.unsetf(std::ios::skipws); f(std::cin), l; parser<it, qi::blank_type> p; try { bool ok = qi::phrase_parse(f,l,p,qi::blank); if (ok) std::cout << "parse success\n"; else std::cerr << "parse failed: '" << std::string(f,l) << "'\n"; if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n"; return ok; } catch(const qi::expectation_failure<it>& e) { std::string frag(e.first, e.last); std::cerr << e.what() << "'" << frag << "'\n"; } return false; }
Comments
Post a Comment