#Winnow seq macro

82 messages · Page 1 of 1 (latest)

regal bane
#

the trait bound Parser is not satisfied while trying to use the seq macro, even though i think it's written correctly (?)

#[derive(Debug, PartialEq)]
pub struct Function {
    name: String,
    body: Vec<Stmt>,
}

pub fn parse_expr(input: &mut &[Token]) -> PResult<Function> {
    seq!{Function {
        _: Token::Func,
        name: Token::Ident,
        _: Token::LBrace,
        body: repeat_till(0.., Token::RParen, parse_stmt),
    }}.parse_next(input)
}
fallen mirageBOT
#

Run cargo check in a terminal

Note: If using rust analyzer you can click the "click for full compiler diagnostic" link in your editor.

Please post the full output of the above command, including the error title and any help or notes. An example of how this looks is:

error[E0308]: mismatched types
 --> src/main.rs:3:17
  |
3 | let foo: &i32 = bar;
  |          ----   ^^^ expected `&i32`, found integer
  |          |
  |          expected due to this
  |
help: consider borrowing here
  |
3 | let foo: &i32 = &bar;
  |                 +

When posting the error put it in a code block so it has nice formatting:

```rust
// error from cargo check here
```

Please do not post a screenshot. If the output is too long then use a paste tool like https://paste.rs/web

gusty mantle
regal bane
#

yeah

#

¯_(ツ)_/¯

gusty mantle
regal bane
#

I'm not home rn so I can't sadly

gusty mantle
#

ok, without that it's hard to say anything really

regal bane
#

ok finally i can send it, here it is

error[E0277]: expected a `FnMut(&mut &[lex::Token])` closure, found `lex::Token`
   --> src/parse/function.rs:17:5
    |
17  | /     seq!{Function {
18  | |         _: Token::Func,
19  | |         name: Token::Ident,
21  | |         _: Token::LBrace,
22  | |         body: repeat_till(0.., Token::RParen, parse_stmt),
23  | |     }}.parse_next(input)
    | |______^ expected an `FnMut(&mut &[lex::Token])` closure, found `lex::Token`
    |
    = help: the trait `for<'a> FnMut(&'a mut &[lex::Token])` is not implemented for `lex::Token`
    = help: the following other types implement trait `winnow::Parser<I, O, E>`:
              `&'s [u8; N]` implements `winnow::Parser<I, <I as Stream>::Slice, E>`
              `&'s [u8]` implements `winnow::Parser<I, <I as Stream>::Slice, E>`
              `&'s str` implements `winnow::Parser<I, <I as Stream>::Slice, E>`
              `()` implements `winnow::Parser<I, (), E>`
              `(P1, P2)` implements `winnow::Parser<I, (O1, O2), E>`
              `(P1, P2, P3)` implements `winnow::Parser<I, (O1, O2, O3), E>`
              `(P1, P2, P3, P4)` implements `winnow::Parser<I, (O1, O2, O3, O4), E>`
              `(P1, P2, P3, P4, P5)` implements `winnow::Parser<I, (O1, O2, O3, O4, O5), E>`
            and 43 others
    = note: required for `lex::Token` to implement `winnow::Parser<&[lex::Token], _, ContextError>`

error[E0308]: mismatched types
  --> src/parse/function.rs:17:5
   |
17 | /     seq!{Function {
18 | |         _: Token::Func,
19 | |         name: Token::Ident,
21 | |         _: Token::LBrace,
22 | |         body: repeat_till(0.., Token::RParen, parse_stmt),
23 | |     }}.parse_next(input)
   | |______^ expected `Vec<Stmt>`, found `(_, Stmt)`
   |
   = note: expected struct `Vec<Stmt>`
               found tuple `(_, Stmt)`
gusty mantle
#

did you implement Parser manually for it maybe?

regal bane
#
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Token {
    // ...
}

impl winnow::stream::ContainsToken<Token> for Token {
    #[inline(always)]
    fn contains_token(&self, token: Token) -> bool {
        *self == token
    }
}

impl winnow::stream::ContainsToken<Token> for &'_ [Token] {
    #[inline]
    fn contains_token(&self, token: Token) -> bool {
        self.iter().any(|t| *t == token)
    }
}

impl<const LEN: usize> winnow::stream::ContainsToken<Token> for &'_ [Token; LEN] {
    #[inline]
    fn contains_token(&self, token: Token) -> bool {
        self.iter().any(|t| *t == token)
    }
}

impl<const LEN: usize> winnow::stream::ContainsToken<Token> for [Token; LEN] {
    #[inline]
    fn contains_token(&self, token: Token) -> bool {
        self.iter().any(|t| *t == token)
    }
}
gusty mantle
#

and to parse a token you need a Parser, not a value of the enum

