PPCompositeParser has its limits. I hate the instance variable mess, but it kind of makes it convenient to refer to other productions.
In Helvetia there is a different implementation of PPCompositeParser that works with the same grammar source but compiles variable accesses to use a dictionary instead. This then scales to an almost infinite number of productions. I agree that introducing the Helvetia dependendency is not feasible though.
I wonder if we could use some other trick that wouldn't require a custom compiler and that would work across platforms?
Another way would be to access some of the parser via method calls instead of accessing the instVar parsers.
That is a possiblity, if they don't depend on each other circularly and if you don't mind the object duplication.
Also you can build your productions more imperatively (like in many examples and the tests you see floating around) instead of purely declaratively as it is mostly done with PPCompositeParser.
So does anybody has some experience in how to structure parsers?
Typically grammars are quite clustered and have complex leaf nodes (the tokens in general, string and number literals, comments, etc.) that can be factored out.
Cheers, Lukas