Ender
Ender

Reputation: 1778

Using Spirit x3, how to control which parser is called on each different input?

I'm working with boost spirit x3 and am unclear on one point. I have a file that has very different and repetitive lines. The first few lines may be comments. The next 1000 lines may be coordinates, the next thousand lines may be a list of int's, etc...

My question is how to recognize the line and know which parser to use for that line. E.g., here are two parser functions ....

template <typename Iterator>
bool parse_ints(Iterator first, Iterator last, std::vector<int>& v)
{
    using x3::int_;
    using x3::phrase_parse;
    using x3::_attr;   
    using ascii::space;

    auto push_back = [&](auto& ctx){ v.push_back(_attr(ctx)); };

    bool r = phrase_parse(first, last,
        (
            int_[push_back]
                >> *(',' >> int_[push_back])
        )
        ,
        space);

    if (first != last) 
        return false;
    return r;
}

template <typename Iterator>
bool parse_doubles(Iterator first, Iterator last, std::vector<double>& v)
{
    using x3::double_;
    using x3::phrase_parse;
    using x3::_attr;
    using ascii::space;

    auto push_back = [&](auto& ctx){ v.push_back(_attr(ctx)); };

    bool r = phrase_parse(first, last,
        (
            double_[push_back]
                >> *(',' >> double_[push_back])
        )
        ,
        space);

    if (first != last) // fail if we did not get a full match
        return false;
    return r;
}

And here is how the input comes in (istringstream is hundreds of MB's in size). And within the while loop is how I'm wondering to know which parser to call.

int main()
{
    istringstream str(my.data());

    while (getline(str, line)) {
        // based on the format of 'line', how does one know which 
        // parser to call?
    }
}

Upvotes: 1

Views: 97

Answers (1)

sehe
sehe

Reputation: 392833

Your grammar could describe the whole input. So you could say

auto input = *headerComment 
          >> points 
          >> edges;

Where you could simply define

auto headerComment = '#' >> *(char_ - eol) >> eol;

And e.g.

auto points = skip(blank) [ 
     *(point >> eol)
   ];

auto edges = skip(blank) [ 
     *(edge >> eol)
   ];

point = int_ >> int_ >> int_; // assuming x y z
edge  = int_ >> int_;         // assuming from to

This assumes that the input format is unambiguous. I.e. it wouldn't work if points were x y only because it's not distinguishable from an edge then.

Upvotes: 1

Related Questions