regal bane
#

the full token is

#[derive(Logos, Debug, Clone, PartialEq, Eq)]
#[logos(error = LexingError)]
#[logos(skip r"[ \t\n\r\f]+")]
pub enum Token {
    #[regex("[a-zA-Z0-9_]+", |lex| lex.slice().to_string())]
    Ident(String),

    #[regex(r#""[^"]*""#, |lex| unescape(&lex.slice().to_string().replace("\"", "")).unwrap())]
    String(String),

    #[regex(r"(0x[0-9a-fA-F]+|0b[01]+|\d+)", priority = 3, callback = |lex| {
        let string = lex.slice();
        if string.starts_with("0x") {
            i64::from_str_radix(&string.replace("0x", ""), 16)
        } else if string.starts_with("0b") {
            i64::from_str_radix(&string.replace("0b", ""), 2)
        } else if string.starts_with("-") {
            Ok(-(string.replace("-", "").parse::<i64>()?))
        } else {
            string.parse()
        }
    })]
    Number(i64),

    #[token("func")]
    Func,

    #[token("(")]
    LParen,

    #[token(")")]
    RParen,

    #[token("{")]
    LBrace,

    #[token("}")]
    RBrace,

    #[token(",")]
    Comma,

    #[token("+")]
    Add,

    #[token("-")]
    Sub,

    #[token("*")]
    Mul,

    #[token("/")]
    Div,

    #[token("+=", priority = 5)]
    AddEqual,

    #[token("-=", priority = 5)]
    SubEqual,

    #[token("*=", priority = 5)]
    MulEqual,

    #[token("/=", priority = 5)]
    DivEqual,

    #[token(";")]
    Semicolon,

    #[token("extern")]
    Extern,

    #[token("var")]
    Var,

    #[token("=")]
    Assign,

    #[token("import")]
    Import,

    #[token(":")]
    Colon,

    #[token("return")]
    Return,

    #[token("->")]
    RightArrow,

    #[regex(r"//[^\n]*", logos::skip)]
    Comment,

    #[regex(r"/\*([^*]|\*[^/])*\*/", logos::skip)]
    MultiComment,
}
gusty mantle
#

so for the tokens you'd require ```rs
pub fn parse_expr(input: &mut &[Token]) -> PResult<Function> {
seq!{Function {
_: literal(Token::Func),
name: literal(Token::Ident),
_: literal(Token::LBrace),
body: repeat_till(0.., literal(Token::RParen), parse_stmt),
}}.parse_next(input)
}

regal bane
#

im new to this library so i don't really know what im doing 😅

#

sorry if its a little frustrating trying to explain it to me

regal bane
# gusty mantle so for the tokens you'd require ```rs pub fn parse_expr(input: &mut &[Token]) ->...

when trying this, i get this error:

error[E0308]: mismatched types
  --> src/parse/function.rs:18:5
   |
18 | /     seq!{Function {
19 | |         _: literal(Token::Func),
20 | |         name: literal(Token::Ident),
21 | |         _: literal(Token::LBrace),
22 | |         body: repeat_till(0.., literal(Token::RParen), parse_stmt),
23 | |     }}.parse_next(input)
   | |      ^
   | |      |
   | |______expected `String`, found `&[Token]`
   |        here the type of `name` is inferred to be `&[lex::Token]`
   |
   = note: expected struct `std::string::String`
           found reference `&[lex::Token]`
   = note: this error originates in the macro `$crate::seq_init_struct_fields` which comes from the expansion of the macro `seq` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> src/parse/function.rs:18:5
   |
18 | /     seq!{Function {
19 | |         _: literal(Token::Func),
20 | |         name: literal(Token::Ident),
21 | |         _: literal(Token::LBrace),
22 | |         body: repeat_till(0.., literal(Token::RParen), parse_stmt),
23 | |     }}.parse_next(input)
   | |______^ expected `Vec<Stmt>`, found `(_, Stmt)`
   |
   = note: expected struct `Vec<Stmt>`
               found tuple `(_, Stmt)`
gusty mantle
#

it's alright, I can see that the library doesn't give a lot of examples for custom Streams, it's mostly &str or &[u8]

gusty mantle
regal bane
#

yeah i read the tutorial

gusty mantle
#

oh it's the struct field

#

