0

I am trying to use nom5 to pass a number of the zinc format https://www.project-haystack.org/doc/Zinc

The number format can be like any of the following formats

1, -34, 10_000, 5.4e-45, -5.4e-45, 9.23kg, 74.2°F, 4min, INF, -INF, NaN

I believe the units can be anything if specified.

I have some examples of simple number passing like Parsing number with nom 5.0

fn number<'a>(i: &'a str) -> IResult<&'a str, Token, (&'a str, ErrorKind)> {
    map(
        tuple((
            opt(char('-')),
            many1(digit1),
            opt(preceded(char('.'), many1(digit1)))
        )),
        |s| Token::Number(s)
    )(i)
}

but I am not sure how to deal with the values possibly also being INF or -INF, NaN and having the possible addition of units.

How would I handle this case in nom ?

Thanks

Glenn Pierce
  • 720
  • 1
  • 6
  • 18
  • Units are just another trailing [`opt`](https://docs.rs/nom/5.1.2/nom/macro.opt.html), and choices are modeled using [`alt`](https://docs.rs/nom/5.1.2/nom/macro.alt.html). – IInspectable Jun 18 '20 at 10:46

1 Answers1

0

In the end I built it up like

fn simple_number<'a>(i: &'a str) -> IResult<&'a str, Token, (&'a str, ErrorKind)> {

    map(
        recognize(tuple( (opt(alt((char('-'), char('+')))), many1(digit1), opt(preceded(char('.'), many1(digit1)))) ) ),
        |s: &str| Token::Number(s.parse::<f64>().unwrap(), "".into())
        //|s: &str| Token::Var(s.into())
    )(i)
}

fn exponent<'a>(i: &'a str) -> IResult<&'a str, Token, (&'a str, ErrorKind)> {
    map(
        recognize(tuple(  ( alt((char('e'), char('E'))), simple_number  )) ),
        |s: &str| Token::Var(s.into())
    )(i)
}

fn number<'a>(i: &'a str) -> IResult<&'a str, f64, (&'a str, ErrorKind)> {
    map(
        recognize(tuple((simple_number, opt(exponent))) ),
        |s: &str| s.parse::<f64>().unwrap()
    )(i)
}

fn units<'a>(i: &'a str) -> IResult<&'a str, &'a str, (&'a str, ErrorKind)> {
    alphanumeric1(i)
}

fn number_with_unit<'a>(i: &'a str) -> IResult<&'a str, Token, (&'a str, ErrorKind)> {
    map(
        tuple((number, opt(units))),
        |t: (f64, Option<&str>)| Token::Number(t.0, t.1.unwrap_or(&"".to_string()).into())
    )(i)
}

// Number: 1, -34, 5.4, -5.4, 9.23, 74.2, 4, 5.4e-45, -5.4e-45, 67.3E7 INF -INF +INF NAN
fn zinc_number<'a>(i: &'a str) -> IResult<&'a str, Token, (&'a str, ErrorKind)> {

    alt( (number_with_unit, inf, nan) ) (i)
}
Glenn Pierce
  • 720
  • 1
  • 6
  • 18