Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
gamma-delta
@gamma-delta
OK I have a legitimate issue this time
I would like to parse stuff like this: 1, 3
so, f32, maybe whitespaces, comma, maybe whitespaces, and another f32
/// Parses a Point.
fn point(input: &str) -> IResult<&str, Point> {
    let (input, x) = recognize_float(input)?;
    // allow spaces between number & comma
    let (input, _) = take_while(is_space)(input)?;
    // the comma
    let (input, _) = char(',')(input)?;
    // more maybe whitespace
    let (input, _) = take_while(is_space)(input)?;
    // And the y
    let (input, y) = recognize_float(input)?;

    // Return OK!
    Ok((x, y))
}
but, it looks like take_while doesn't work on characters or something?
error[E0271]: type mismatch resolving `<&str as nom::traits::InputTakeAtPosition>::Item == u8`
  --> trident\src\parse.rs:17:22
   |
17 |     let (input, _) = take_while(is_space)(input)?;
   |                      ^^^^^^^^^^ expected `char`, found `u8`

error[E0271]: type mismatch resolving `<&str as nom::traits::InputTakeAtPosition>::Item == u8`
  --> trident\src\parse.rs:21:22
   |
21 |     let (input, _) = take_while(is_space)(input)?;
   |                      ^^^^^^^^^^ expected `char`, found `u8`

error[E0308]: mismatched types
  --> trident\src\parse.rs:26:12
   |
26 |     Ok((x, y))
   |            ^ expected tuple, found `&str`
   |
   = note:  expected tuple `(f32, f32)`
           found reference `&str`
i don't understand what is wrong
please help?
zserik
@zserik
maybe take_while(|x| x.is_ascii_whitespace()) or something like that
and you probably need to change Ok((x,y)) to Ok(Point(x,y)) or something like that (I don't know your type definition of Point...)...
gamma-delta
@gamma-delta
It's pub type Point = (f32, f32) dw :)
zserik
@zserik
hm
gamma-delta
@gamma-delta
is_a(" \t")(input)?; seems to work
But now, it thinks y is a (f32, f32)?
oh
i messed up the return
How do you convert some other kind of error into an IResult?
specifically the error from .parse()
zserik
@zserik
to parse floats maybe use nom::number::streaming::float
gamma-delta
@gamma-delta
i thought that took bytes though?
like the 4 bytes of a f32 in memory, not the textual representation
zserik
@zserik
s/streaming/complete/;
ah, ok.
gamma-delta
@gamma-delta
oh nope you're right
that would be big endian float parsing :-)
gamma-delta
@gamma-delta
OK
Is there a way to tell nom about comments?
like "Hey at any point if I see a # just ignore everything till eol"
zserik
@zserik
you could try to insert calls to opt or ss
so.
gamma-delta
@gamma-delta
after every statement?
owch
zserik
@zserik
maybe you should split the parser into multiple parts 1. parse comments and escapes, return byte slices, fold them, then run a second parser on that or so...
would be a bit more difficult, but also probably less error prone, I suppose... it might be necessary to save the original offsets somewhere for good error reporting, tho.
gamma-delta
@gamma-delta
or i could just only allow comments at the beginning of lines
which sounds like a way easier idea...
zserik
@zserik
it might be a good idea to allow them after complete finished statements (often only one additional place to include an opt(...comments...) parser), but with benefits for code writers..
gamma-delta
@gamma-delta
Actually yeah good idea
right cause if it sees a hashtag midway through a statement then it will yell about "hey i don't know what that weird symbol is"
gamma-delta
@gamma-delta
why doesn't this work? ```rs
uh
let single_point = |input: &str| {
    let (input, _) = is_a(" \t")(input)?;
    let (input, p) = point(input)?;
    let (input, _) = is_a(" \t")(input)?;
    let (input, _) = char(';')(input)?;
    <IResult<&str, Point>>::Ok((input, p))
};
trying to do an inline closure here because I need to match a Shape, ending with a semicolon
but i get a conflicting lifetime error
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> trident\src\parse.rs:47:38
   |
47 |         let (input, _) = is_a(" \t")(input)?;
   |                                      ^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 46:24...
  --> trident\src\parse.rs:46:24
   |
46 |       let single_point = |input: &str| {
   |  ________________________^
47 | |         let (input, _) = is_a(" \t")(input)?;
48 | |         let (input, p) = point(input)?;
49 | |         let (input, _) = is_a(" \t")(input)?;
50 | |         let (input, _) = char(';')(input)?;
51 | |         <IResult<&str, Point>>::Ok((input, p))
52 | |     };
   | |_____^
note: ...so that the expression is assignable
  --> trident\src\parse.rs:47:38
   |
47 |         let (input, _) = is_a(" \t")(input)?;
   |                                      ^^^^^
   = note: expected  `&str`
              found  `&str`
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 44:1...
  --> trident\src\parse.rs:44:1
   |
44 | / fn shape(input: &str) -> IResult<&str, Shape> {
45 | |     // Parses a single entry (Point;)
46 | |     let single_point = |input: &str| {
47 | |         let (input, _) = is_a(" \t")(input)?;
...  |
70 | |     Ok((input, Shape { color, points }))
71 | | }
   | |_^
note: ...so that the expression is assignable
  --> trident\src\parse.rs:57:67
   |
57 |     let (input, required_3_points) = count(single_point, 3)(input)?;
   |                                                                   ^
   = note: expected  `std::result::Result<(&str, Shape), nom::internal::Err<(&str, nom::error::ErrorKind)>>`
              found  `std::result::Result<(&str, Shape), nom::internal::Err<(&str, nom::error::ErrorKind)>>`
Why doesn't this work? i can pass input around all I like in other spaces...
gamma-delta
@gamma-delta
I got that fixed yay
How do you do take_until(line_ending)?
ie, take_until another parser matches