Разбор числа в nom - PullRequest
       49

Разбор числа в nom

0 голосов
/ 18 июня 2020

Я пытаюсь использовать nom5 для передачи числа в формате zin c https://www.project-haystack.org/doc/Zinc

Формат чисел может быть как любой из следующих форматов

1, -34, 10_000, 5.4e-45, -5.4e-45, 9,23 кг, 74,2 ° F, 4 мин, INF, -INF, NaN

Я считаю, что единицы могут быть любыми, если указаны .

У меня есть несколько примеров передачи простых чисел, например, Число синтаксического анализа с 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)
}

, но я не уверен, как поступить со значениями, которые, возможно, также INF или -INF, NaN и с возможным добавлением единиц.

Как мне обработать этот случай в nom?

Спасибо

1 Ответ

0 голосов
/ 18 июня 2020

В итоге собрал как

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)
}
...