Search code examples
boost-spiritboost-spirit-qi

Implementing ternary-type if with lazy evaluation


I'm implementing a production rule for an if function:

qi::rule<Iterator, ascii::space_type, double(void)> f_if;
f_if = qi::ascii::string("if")
            >> qi::char_('(')
            >> (comparator >> ',' >> expression >> ',' >> expression) [qi::_val = boost::phoenix::bind(&Grammar<Iterator>::function_if, this, qi::_1, qi::_2, qi::_3)]
            >> qi::char_(')')
            ;

with expression and comparator declared as

qi::rule<Iterator, ascii::space_type, double(void)> expression;
qi::rule<Iterator, ascii::space_type, bool(void)> comparator;

and the binding function has the prototype

 double function_if(bool comparator, double left, double right);

Is there something I can do so that only one expression is evaluated, according to the value of the comparator?


Solution

  • Use boost::phoenix::if_else which is an actor formulation of the C++ ternary operator:

    >> (comparator >> ',' >> expression >> ',' >> expression) [qi::_val = boost::phoenix::if_else(qi::_1, qi::_2, qi::_3)]

    (with all other lines of code as they were).

    This means that only one of qi::_2 and qi::_3 will be evaluated.