Zach Laine wrote: ...
I'm calling my proposal Boost.Parser, and it follows many of the conventions of Boost.Spirit 2 and X3, such as the operators used for overloading, the names of many parsers and directives, etc. It requires C++17 or later. ...
The Github page is here: https://github.com/tzlaine/parser The online docs are here: https://tzlaine.github.io/parser
Some observations: I understand, in principle, the motivation behind asserting at runtime instead of failing compilation, but I don't think the same argument applies to rejecting *eps parsers. It seems to me that a static assert for any *p or +p where p can match epsilon (can succeed while consuming no input) would be clear enough. (E.g. +-p, *(p | q | eps), *attr(...), +&p, etc.) Interestingly, this would reject **p and +*p, because these parsers can go into an infinite loop. The current behavior is to collapse them into *p, which is useful, but technically wrong. This raises the possibility of, instead of rejecting *p or +p when p can match epsilon, just 'fixing' its behavior so that when p matches epsilon, the outer parser just exits the loop. This will make the current collapsing behavior equivalent to the non-collapsed one. Also, errors should definitely go to std::cerr by default, not std::cout. Errors aren't program output, and routing them to stdout is script-hostile.