Skip to content

Lrpar codegen - #655

Closed
ratmice wants to merge 3 commits into
softdevteam:masterfrom
ratmice:lrpar_codegen
Closed

Lrpar codegen#655
ratmice wants to merge 3 commits into
softdevteam:masterfrom
ratmice:lrpar_codegen

Conversation

@ratmice

@ratmice ratmice commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Here is an attempt at pulling a codegen module out of lrpar, it migrates the CTParserBuilder to use it, and passes
the testsuite. I haven't gone over this with a fine toothed comb, but there have been some obscure timing related problems I have introduced but noticed, but didn't cause any testsuite failures.

(Like calling check_unused_header_keys() too early before the callback.

I wasn't able to do this patch in a way that was even remotely incremental because of ownership issues. Nor really figure out a way to do it in a way that didn't require making slight changes to things as they moved over (mostly changing references to self, removing calls unwrap()).

There are 3 passes to this and a 4th structure ParserBuildEnvArgs:

  1. ParserSrcEnv
  2. ParserBuildEnv
  3. ParserCodeGen

The general idea is:

ParserSrcEnv: source, source path, diagnostics generator, header collection which contains the default values for the %grmtools section.
ParserBuildEnvArgs, these are essentially the builder arguments including the essential Option<> types. It's just a minimal builder.
ParserBuildEnv: This structure contains fields derived from the BuildEnvArgs and also the inner types from options in BuildEnvArgs. By derived fields I mean things like ASTWithValidationInfo
ParserCodegen: This one contains a YaccGrammar, StateTable, and StateGraph. In order to generate code, though it still needs the SrcEnv and the BuildEnv.

Currently the BuildEnv takes ownership of the BuildEnvArgs, it was easiest this way because the rebuild_cache code expects Options it may be we should drop BuildEnvArgs from BuildEnv.

But generally the idea (in a pseudo functional syntax) is something to the effect of:

(SrcEnv?, BuildEnvArgs) -> BuildEnv? -> CodeGen::generate(&build_env, &src_env)?;

There is a pretty high probability that this contains some code duplicated from CTParserBuilder, which
didn't go fully unused in CTParserBuilder, given that the diff +/- is only a few hundred lines, I don't expect an enormous amount. But perhaps if it is really used in both places like fn indent appears to be we can use ctbuilder::indent instead.
I'll try and read through it in this regard tomorrow.

ratmice added 3 commits August 4, 2026 16:06
This had to introduce a call to `parser_builder.from_ast.clone()`
to work.
When building a parser from an ast rather than from a source string,
we would clone the AST. Instead this patch takes it via a reference.
@ratmice

ratmice commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

I forgot to mention that there is one aspect of rebuild_cache I couldn't save is the whole

let Self{
   // destructure all the fields to ensure the cache is complete.
} = self;

I'm pretty sad to see this go, as it's saved me almost every time I've added a field which would affect the cache.
I'm at a loss though for how we could manage to salvage that.

// change for reasons beyond lrpar's control. If it does change, that means that the lexer
// and lrpar would get out of sync, so we have to play it safe and regenerate in such
// cases.
let cache_str = code_gen.cache_string(&src_env, &build_env);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there are a couple of places where we break the general abstraction, that
the code generator is just doing code generation, like here where we peek
at the cache string, to check if the existing code contains it.

)
.into());
}
src_env.check_unused_header_keys()?;

@ratmice ratmice Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is another place where we kind of break the abstraction by looking at the header for any unused keys, the other places src_env produces errors (when producing the build_env would be too early for this error, because of the inspect_rt callback above.

This is kind of undocumented API though, currently mostly used by the test_files key of the grmtools section. The callback needs to mark the test_files key as used.

@ratmice

ratmice commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

One last thing, is that now that I have a blueprint for how this goes, perhaps I could figure out how to do an incremental transition, which could lead to a more reviewable patch (I do have some ideas how it would go).

Edit: I feel like it's probably worth trying, and I'm kind of stuck inside until the smoke blows away, so I'll probably give this a shot.

@ratmice

ratmice commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

I have managed to get a good start at splitting this patch up, so I'm going to close this in favor of a future PR.
I don't intend to do anything differently except hopefully make it easier to review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants