Any chance this could be subdivided further to implement only one grammar rule or the like? It'd make it much easier to inspect the test quality with smaller increments like that.
We tend not to use 'const' on locals, and maybe especially not on parameters (since it's even more readily confused with const-ref on parameters).
This whole thing is alphabetic except for 'p' - maybe put it in order?
Also - maybe use a const char* array indexed on C - 'a'? Not necessary by any means, though.
Perhaps the recursion system could be a scoped device, making it easier to add/less error-prone in case of early returns, etc?
Recurse R(Error, RecursionLimit); // or just take *this and befriend for access to Error and RecursionLimit if (!R) return; // Recurse's dtor decrements the RecursionLimit)
Could this be cut down further to be paths OR named types, rather than both? (I know this seems fussy/like a pain & I'm sorry about that - but if it gets down to the smallest thing possible (like adding only one named type and associated tests) I'm hoping it'll be super easy to review and verify the tests/understand how the grammar is implemented, etc - as it stands currently it does take me a while to understand each test case, which set of grammar rules are being tested relative to which different rules are being implemented in the patch, etc)
I reduced the changes further still. To introduce further path productions I need types, and the one already implemented type is a named type, i.e., a path. Grammar limits how much I can break it down, but I will see what I can do.
Do these benefit from being inside two namespaces? I think it'd be great if features were tested as much in isolation as possible, with maybe a single test demonstrating that a feature works in a particular context (which is really testing the outer production - and should used the simplest instance of the inner production as possible).
There's also a rather large and, so far as I can tell, arbitrary, disambiguator ('s21hi0yVfW1J') - is there a particular reason for that being present, and having such a long/complicated value?
ie, maybe these tests could be:
_RNCC5crate0 _RNCC5crates_0 _RNCNCC5crates_00 _RNCNCC5crates_01g
& I'm still thinking maybe some kind of comment would be useful to describe these things, though I'm not sure exactly what.
_R N [ C [ C 5crate ] 0 ] _R N [ C [ C 5crate ] [ s _0 ] ] _R N [ C [ N [ C [ C 5crate ] [ s _0 ] ] ] 0 ]
In any case - could you simplify down the test cases to make them as narrow and legible/obvious as possible? Maybe add some comments about the invalid/mangled cases - where the invalidity is interesting, for instance? But hopefully if they're simplified way down, the invalidity will be more clear/obvious?
Simplify test cases
I used rustc to generate the test cases previously. The extra nesting is necessary at language level. The long disambiguator s21hi0yVfW1J is a crate hash. Together with a crate name it forms a unique global identifier of the crate (c++filt shows / omits those hashes output based on -i flag, and I would like to implement something similar later on).
Neither of those aspect is strictly necessary for testing, so I reduced the test cases, but they no longer correspond to valid Rust programs.
Looks great - thanks for sticking with me/helping make this easier for me to follow.
Might be worth consistently using certain easy to identify identifiers? (I at least find it easier to understand the tests when the identifiers are readily.. identifiable - 'crate' is easy to spot in the other examples, for instance - but in an example with single letter identifiers like this ('a' and 'c') can make it a bit harder to read the example - knowing where the user-provided names start/end, which parts aren't from the user identifier)
(similarly below in the invalid namespace)
I guess in the first few examples the manglings were short/simple enough for me to figure out which component was from what - but as the examples get more complicated it's a bit harder to follow/understand and maybe clearer/long/obvious names would make it a bit easier.