Exagon
Exagon

Reputation: 5088

Parsing a comma separated 0 or more list using boost spirit x3

I often need to parse a comma separated 0 or more list in boost spirit x3. I know the %-operator which parses a 1 or more list into an std::vector. When I need a 0 or more list I currently do it like this -(element_parser % separator), which does what I want, but parses into a boost::optional<std::vector>, which is not quite the thing I am after. So how can I make a parser, which parses a comma separated 0 or more list into a plain std::vector using boost spirit x3.

Upvotes: 3

Views: 815

Answers (1)

Travis Gockel
Travis Gockel

Reputation: 27633

Perhaps I'm missing something, but using - works as expected for me:

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

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

namespace x3 = boost::spirit::x3;

const x3::rule<class number_list_tag, std::vector<int>> integer_list = "integer_list";
const auto integer_list_def = -(x3::int_ % ',');
BOOST_SPIRIT_DEFINE(integer_list);

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec)
{
    bool first = true;
    os << '[';
    for (const T& x : vec)
    {
        if (first)
            first = false;
        else
            os << ", ";

        os << x;
    }
    os << ']';
    return os;
}

std::vector<int> parse(const std::string& src)
{
    std::vector<int> result;
    auto iter = src.begin();
    bool success = x3::phrase_parse(iter, src.end(), integer_list, x3::space, result);
    if (!success || iter != src.end())
        throw std::runtime_error("Failed to parse");
    else
        return result;
}

int main()
{
    std::cout << "\"\":\t" << parse("") << std::endl;
    std::cout << "\"5\":\t" << parse("5") << std::endl;
    std::cout << "\"1, 2, 3\":\t" << parse("1, 2, 3") << std::endl;
}

Output is:

"":     []
"5":    [5]
"1, 2, 3":      [1, 2, 3]

Upvotes: 4

Related Questions