I have been experimenting a bit with parser-combinators (something which seems to be pretty common here ). I want to avoid using macros except as syntactic sugar, and so far it seems to be possible to write pretty clean code for a parser-combinator, as long as you are willing to put up with lots of generics for some operations (basic parser-type is generic over type it parses, contained success state as well as error state).
I have now reached a point where I feel that I need to get some input on this subject. I have some code working, and it looks promising, but I cannot decide on what approach to take since I have tried multiple variants (stacking structs, passing monad-state along manually as well as boxed closures). So I decided to try to sum up my dilemma in a blog-post:
What really differs between the two approaches listed is how it behaves when you parse things with it, as well as the function signatures of the parsers themselves. If you use the macro-sugar I have provided the syntax inside the parser itself barely differs.
I am not sure if I should just go with the better performing option or the more “true” approach which is boxing closures (though just the fact that it is boxing stuff makes it less than appealing in some ways). I am also guessing that additions to Rust itself could also improve the closure-using option enough so that it performs better, though that would require that a few RFCs gets approved and implemented as well as backwards-incompatible API-changes to the parser-combinator.