and it's ```rs
pub enum Token {
Ident(String),

#

hmm

regal bane
#

yeah

#

how would it be extracted tho

#

ok i changed it to this:

pub fn parse_function(input: &mut &[Token]) -> PResult<Function> {
    seq!{Function {
        _: literal(Token::Func),
        name: literal(Token::Ident.0),
        _: literal(Token::LBrace),
        body: repeat_till(0.., literal(Token::RParen), parse_stmt),
    }}.parse_next(input)
}

and now only this error is left (and a bunch of "x is not satisfied"):

error[E0308]: mismatched types
  --> src/parse/function.rs:18:5
   |
18 | /     seq!{Function {
19 | |         _: literal(Token::Func),
20 | |         name: literal(Token::Ident.0),
21 | |         _: literal(Token::LBrace),
22 | |         body: repeat_till(0.., literal(Token::RParen), parse_stmt),
23 | |     }}.parse_next(input)
   | |______^ expected `Vec<Stmt>`, found `(_, Stmt)`
   |
   = note: expected struct `Vec<Stmt>`
               found tuple `(_, Stmt)`
gusty mantle
#

from the Stream implementation tutorial you can use ```rs
one_of(|t| matches!(t, Token::Value(_))).map(|t| match t {
Token::Value(v) => Expr::Value(v),
_ => unreachable!(),
}),

#

that will work for Ident

regal bane
#

it seems i already fixed it

gusty mantle
#

that's unlikely

regal bane
#

well the error is gone so maybe

#

¯_(ツ)_/¯

gusty mantle
#

unless seq! is really really really magic then literal(Token::Ident.0) makes no sense

regal bane
#

macros themselves are magic

gusty mantle
#

not really

regal bane
#

but you may be right

gusty mantle
regal bane
#

changed it, still the same error and "x is not satisfied" errors:

error[E0308]: mismatched types
  --> src/parse/function.rs:18:5
   |
18 | /     seq!{Function {
19 | |         _: literal(Token::Func),
20 | |         name: one_of(|t| matches!(t, Token::Ident(_))).map(|t| match t {
21 | |             Token::Ident(v) => v,
...  |
25 | |         body: repeat_till(0.., literal(Token::RParen), parse_stmt),
26 | |     }}.parse_next(input)
   | |______^ expected `Vec<Stmt>`, found `(_, Stmt)`
   |
   = note: expected struct `Vec<Stmt>`
               found tuple `(_, Stmt)`
gusty mantle
#

yeah that repeat_till doesn't do what you think it does

#

I think you swapped the arguments

regal bane
#

how can i use the parse_stmt parser until a Token::RParen then?

gusty mantle
#

swap the arguments

regal bane
#
error[E0308]: mismatched types
  --> src/parse/function.rs:18:5
   |
18 | /     seq!{Function {
19 | |         _: literal(Token::Func),
20 | |         name: one_of(|t| matches!(t, Token::Ident(_))).map(|t| match t {
21 | |             Token::Ident(v) => v,
...  |
25 | |         body: repeat_till(0.., parse_stmt, literal(Token::RParen)),
26 | |     }}.parse_next(input)
   | |______^ expected `Vec<Stmt>`, found `(_, &[Token])`
   |
   = note: expected struct `Vec<Stmt>`
               found tuple `(_, &[lex::Token])`
gusty mantle
#

then you need the first element of the tuple

#

probably using .map()

regal bane
#

changed it to this:

#[derive(Debug, PartialEq)]
pub struct Function {
    name: String,
    body: Vec<Stmt>,
}

pub fn parse_function(input: &mut &[Token]) -> PResult<Function> {
    seq!{Function {
        _: literal(Token::Func),
        name: one_of(|t| matches!(t, Token::Ident(_))).map(|t| match t {
            Token::Ident(v) => v,
            _ => unreachable!(),
        }),
        _: literal(Token::LBrace),
        body: repeat_till(0.., parse_stmt, literal(Token::RParen)).map(|x| {
            x.0
        }),
    }}.parse_next(input)
}
#

now i only see errors about "trait x is not implemented":
the trait Compare<lex::Token> is not implemented for &[lex::Token]
the trait SliceLen is not implemented for lex::Token

gusty mantle
#

with just the value, the same way

regal bane
#

oh it finally works

#

at least no errors

gusty mantle
#

so, I just read the custom Stream code from the docs carefully

regal bane
#

wait how do i even convert vec<Token> to &mut &[Token]?
i can only make it &mut _

#

ok i did it

gusty mantle
#
pub(crate) fn expr2(i: &mut &str) -> PResult<Expr> {
    let tokens = lex.parse_next(i)?;
    expr.parse_next(&mut tokens.as_slice())
}
``` from the Stream page
#

tokens: Vec<Token>

regal bane
#

ah this is not very good Err(Backtrack(ContextError { context: [], cause: None }))

#

time to debug

regal bane
#

ummmmm

#

for some reason the one_of function just errors

#

even this basic code makes an error:

let _ = one_of(Token::Func).parse_next(input)?;
#

ah nevermind, my test code was wrong

gusty mantle
#

they could help you debug

regal bane
#

yeah i already found it ferrisSweat

#

i may just be a little bad at programming lol