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
insert
string 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