winnow-rs / winnow

Making parsing a breeze
https://docs.rs/winnow
Other
572 stars 44 forks source link

take_till not support tag(char) #419

Closed baoyachi closed 10 months ago

baoyachi commented 10 months ago

Please complete the following tasks

rust version

rustc 1.74.0 (79e9716c9 2023-11-13)

winnow version

0.5.33

Minimal reproducible code

fn parse_no_escaped_with_tag<'i>(input: &mut &'i str) -> PResult<ExprVal> {
    trace("parse_no_escaped_with_tag",
          take_till(1.., [tag('"'), tag('\\')]).map(|x: &str| ExprVal::NormalVal(x.to_string()))
    ).parse_next(input)
}

fn parse_no_escaped_with_char<'i>(input: &mut &'i str) -> PResult<ExprVal> {
    trace("parse_no_escaped_with_char",
          take_till(1.., ['"', '\\']).map(|x: &str| ExprVal::NormalVal(x.to_string()))
    ).parse_next(input)
}

#[derive(Clone, Debug)]
enum ExprVal {
    Char(char),
    NormalVal(String),
}

parse_no_escaped_with_tag vs parse_no_escaped_with_char function is equivalent and currently does not support passing tags (char) to a List args.

Steps to reproduce the bug with the above code

error[E0277]: expected a `Fn<(_,)>` closure, found `[impl Parser<_, <_ as Stream>::Slice, _>; 2]`
   --> src/main.rs:11:26
    |
11  |           take_till(1.., [tag('"'), tag('\\')]).map(|x: &str| ExprVal::NormalVal(x.to_string()))
    |           ---------      ^^^^^^^^^^^^^^^^^^^^^ expected an `Fn<(_,)>` closure, found `[impl Parser<_, <_ as Stream>::Slice, _>; 2]`
    |           |
    |           required by a bound introduced by this call
    |
    = help: the trait `Fn<(_,)>` is not implemented for `[impl Parser<_, <_ as Stream>::Slice, _>; 2]`
    = help: the following other types implement trait `ContainsToken<T>`:
              [char; LEN]
              [u8; LEN]
              &[u8]
              &[char]
              &[u8; LEN]
              &[char; LEN]
    = note: required for `[impl Parser<_, <_ as Stream>::Slice, _>; 2]` to implement `ContainsToken<_>`
note: required by a bound in `take_till`
   --> ~/.cargo/registry/src/winnow-0.5.33/src/token/mod.rs:767:8
    |
760 | pub fn take_till<T, I, Error: ParserError<I>>(
    |        --------- required by a bound in this function
...
767 |     T: ContainsToken<<I as Stream>::Token>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `take_till`

Actual Behaviour

parse_no_escaped_with_tag cannot be compiled

Expected Behaviour

parse_no_escaped_with_tag vs parse_no_escaped_with_char function also support .

Additional Context

No response

epage commented 10 months ago

take_till only takes up to a token from a token set, not a parsed result, and does so using the ContainsToken trait.

Your code can be fixed by changing it to ['"', '\\'].

If you do want to take up to a parser, you need

In theory, we could make tag return a struct Tag, rather than an impl Parser and impl ContainsToken for Tag<char> but that seems like that would just confuse the issue more to have some parsers that can also be a token set.

baoyachi commented 10 months ago

THX