You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Mixing operator >> and > considered harmful on the semantics of the combined parser tree #60
Historically, people believed >> and > are perfectly equivalent in parser's semantics except that > wraps the rhs with expect directive. People believed that ((a > b) >> c) and (a > (b >> c)) are somehow interchangeable and has no observable difference in parser semantics. This is NOT true in current codebase, and was NEVER true in the whole history of Spirit.X3.
During the implementation of boostorg/spirit_x4#50, I found that some parser combinations yield significant difference on how the contents of the exposed container variable is preserved. I then realized that the difference comes from the difference of ((a b) c) and (a (b c)).
((a b) c) means: if (a b) succeeded, parse c. (a (b c)) means: if a succeeded, parse (b c).
These are definitely not the same and can introduce semantically different parser tree. The alternative parser was one notable example where it produced inconsistent "held" value on above two variants.
At the time of implementing boostorg/spirit_x4#64, I modified the container handling to not expose the observable difference to the library user. In other words, I ignored the semantic difference and made the implementation details more robust so that it crushes the underlying semantic difference.
As a side note, the current operator< has a minor problem where it cannot be the first entity of a combined parser, because there's nothing to chain on the left hand side of the first item (we always needed to use x4::expect[p] in this case).
I think we should reconsider the chained binary expression and instead introduce some unary operator such as ++parser.
The actual parse tree is now (a b c) in both (a >> b) >> c and a >> (b >> c) thanks to #108.
However, we still need a better interface so that modern IDEs and linters (clang-tidy) won't complain about "a > b > c". I still think the best solution seems to be the introduction of new unary operator++.
I'm quite confident now that unary operator++ is the "best" solution because if we try to solve it using a binary operator, the only technically feasible solution is to use the binary operator that has the exactly equal precedence with operator<<, that is only operator>>. It is obvious that operator>> is NEVER going to be a good API candidate as it's super disgusting to see a code like a << b >> c or a >> b << c.
Activity
saki7 commentedon Sep 13, 2026
operator++looks like a very good candidate but we might also want to use that forx4::force_attribute(p), see #100saki7 commentedon Oct 8, 2026
The actual parse tree is now
(a b c)in both(a >> b) >> canda >> (b >> c)thanks to #108.However, we still need a better interface so that modern IDEs and linters (clang-tidy) won't complain about "a > b > c". I still think the best solution seems to be the introduction of new unary
operator++.I'm quite confident now that unary
operator++is the "best" solution because if we try to solve it using a binary operator, the only technically feasible solution is to use the binary operator that has the exactly equal precedence withoperator<<, that is onlyoperator>>. It is obvious thatoperator>>is NEVER going to be a good API candidate as it's super disgusting to see a code likea << b >> cora >> b << c.