2

I can't get a modified version of the example provided in boost's documentation to output correctly

Here's the documentation on sequential OR parser: http://www.boost.org/doc/libs/1_56_0/libs/spirit/doc/html/spirit/qi/reference/operator/sequential_or.html

test_parser("123.456", int_ || ('.' >> int_));  // full

I want this expression to populate a vector<int> with 2 entries:

[0] = 123
[1] = 456

Why doesn't this work?

string input("123.456");
vector<int> output;

string::iterator i = input.begin();

parse(i, input.end(), int_ || ('.' >> int_), output);

I have verified parse returns true and i == input.end(). I have also tried different data structures for output including tuples with optionals, and vectors of optionals. And they all produce a single entry containing just 123, never 456.

Niall
  • 30,036
  • 10
  • 99
  • 142
Jimbobot
  • 33
  • 2
  • @Yakk "And they all produce a single entry containing just 123, never 456." Seems pretty clear to me. – Mark Ransom Sep 26 '14 at 19:12
  • 1
    If I'm reading the documentation correctly, `parse` doesn't output to a vector, it outputs to individual variadic parameters. Since you only have one output parameter, you only get one result. – Mark Ransom Sep 26 '14 at 19:17
  • Mark Ransom was right. Providing two ints does output 123 and 456. An std::pair of ints also work. However a tuple, optional> and a vector of optionals, only produces 123. I'd still like to know why though. – Jimbobot Sep 29 '14 at 14:06
  • @Jimbobot it's because of limitations to the attribute compatibility rules/heuristics. This is where Spirit can become quite magical. You get a sense for this over time though. – sehe Sep 29 '14 at 14:09

1 Answers1

1

The || parser will parse into tuple<optional<A>, optional<B> > (for the optimistic scenario). This is never gonna be compatible with your container attribute.

However, it looks like you could use

parse(i, input.end(), -int_ >> -('.' >> int_), output);

That said... if I were secretly Clippy, I might say "it looks like you are trying to parse real numbers.

Consider float_, double_, or the underlying real_parser with perhaps a custom policy. See also:

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    || is a sequential OR parser. Go read the doc in the link i provided. – Jimbobot Sep 29 '14 at 13:47
  • Oops. I think I should know the docs. However, you've got a point I glossed over the fact that you were using `||` instead of `|`. – sehe Sep 29 '14 at 13:55
  • Updated my answer. I''ve also added a link to an answer where I talked about parsing mixed ints/double as you seem to require. – sehe Sep 29 '14 at 14:13
  • "The || parser will parse into tuple, optional > (for the optimistic scenario). This is never gonna be compatible with your container attribute." Why? I don't want to change my expression to make it fit into a tuple of optionals. This is just for my education. I want to know why sequential OR can't take a tuple of optionals even though the docs says it should. – Jimbobot Sep 29 '14 at 14:20
  • 1
    Ah. That way. A. did you confuse Fusion tuples and Boost Tuple? In that case `#include ` could fix you up. B. To learn how it really works you could probably best read into the source code, as the docs do not have the ambition to explain the various trade-offs and interferences with attribute transformations and compatibility rules in that amount of detail. – sehe Sep 29 '14 at 14:27
  • 1
    @Jimbobot I found the time to demo what I meant about using `tuple – sehe Sep 29 '14 at 14:40
  • Thank you so much. #include fixed the issue. It completely makes sense now why i need this include. I would have never figured this out myself. – Jimbobot Sep 29 '14 at 14:55