chumsky icon indicating copy to clipboard operation
chumsky copied to clipboard

Basic implementation of recursive parsers macro

Open zesterer opened this issue 2 months ago • 3 comments

(The use of Unpin is arbitrary, I just wanted some dyn-compatible trait that worked for non-'static lifetimes)

zesterer avatar Nov 02 '25 18:11 zesterer

After having played around with this version a bit, it has the same benefit that the (improved) recursive_n function does, which is "returning" multiple of the parsers, but without the tuple games that you mentioned. So... despite also normally shying away from macros, I think this one would be a great tool. rust-analyzer didn't seem to have any issues with the macro, which is a blessing. It may be worth considering offering the arm without = <expr> (if at all possible), so that the user gets auto-complete while trying to type names. It was the only real advantage I noticed while comparing the two (ignoring that the current impl doesn't allow for declaring parsers! multiple times in the same scope, but that fix is easy).

Neat solution :) Out of curiosity, what is your opinion on removing define and declare from the public API Recursive (either through renaming to _define and declare or deprecating the methods while mentioning the leak?

Zij-IT avatar Nov 03 '25 19:11 Zij-IT

I'm glad you like it, your recursive_n approach inspired me to come up with the drop closure solution.

It may be worth considering offering the arm without = <expr> (if at all possible), so that the user gets auto-complete while trying to type names.

Hmm, what do you mean by this? My editor doesn't have LSP support, so I don't really understand.

My plan is to add some way to include a type hint (like <name> $(: <type>)? = ...).

Out of curiosity, what is your opinion on removing define and declare from the public API Recursive (either through renaming to _define and declare or deprecating the methods while mentioning the leak?

Very much in favour. I've been of the view for a while that they're a stop-gap, and one that's easy to accidentally misuse. I think deprecation is fine for the time being (leaks aren't ideal, but they're not really an actual problem for the most-part), at least until a 1.0 release finally comes around.

zesterer avatar Nov 03 '25 19:11 zesterer

Hmm, what do you mean by this? My editor doesn't have LSP support, so I don't really understand.

Ah. I would not survive programming Rust without my LSP, props to you. So, I mean:

// With `recursive_n` you effectively have to forward declare the parsers
recursive_n(|(expr, statement)|
    let expr = expr_atom(expr.clone(), , sta▍)
})

// With `parsers!` you are encouraged to finish the definition before moving to the next time
parsers! {
    expr = expr_atom(expr.clone(), sta▍)
}

For this example, we can treat ▍as the cursor position. At this point with recursive_n there is enough information to get auto-complete for statement where as it's not possible to do something similar with parsers! without doing statement = chumsky::prelude::todo() somewhere in the macro. Perhaps just having a way to forward declare like:

parsers! {
    declare: expr, statement;
    /* rest */
}

I don't think it's really a big problem, but just something I noticed :)

Zij-IT avatar Nov 03 '25 20:11 Zij-IT