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

How to write a boost::spirit::qi parser to parse an integer range from 0 to std::numeric_limits<int>::max()?


I tried to use qi::uint_parser<int>(). But it is the same like qi::uint_. They all match integers range from 0 to std::numeric_limits<unsigned int>::max().

Is qi::uint_parser<int>() designed to be like this? What parser shall I use to match an integer range from 0 to std::numeric_limits<int>::max()? Thanks.


Solution

  • Simplest demo, attaching a semantic action to do the range check:

    uint_ [ _pass = (_1>=0 && _1<=std::numeric_limits<int>::max()) ];
    

    Live On Coliru

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    template <typename It>
    struct MyInt : boost::spirit::qi::grammar<It, int()> {
        MyInt() : MyInt::base_type(start) {
            using namespace boost::spirit::qi;
            start %= uint_ [ _pass = (_1>=0 && _1<=std::numeric_limits<int>::max()) ];
        }
      private:
        boost::spirit::qi::rule<It, int()> start;
    };
    
    template <typename Int>
    void test(Int value, char const* logical) {
        MyInt<std::string::const_iterator> p;
    
        std::string const input = std::to_string(value);
        std::cout << " ---------------- Testing '" << input << "' (" << logical << ")\n";
    
        auto f = input.begin(), l = input.end();
        int parsed;
        if (parse(f, l, p, parsed)) {
            std::cout << "Parse success: " << parsed << "\n";
        } else {
            std::cout << "Parse failed\n";
        }
    
        if (f!=l) {
            std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
        }
    }
    
    int main() {
        unsigned maxint = std::numeric_limits<int>::max();
    
        MyInt<std::string::const_iterator> p;
    
        test(maxint  , "maxint");
        test(maxint-1, "maxint-1");
        test(maxint+1, "maxint+1");
        test(0       , "0");
        test(-1      , "-1");
    }
    

    Prints

     ---------------- Testing '2147483647' (maxint)
    Parse success: 2147483647
     ---------------- Testing '2147483646' (maxint-1)
    Parse success: 2147483646
     ---------------- Testing '2147483648' (maxint+1)
    Parse failed
    Remaining unparsed: '2147483648'
     ---------------- Testing '0' (0)
    Parse success: 0
     ---------------- Testing '-1' (-1)
    Parse failed
    Remaining unparsed: '-1'