Search code examples
c++parsingboost-spiritboost-spirit-x3

boost spirit x3 double parser with restrictions


I am currently parsing doubles using boost spirit x3 with this parser:

boost::spirit::x3::real_parser<double, x3::strict_real_policies<double> > const strict_double = {};

but it also parses doubles like .356 and 356. I would like to avoid this, and having the user write 0.356 and 356.0 instead. Hoow can I apply such an restriction on this existing parser? Is there a way without writing my own double parser from the scratch?


Solution

  • You can very easily create a custom policy that does what you want:

    template <typename ValueType>
    struct really_strict_real_policies : boost::spirit::x3::strict_real_policies<ValueType>
    {
        static bool const allow_leading_dot = false;
        static bool const allow_trailing_dot = false;
    };
    

    Full example (Running on WandBox)

    #include <iostream>
    #include <boost/spirit/home/x3.hpp>
    
    template <typename ValueType>
    struct really_strict_real_policies : boost::spirit::x3::strict_real_policies<ValueType>
    {
        static bool const allow_leading_dot = false;
        static bool const allow_trailing_dot = false;
    };
    
    template <typename Parser>
    void parse(const std::string& input, const Parser& parser, bool expected)
    {
        std::string::const_iterator iter=input.begin(), end=input.end();
    
        bool result = boost::spirit::x3::parse(iter,end,parser);
    
        if( (result && (iter==end))==expected )
            std::cout << "Yay" << std::endl;
    }
    
    int main()
    {
        boost::spirit::x3::real_parser<double, really_strict_real_policies<double> > const really_strict_double = {};
    
        parse(".2",really_strict_double,false);
        parse("2.",really_strict_double,false);
        parse("2.2",really_strict_double,true);
    }