-
Notifications
You must be signed in to change notification settings - Fork 38
Add a YaccKind::SelfDescribing style.
#491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This allows the yacckind value to be specified within a grammar. When using the `YaccKind::SelfDescribing` style the grammar must start with an initial `%grmtools` section, as documented in the variant. For other `YaccKind` variants the `%grmtools` section is allowed (not required) and the `YaccKind` value given to `YaccGrammar::new` overrides one given in the `%grmtools` section. Fixes softdevteam#349
|
One thing I meant to say is that the parsing code is most likely whitespace sensitive, And would fail with something like Edit: It looks like the only case it wasn't handling correctly was the following which is fixed in 8d9520b |
|
I think we would want the eventual parser to be whitespace insensitive, but it shouldn't be too hard? We just need to define how we want to map the human-writeable text to the internal format. We don't have to make it too "serde like" or even "Rust like". [I'll try to do a proper review of this later today.] |
|
Yeah, I don't think it should be too hard either -- it just isn't how our current Indeed I didn't do much or anything in the way of internal format, the key parsing just writes directly to the Edit (One more thing I recall worth thinking about): nimbleparse currently defaults to Currently this patch errors rather than provide a default
The latter option feels more tolerable to me (I went ahead and pushed an exploratory implementation of that), any opinions? |
…arse. Because of recursive types, this needs to be boxed, and because of box this enum can no longer be `Copy`, so we had to drop the `Copy` trait for `YaccKind` in order for this to work.
|
I've dumped in some detailed, but mostly not deep, comments. One high-level thing that I haven't quite wrapped my head around is how we expect the user to use the |
|
I'm still waking up, I haven't managed to parse your confusion above so I don't quite understand the exact scenario given yet. I definitely agree that the number of "degrees of freedom" in the overriding can be confusing because it can be overridden "bottom up" where the Overall my thoughts have been that the typical user shouldn't need to be aware of the Unfortunately that isn't actually fixed by the patch, because for backwards compatibility it uses My general thinking is that new code should typically use There are a few reasons to want to specify values other than
So, I think from the perspective of a user, That might not answer your specific scenario, I've got to go make some ☕ and read it again. |
That's an interesting idea that hadn't occurred to me. I think I like it. Let me chew on it for a bit. |
I agree with this and I tend to think this should become the default in the next major release i.e. we would no longer force API users to specify |
|
Cool, well I think I've dealt with all the issues that I had brought up after my initial commits, and feel like I'm satisfied with how it has turned out, unless anything comes up in another round of review. |
So after my last comment I got to thinking I'm unsure how I should take this, I initially got to thinking this should mean the next time we consider making a breaking change we should make the But I later considered that I could take it to mean that e.g. instead of adding a new variant, we could do much the same, I do think skipping the |
|
Long and short: whereas in |
|
Ahh yeah I think I see, That isn't too hard of a task (e.g. the builder code already works with So I think the simplest change is for that is turning a Builder |
|
I went ahead and made that change relaxing the builder requirements. |
I must admit I haven't quite managed to visualise what this would do/look like in my head. |
I think was most likely wrong that it would be an option, but Basically we just take the 3 methods new, new_with_storaget, new_from... And change all the The reason it doesn't seem like a viable approach is because we would have to pick between the top-down and the bottom-up overriding, and it seems like we need both for different use cases. I suppose that the way it would work is if we did Edit: The mapping between the It does allow us to get rid of the |
|
I think I'll take a bit of time to make a separate exploratory PR based on the edits in above comment, Edit: But just dipping my toes in, it is sufficient to say it is way more involved than this patch |
| let yacc_y_path = PathBuf::from(&matches.free[1]); | ||
| let yacc_src = read_file(&yacc_y_path); | ||
| let ast_validation = ASTWithValidityInfo::new(yacckind, &yacc_src); | ||
| let ast_validation = ASTWithValidityInfo::new(yacckind.clone(), &yacc_src); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, working on the exploratory PR for the other approach, it became apparent that there is actually an issue here,
It's actually quite a major issue!
Basically the clone calls are keeping around a YaccKind::SelfDescribing, and because YaccParser.yacc_kind isn't pub, it never gets read back out after parser initialization. The testsuite isn't actually picking it up yet,
We don't seem to have tests for nimbleparse, and I haven't implemented the cttests since modifying CTParserBuilder yet.
After adding in the %grmtools {yacckind Grmtools} section to calc.y
echo -n "1+1" | target/debug/nimbleparse lrpar/examples/calc_actions/src/calc.{l,y} -
thread 'main' panicked at cfgrammar/src/lib/yacc/grammar.rs:154:17:
not implemented: Concrete YaccKind must be known by this point
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
So, that is definitely a hurdle that this PR needs to overcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fixed in 98b6ee2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cttests added, and fixed similarly in 23232f8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point about nimbleparse. We could at least test it minimally in .buildbot.sh?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want to pub(crate) the yacc_kind: YaccKind field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a pub(crate) fn yacc_kind(&self) -> &YaccKind be okay?
We need it to escape, along side this YaccParser::ast() function which is pub(crate)?
Edit: Another option might be having something like that ast function that returns return a (YaccKind, GrammarAST) tuple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went ahead and tried that later option plus renaming the ast function which seemed like the cleanest to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the record, I had a crisis of conscience in regard to that, e.g. whether what I did was right vs adding a yacc_kind field to GrammarAST. So I also tried adding it to GrammarAST, but the takeaway was that currently GrammarAST is completely devoid of anything related syntax. You can even construct one by hand with no syntax at all. Where YaccKind is kind of YaccParser specific thing. So my takeaway from that experiment was that I still think prefer that finish function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a pub(crate) fn yacc_kind(&self) -> &YaccKind be okay?
Yep!
|
Here is the initial results of that other exploratory branch, But given that it is a much more breaking change, I wanted to post it for feedback on whether you think that approach is beneficial enough to justify the breakage, before actually going through the effort of making it fully functional. https://github.com/ratmice/grmtools/tree/grmtools_directive_2 |
|
I think the key bit is: pub enum YaccKindResolver {
/// Uses exactly the given yacc kind
Exactly(YaccKind),
/// Attempt to read yacc kind from the `%grmtools` section,
/// otherwise falls back to using the given yacc kind.
Fallback(YaccKind),
/// Attempt to read the yacc kind from the `%grmtools` section
/// otherwise throws a `MissingYaccKind` error.
SelfDescribing,
}I can definitely bikeshed the names, but the intent is fairly clear. I'd perhaps call them something like: enum YaccKindResolver {
/// The user can specify `%grmtools` in their grammar but it differs from this `YaccKind`, it's an error
Force(YaccKind),
/// Use `YaccKind` if the user doesn't specify `%grmtools` in their grammar
Default(YaccKind),
/// The user must specify `%grmtools` in their grammars or we throw an error
NoDefault
}but that's a relatively minor tweak. Obvious question: what would the default be? |
Well, I've used i.e. nimbleparse and ctparserbuilder currently have different defaults in this patch and that other branch. For nimbleparse though I just did that because that is what is most compatible with the current behavior. |
I am inclined to agree. Yes, it's a breaking change, but it's a pretty sensible one. Even better, we can presumably make it so that lrpar users specifying Go ahead! |
|
Sounds good, I'll go ahead and close this PR now then and open a new one once I've finished merging all the parsing code from this one, and updated it based on the things we've discussed. |
I belive this should implement what we discussed in #349 for lrpar (It doesn't try to tackle lrlex yet)
I'm still not certain I like the syntax but it seemed not worth worrying about until I got something working at least.
This allows the yacckind value to be specified within a grammar. When using the
YaccKind::SelfDescribingstyle the grammar must start with an initial%grmtoolssection, as documented in the variant.For other
YaccKindvariants the%grmtoolssection is allowed (not required) and theYaccKindvalue given toYaccGrammar::newoverrides one given in the%grmtoolssection.Fixes #349