Closed koshell closed 2 months ago
Does the bool
function return impl Parser<...>
or impl Parser<...> + Clone
?
Does the
bool
function returnimpl Parser<...>
orimpl Parser<...> + Clone
?
... That is a good point, currently its signature is fn bool<'t>() -> impl Parser<'t, &'t str, TokenSpan<'t>>
(copied more or less verbatim from some of them doc). I had kind of forgotten that I'm passing around Traits and not Types. I'll try adding + Clone
and see if that resolves it.
Yep, instantly solved. Confusing error message had short-circuited my brain and I had forgotten to think about the traits I'm passing around.
I'll make some kind of wrapper struct so I can return a concrete type and hopefully get more helpful errors next time. Thanks for the help @wackbyte.
I've been wondering for a while whether Parser
should implicitly have Clone
as a supertrait. Technically it's unnecessary and a greater restriction placed upon the user, but in practice it's probably a usability win in 99% of cases: you're perhaps the dozenth person I've seen with a similar issue.
I also can't really see a use-case for a !Clone
parser either: it would need to be non-recursive and also have a reason to consume itself, which no parser method requires anyway.
I'm trying to build a lexer for Lua. I'm having some very confusing issues dealing with recursive parsers. Currently I'm trying to implement this (ebnf):
The tokens that don't require recursion appear to work fine. However when implementing recursion for
unop exp
I keep getting a very confusing error. Confusingly the error happens even when I'm not actually using the parser recursively. (Struct and function definitions at the end.)This is the code (I'm not using
recursive()
so I could isolate the error):The error message (it's a lot)
```text error[E0277]: the trait bound `chumsky::combinator::MapI've been having some difficulty working out what is causing this issue. There are a lot of opaque types and closures which make the type signature a mess. My thoughts:
Clone
and isn't getting it.Clone
if their captures areClone
.Clone
.With that in mind I'm wondering if it's one of the intermediate types that isn't
Clone
. Specifically I noticed MapExtra (used inParser.map_with(f: F)
) isn'tClone
. Could that be the issues? I didn't think it was capturingMapExtra
since it's passed as a variable to the closure, but this isn't an area of Rust I'm terribly familiar with.Wrapping the whole thing in
Rc::new
does solve the issue:I'll use this as a workaround for now while I build up the rest of the tokens. Please let me know if there is a more idiomatic way to resolve this.
Struct and function definitions:
Token
```rust #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum Token<'t> { Boolean(bool), // ... snip ... Ellipsis, Nil, } impl<'t> Token<'t> { pub(crate) const fn with_span(self, span: SimpleSpan) -> TokenSpan<'t> { TokenSpan::from(self, span) } } ```TokenSpan
```rust #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) struct TokenSpan<'t>(Token<'t>, SimpleSpan); impl<'t> TokenSpan<'t> { pub fn to_vec(self) -> Vecbool()
```rust fn bool<'t>() -> impl Parser<'t, &'t str, TokenSpan<'t>> { choice(( text::keyword("true").map_with(|_, e| Token::Boolean(true).with_span(e.span())), text::keyword("false").map_with(|_, e| Token::Boolean(false).with_span(e.span())), )) } ```