Подходим слизняк с Ном - PullRequest
       129

Подходим слизняк с Ном

0 голосов
/ 31 января 2020

Я некоторое время пытался найти достойное решение для Nom, чтобы распознать слизняк как alpha1. Таким образом, я мог бы разобрать что-то вроде этого

fn parse<'a>(text: &'a str) -> IResult<&'a str, &'a str> {
  delimited(char(':'), slug, char(':'))(text)
}

assert!(
  parse(":hello-world-i-only-accept-alpha-numeric-char-and-dashes:"),
  "hello-world-i-only-accept-alpha-numeric-char-and-dashes"
);

Я пробовал что-то подобное, но, похоже, это не работает.

fn slug<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
    T: InputTakeAtPosition,
    <T as InputTakeAtPosition>::Item: AsChar + Clone,
{
    input.split_at_position1(
        |item| {
            let c = item.clone().as_char();

            !(item.is_alpha() || c == '-')
        },
        ErrorKind::Char,
    )
}

PS: Вы знаете, как сказать Nom, что «-» в слизне не должно быть ни в начале, ни в конце?

1 Ответ

1 голос
/ 01 февраля 2020

Для этого есть nom::multi::separated_list. И поскольку вы хотите, чтобы результатом была сама строка, а не вектор сегментов, объедините ее с nom::combinator::recognize, чтобы добиться цели:

use std::error::Error;
use nom::{
    IResult,
    character::complete::{alphanumeric1, char},
    combinator::recognize,
    multi::separated_list,
    sequence::delimited,
};

fn slug_parse<'a>(text: &'a str) -> IResult<&'a str, &'a str> {
    let slug = separated_list(char('-'), alphanumeric1);
    delimited(char(':'), recognize(slug), char(':'))(text)
}

fn main() -> Result<(), Box<dyn Error>> {
    let (_, res) = slug_parse(":hello-world-i-only-accept-alpha-numeric-char-and-dashes:")?;
    assert_eq!(
      res,
      "hello-world-i-only-accept-alpha-numeric-char-and-dashes"
    );

    Ok(())
}
...