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

Boost Spirit X3: skip parser that would do nothing


I'm getting myself familiarized with boost spirit v3. The question I want to ask is how to state the fact that you don't want to use skip parser in any way.

Consider a simple example of parsing comma-separated sequence of integers:

#include <iostream>
#include <string>
#include <vector>

#include <boost/spirit/home/x3.hpp>

int main()
{
    using namespace boost::spirit::x3;

    const std::string input{"2,4,5"};

    const auto parser = int_ % ',';
    std::vector<int> numbers;

    auto start = input.cbegin();
    auto r = phrase_parse(start, input.end(), parser, space, numbers);

    if(r && start == input.cend())
    {
        // success
        for(const auto &item: numbers)
            std::cout << item << std::endl;
        return 0;
    }

    std::cerr << "Input was not parsed successfully" << std::endl;
    return 1;
}

This works totally fine. However, I would like to forbid having spaces in between (i.e. "2, 4,5" should not be parsed well).

I tried using eps as a skip parser in phrase_parse, but as you can guess, the program ended up in the infinite loop because eps matches to an empty string.

Solution I found is to use no_skip directive (https://www.boost.org/doc/libs/1_75_0/libs/spirit/doc/html/spirit/qi/reference/directive/no_skip.html). So the parser now becomes:

const auto parser = no_skip[int_ % ','];

This works fine, but I don't find it to be an elegant solution (especially providing "space" parser in phrase_parse when I want no whitespace skips). Are there no skip parsers that would simply do nothing? Am I missing something?

Thanks for Your time. Looking forward to any replies.


Solution

  • You can use either no_skip[] or lexeme[]. They're almost identical, except for pre-skip (Boost Spirit lexeme vs no_skip).

    Are there no skip parsers that would simply do nothing? Am I missing something?

    A wild guess, but you might be missing the parse API that doesn't accept a skipper in the first place

    Live On Coliru

    #include <iostream>
    #include <iomanip>
    #include <boost/spirit/home/x3.hpp>
    namespace x3 = boost::spirit::x3;
    
    int main() {
        std::string const input{ "2,4,5" };
        auto f = begin(input), l = end(input);
    
        const auto parser = x3::int_ % ',';
        std::vector<int> numbers;
    
        auto r = parse(f, l, parser, numbers);
    
        if (r) {
            // success
            for (const auto& item : numbers)
                std::cout << item << std::endl;
        } else {
            std::cerr << "Input was not parsed successfully" << std::endl;
            return 1;
        }
    
        if (f!=l) {
            std::cout << "Remaining input " << std::quoted(std::string(f,l)) << "\n";
            return 2;
        }
    }
    

    Prints

    2
    4
    5