Search code examples
c++boostboost-spiritboost-variantboost-spirit-karma

boost::spirit::karma: using no_delimit with alternatives


I'm trying to turn off delimiting around a rule that includes the alternatives operator ('|'), but I'm getting a compile error about incompatible delimiters. As an example, I took the calc2_ast_dump.cpp example from boost, and modified the ast_node rule in struct dump_ast to be:

ast_node %= no_delimit[int_ | binary_node | unary_node];

but this gives the compile error:

/usr/include/boost/function/function_template.hpp:754:17: note: candidate function not viable: no known conversion
  from 'const
boost::spirit::karma::detail::unused_delimiter<boost::spirit::karma::any_space<boost::spirit::char_encoding::ascii>
  >' to 'const boost::spirit::karma::any_space<boost::spirit::char_encoding::ascii>' for 3rd argument
result_type operator()(BOOST_FUNCTION_PARMS) const

and a relevant comment in boost/spirit/home/karma/nonterminal/rule.hpp:

// If you are seeing a compilation error here stating that the
// third parameter can't be converted to a karma::reference
// then you are probably trying to use a rule or a grammar with
// an incompatible delimiter type.

in my own project, I'm able to do "no_delimit[a << b]" without issue (using karma::space delimiter).

Is there something I'm missing about alternatives? why would no_delimit work with '<<', but not '|'?

I'm using boost 1.48, so was there a bugfix I need to pick up?


Solution

  • You need to modify the rule declarations to reflect the fact that they aren't using a delimiter.

    Assuming that you didn't want any delimiting, whatsoever:

    template <typename OuputIterator>
    struct dump_ast
      : karma::grammar<OuputIterator, expression_ast()>
    {
        dump_ast() : dump_ast::base_type(ast_node)
        {
            ast_node %= int_ | binary_node | unary_node;
            binary_node %= '(' << ast_node << char_ << ast_node << ')';
            unary_node %= '(' << char_ << ast_node << ')';
        }
    
        karma::rule<OuputIterator, expression_ast()> ast_node;
        karma::rule<OuputIterator, binary_op()> binary_node;
        karma::rule<OuputIterator, unary_op()> unary_node;
    };
    

    See it live on http://liveworkspace.org/code/4edZlj$0