Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will nom_locate support nom 5 number parsers #35

Open
lochbrunner opened this issue Aug 10, 2019 · 8 comments
Open

Will nom_locate support nom 5 number parsers #35

lochbrunner opened this issue Aug 10, 2019 · 8 comments

Comments

@lochbrunner
Copy link

As far as I see the number parsers in nom 5 dont support nom_locate::LocatedSpan<_> :

See here: https://github.com/Geal/nom/blob/master/src/number/complete.rs

Will this crate support that parsers in future?

@progval
Copy link
Collaborator

progval commented Aug 10, 2019

:(

I think the right fix would be for nom to implement these for any type implementing a certain trait (probably InputTake).

@progval
Copy link
Collaborator

progval commented Aug 10, 2019

ping @Geal

@progval
Copy link
Collaborator

progval commented Apr 4, 2020

Or alternatively, @eignnx's idea in #55 might solve this issue as well

@Stargateur
Copy link

well... this ParseError is a pain

@paulyoung
Copy link

I arrived here after trying to figure out how to make hex_u32 accept a LocatedSpan.

I can dereference the input (*hex) but then things don’t type check because my ParseError implementation is only for LocatedSpan and not just [u8].

Does anyone have any suggestions?

@Stargateur
Copy link

@paulyoung should be fine since nom 6, this issue should be close.

@paulyoung
Copy link

@Stargateur I’m using nom 7 and wasn’t able to figure it out. I ended up doing this instead:

+// Based on https://docs.rs/nom/7.0.0/src/nom/number/complete.rs.html#1363-1383
-pub fn hex_u32<'a, E: ParseError<&'a [u8]>>(input: &'a [u8]) -> IResult<&'a [u8], u32, E> {
+pub fn hex_u32(input: Span) -> IResult<u32> {
    let (i, o) = nom::bytes::complete::is_a(&b"0123456789abcdefABCDEF"[..])(input)?;
    // Do not parse more than 8 characters for a u32
    let (parsed, remaining) = if o.len() <= 8 {
        (o, i)
    } else {
-    (&input[..8], &input[8..])
+    (Span::new(&input[..8]), Span::new(&input[8..]))
    };

    let res = parsed
        .iter()
        .rev()
        .enumerate()
        .map(|(k, &v)| {
            let digit = v as char;
            digit.to_digit(16).unwrap_or(0) << (k * 4)
        })
        .sum();

    Ok((remaining, res))
}

@paulyoung
Copy link

paulyoung commented Sep 3, 2021

For context:

// https://iximiuz.com/en/posts/rust-writing-parsers-with-nom/
use nom;
use nom_locate::LocatedSpan;

pub type Span<'a> = LocatedSpan<&'a [u8]>;

pub type IResult<'a, O> = nom::IResult<Span<'a>, O, ParseError<'a>>;

#[derive(Debug, PartialEq)]
pub struct ParseError<'a> {
    span: Span<'a>,
    message: String,
}

impl<'a> ParseError<'a> {
    pub fn new(message: String, span: Span<'a>) -> Self {
        Self { message, span }
    }

    pub fn span(&self) -> &Span { &self.span }

    pub fn line(&self) -> u32 { self.span().location_line() }

    pub fn offset(&self) -> usize { self.span().location_offset() }
}

impl<'a> nom::error::ParseError<Span<'a>> for ParseError<'a> {
    fn from_error_kind(input: Span<'a>, kind: nom::error::ErrorKind) -> Self {
        Self::new(format!("parse error {:?}", kind), input)
    }

    fn append(_input: Span<'a>, _kind: nom::error::ErrorKind, other: Self) -> Self {
        other
    }

    fn from_char(input: Span<'a>, c: char) -> Self {
        Self::new(format!("unexpected character '{}'", c), input)
    }
}

impl<'a> nom::error::ContextError<Span<'a>> for ParseError<'a> {
    fn add_context(input: Span<'a>, ctx: &'static str, other: Self) -> Self {
        let message = format!("{}: {}", ctx, other.message);
        ParseError::new(message, input)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants