Search code examples
c++boostboost-spiritboost-spirit-qi

boost::spirit (qi) decision between float and double


I have a parser which parses different data types from an input file. I already figured out, that spirit can decide between short and int, for example:

value %= (shortIntNode | longIntNode);

with

shortIntNode %= (qi::short_ >> !qi::double_)
                [qi::_val = phoenix::bind(&CreateShortIntNode, qi::_1)];
longIntNode  %= (qi::int_ >> !qi::double_)
                [qi::_val = phoenix::bind(&CreateLongIntNode, qi::_1)];

I used this type of rules to detect doubles as well (from the answers here and here). The parser was able to decide between int for numbers > 65535 and short for numbers <= 65535. But, for float_ and double_ it does not work as expected. It just rounds these values to parse it into a float value, if there is a rule like this:

 value %= (floatNode | doubleFloatNode);   

with

floatNode       %= (qi::float_)
                   [qi::_val = phoenix::bind(&CreateFloatNode, qi::_1)];
doubleFloatNode %= (qi::double_)
                   [qi::_val = phoenix::bind(&CreateDoubleFloatNode, qi::_1)];

Do you know if there is something like an option or some other trick to decide between float_ and double_ depending on the data type range?

Thank you very much!


Solution

  • Lexing can help. Ultimately you decide, not the parser. Ordering your branches should help. See also

    For similar parsers with Boost Spirit.

    If you want to decide between float/double, there is no real input criterion. I'd suggest always parsing into double. However, you could, of course use semantic actions to force a float for certain size.

    Here's what C++ grammar does (e.g.):

    floatrule  = lexeme [ float_ >> 'f' ];
    doublerule = double_;
    
    float_or_double = floatrule | doublerule;