Code Monkey home page Code Monkey logo

Comments (6)

Timmmm avatar Timmmm commented on June 12, 2024 1

Ah that still didn't quite compile, but one of the compilation errors was complaining about C: Char, saying I should use where instead. Since I don't care about being that generic I just changed all the Cs to char and it worked!

from chumsky.

zesterer avatar zesterer commented on June 12, 2024

As of the (alpha) 1.0 releases, all spans are byte offsets. In 0.9 you can use byte offsets too by constructing Stream manually.

from chumsky.

Timmmm avatar Timmmm commented on June 12, 2024

Aha, I upgraded to 1.0.0-alpha4 and that did the trick! If it helps you write the documentation, here were the things I had to change:

  • pub type Span = std::ops::Range<usize>; -> pub type Span = SimpleSpan<usize>;
  • .chain() -> .then()
  • .collect::<String>().map( -> .map_slice(
  • .labelled(..) -> Dunno, I just removed these for now... :-|
  • skip_then_retry_until([]) -> skip_then_retry_until(any().ignored(), end())
  • .parse_recovery(s) -> .parse(s)
  • take_until(just("*/")) -> any().and_is(just("*/").not()).repeated()).then(just("*/")) (feels like there's probably a better way here?)

I also couldn't figure out why this slightly modified ident() function doesn't work (it's supposed to allow ~ as a special identifier):

#[must_use]
pub fn ident<'a, I: ValueInput<'a> + StrInput<'a, C>, C: Char, E: ParserExtra<'a, I>>(
) -> impl Parser<'a, I, &'a C::Str, E> + Copy + Clone {
    any()
        // Use try_map over filter to get a better error on failure
        .try_map(|c: C, span| {
            if c.to_char().is_ascii_alphabetic() || c.to_char() == '_' || c.to_char() == '?' {
                Ok(c)
            } else {
                Err(Error::expected_found([], Some(MaybeRef::Val(c)), span))
            }
        })
        .then(
            any()
                // This error never appears due to `repeated` so can use `filter`
                .filter(|c: &C| c.to_char().is_ascii_alphanumeric() || c.to_char() == '_' || c.to_char() == '?' || c.to_char() == '\'')
                .repeated(),
        )
        .or(just('~'))
        .slice()
}

The error messages are hard! Documentation is generally excellent though, so it wasn't too bad an upgrade. Thanks for the great library! Don't think I'd go back to Nom or Tree Sitter.

from chumsky.

zesterer avatar zesterer commented on June 12, 2024

here were the things I had to change:

Thanks! That's going to be quite useful when I finally get round to writing migration docs from 0.9 to 1.0.

* `.labelled(..)` -> Dunno, I just removed these for now... :-|

labelled still exists, but is behind the label feature flag for now.

* `take_until(just("*/"))` -> `any().and_is(just("*/").not()).repeated()).then(just("*/"))` (feels like there's probably a better way here?)

This is the current recommended approach, yes. It's unfortunate that it's more noisy, but and_is and not in combination are much more flexible than take_until (which ended up often being only a half solution for many problems). At some point I might try to take common patterns like this and put them into some sort of escaped combinator that makes this sort of thing a bit easier.

I also couldn't figure out why this slightly modified ident() function doesn't work (it's supposed to allow ~ as a special identifier):

When you say that it doesn't work, what do you mean? Do you get compiler errors, or does it not parse a certain input correctly?

The error messages are hard! Documentation is generally excellent though, so it wasn't too bad an upgrade. Thanks for the great library! Don't think I'd go back to Nom or Tree Sitter.

Thanks for your kind words! I definitely agree with regard to error messages: I'd really like to see Rust get better at these sort of diagnostics. I'm firmly of the opinion that it's possible to produce better results, but unfortunately I don't have enough knowledge of rustc to make the changes myself.

from chumsky.

Timmmm avatar Timmmm commented on June 12, 2024

labelled still exists, but is behind the label feature flag for now.

Aha, thanks!

When you say that it doesn't work, what do you mean?

I get this compilation error:

error[E0277]: the trait bound `Just<char, _, _>: chumsky::private::ParserSealed<'_, _, (C, ()), _>` is not satisfied
    --> sail_parser\src\lib.rs:310:13
     |
310  |         .or(just('~'))
     |          -- ^^^^^^^^^ the trait `chumsky::private::ParserSealed<'_, _, (C, ()), _>` is not implemented for `Just<char, _, _>`
     |          |
     |          required by a bound introduced by this call
     |
     = help: the trait `chumsky::private::ParserSealed<'a, I, T, E>` is implemented for `Just<T, I, E>`
     = note: required for `Just<char, _, _>` to implement `Parser<'_, _, (C, ()), _>`
note: required by a bound in `or`
    --> C:\Users\Tim\.cargo\registry\src\index.crates.io-6f17d22bba15001f\chumsky-1.0.0-alpha.4\src\lib.rs:1190:12
     |
1187 |     fn or<B>(self, other: B) -> Or<Self, B>
     |        -- required by a bound in this associated function
...
1190 |         B: Parser<'a, I, O, E>,
     |            ^^^^^^^^^^^^^^^^^^^ required by this bound in `Parser::or`

error[E0277]: the trait bound `Just<char, _, _>: chumsky::private::ParserSealed<'_, _, (C, ()), _>` is not satisfied
   --> sail_parser\src\lib.rs:311:10
    |
311 |         .slice()
    |          ^^^^^ the trait `chumsky::private::ParserSealed<'_, _, (C, ()), _>` is not implemented for `Just<char, _, _>`
    |
    = help: the trait `chumsky::private::ParserSealed<'a, I, T, E>` is implemented for `Just<T, I, E>`
    = note: required for `Just<char, _, _>` to implement `Parser<'_, _, (C, ()), _>`
    = note: required for `Or<Then<TryMap<chumsky::primitive::Any<_, _>, C, [closure@sail_parser\src\lib.rs:297:18: 297:30]>, Repeated<chumsky::combinator::Filter<chumsky::primitive::Any<_, _>, [closure@sail_parser\src\lib.rs:307:25: 307:32]>, C, _, _>, C, (), _>, Just<char, _, _>>` to implement `chumsky::private::ParserSealed<'_, _, (C, ()), _>`
note: required by a bound in `chumsky::Parser::slice`
   --> C:\Users\Tim\.cargo\registry\src\index.crates.io-6f17d22bba15001f\chumsky-1.0.0-alpha.4\src\lib.rs:303:5
    |
303 |     ParserSealed<'a, I, O, E>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Parser::slice`
...
416 |     fn slice(self) -> Slice<Self, O>
    |        ----- required by a bound in this associated function

error[E0277]: the trait bound `Just<char, _, _>: chumsky::private::ParserSealed<'_, I, (C, ()), E>` is not satisfied
   --> sail_parser\src\lib.rs:294:6
    |
294 | ) -> impl Parser<'a, I, &'a C::Str, E> + Copy + Clone {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `chumsky::private::ParserSealed<'_, I, (C, ()), E>` is not implemented for `Just<char, _, _>`
    |
    = help: the trait `chumsky::private::ParserSealed<'a, I, T, E>` is implemented for `Just<T, I, E>`
    = note: required for `Just<char, _, _>` to implement `Parser<'_, I, (C, ()), E>`
    = note: required for `Or<Then<TryMap<chumsky::primitive::Any<I, E>, C, [closure@sail_parser\src\lib.rs:297:18: 297:30]>, Repeated<chumsky::combinator::Filter<chumsky::primitive::Any<I, E>, [closure@sail_parser\src\lib.rs:307:25: 307:32]>, C, I, E>, C, (), E>, Just<char, _, _>>` to implement `chumsky::private::ParserSealed<'_, I, (C, ()), E>`
    = note: 3 redundant requirements hidden
    = note: required for `Slice<Or<Then<TryMap<chumsky::primitive::Any<I, E>, C, [closure@sail_parser\src\lib.rs:297:18: 297:30]>, Repeated<chumsky::combinator::Filter<chumsky::primitive::Any<I, E>, [closure@sail_parser\src\lib.rs:307:25: 307:32]>, C, I, E>, C, (), E>, Just<char, _, _>>, 
(C, ())>` to implement `Parser<'a, I, &'a <C as chumsky::text::Char>::Str, E>`

from chumsky.

zesterer avatar zesterer commented on June 12, 2024

The problem here is that the output types of a and b in a.or(b) need to match. In your specific case, you have:

any()
    .then(...) // Output type = (char, _)
    .or(just('~') /* Output type = char */)
    .slice()

You can see the mismatch here. An easy approach to solving this, since the output value gets thrown away anyway, is to just use .ignored() on both parsers to give them both an output type of ():

any()
    .then(...)
    .ignored() // Output type = ()
    .or(just('~').ignored() /* Output type = () */)
    .slice()

from chumsky.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.