zesterer / chumsky

Write expressive, high-performance parsers with ease.
https://crates.io/crates/chumsky
MIT License
3.61k stars 155 forks source link

Allow `nested_in` to accept a parser that emits a different type of tokens #689

Open TheOnlyTails opened 1 week ago

TheOnlyTails commented 1 week ago

I have this use case, where expr is a parser with (Token, Span) as the input, and the surrounding function returns a parser that takes in `(StringToken, Span)

expr.nested_in(select_ref! {
    StringToken::Interpolation(inner) = e => {
        inner.as_slice().spanned(SimpleSpan::to_end(&e.span()))
    },
});

However, this errors because nested_in expects the parser being passed in to both accept and return the same type, which clashes here.

zesterer commented 1 week ago

Hmm. I can see this use-case, certainly.

TheOnlyTails commented 1 week ago

I think it's just a matter of changing around the type params to allow for it?

fn nested_in<IB: Input<'a>, EB: ParserExtra<'a, IB>, B: Parser<'a, IB, I, EB>>(
    self,
    other: B,
) -> NestedIn<Self, B, O, E>
where
    Self: Sized,
{
    NestedIn {
        parser_a: self,
        parser_b: other,
        phantom: EmptyPhantom::new(),
    }
}
zesterer commented 1 week ago

I've had a go at implementing this, and it does seem to work, but it comes with a constraint: specifically, that the State, Context, and Error types need to match between the inner and outer inputs.

I've pushed up a commit on main that makes this change. Could you give it a go to see if it does what you're looking for?

TheOnlyTails commented 1 week ago

Updated, this seems to be related but I'm not sure how (maybe the same change needs to be made for select and select_ref?)

let interpolation= expr
    .nested_in::<_, StringInput, StringExtra>(select_ref! {
        StringToken::Interpolation(inner) = e => {
            inner.as_slice().spanned(SimpleSpan::to_end(&e.span()))
        },
    })
    .map(|t| StringPart::InterpolatedExpr(t.into()));
the method `map` exists for struct `NestedIn<P, SelectRef<{closure@lib.rs:2809:13}, SpannedInput<..., ..., ...>, ..., ...>, ..., ..., ..., ...>`, but its trait bounds were not satisfied
zesterer commented 1 week ago

There's not enough information there to be useful. My hunch is that one of the constraints I listed is being violated somehow. If you have a small failing example I can run, that would be useful too.

TheOnlyTails commented 1 week ago

Can we discuss on Discord or something? I don't want to clog up the issue tracker with debugging.

zesterer commented 1 week ago

Sure. I'm active on the Rust Community Discord, in the #langdev channel.

To anybody else reading this, any important information will be fed back here.