Here's your rule:
qi::rule<char const*> r =
qi::int_ [phoenix::ref(p) = qi::_1]
>> (qi::eps(phoenix::ref(p) == 0)
>> qi::char_('a') | qi::char_('b'))
That to me says: accept '0a' or anything that ends with 'b'. That matches the results you get in your code snippet.
I confess I don't entirely understand your question, but if you are trying to get a kind of 'exclusive or' thing happening (as indicated by the comments in your code snippet), then this rule is incomplete. The workaround (actually more of a 'fix' than a 'workaround') you presented in your comment is one solution, though you don't need the qi::lazy
as the phoenix-based Qi locals are already lazy, but you are on the right track. Here's another (more readable?) solution.
qi::rule<char const*> r =
qi::int_ [phoenix::ref(p) = qi::_1]
>> ((qi::eps(phoenix::ref(p) == 0) >> qi::char_('a')) |
(qi::eps(phoenix::ref(p) == 1) >> qi::char_('b')))
;
If you prefer to use the locals<> you added in your comment, that's fine too, but using the reference to p
adds less overhead to the code, as long as you remember not to set p
anywhere else in your grammar, and you don't end up building a grammar that recurses that rule :)