Как разобрать совпадающие разделители по номеру? - PullRequest
0 голосов
/ 19 сентября 2019

Я хочу проанализировать дату YMD в четырех формах ("20190919", "2019.09.19", "2019-09-19" и "2019/09/19") в библиотеке nom .

Я начал с iso8601 парсера, который анализирует только форму "ГГГГ-ММ-ДД".И я попытался сопоставить разделитель и использовать его для следующего сопоставления, как в регулярном выражении (\ d {4}) ([.- /]?) (\ D {2}) \ 2 (\ d {2}) .

Оказалось, что этот код работает:

fn parse_ymd(i: &[u8]) -> IResult<&[u8], DateType> {
    let (i, y) = year(i)?;

    // Match separator if it exist.
    let (i, sep) = opt(one_of(".-/"))(i)?;

    let (i, m) = month(i)?;

    // If first separator was matched then try to find next one.
    let (i, _) = if let Some(sep) = sep {
        tag(&[sep as u8])(i)?
    } else {
        // Support the same signature as previous branch.
        (i, &[' ' as u8][..])
    };

    let (i, d) = day(i)?;

    Ok((
        i,
        DateType::YMD {
            year: y,
            month: m,
            day: d,
        },
    ))
}

Но, очевидно, это выглядит странно.

Существуют ли какие-нибудь инструменты для более подходящего способа?

(Этот вопрос о функциональности nom и о том, как все сделать правильно, а не об этом конкретном примере.)

1 Ответ

0 голосов
/ 19 сентября 2019

Ваше решение достаточно приличное.На самом деле я могу предложить только одно предложение:

fn parse_ymd(i: &[u8]) -> IResult<&[u8], DateType> {
    ...

    // If first separator was matched then try to find next one.
    let i = match sep {
        Some(sep) => tag(&[sep as u8])(i)?.0,
        _ => i,
    };

    ...
}

Возможно, вы не знакомы с синтаксисом прямого доступа к элементу кортежа.Из rust book :

Помимо деструктуризации с помощью сопоставления с образцом, мы можем напрямую получить доступ к элементу кортежа, используя точку (.), За которой следует индекс нужного нам значения.для доступа.

В этом случае это избавляет вас от неловкости попыток сопоставить подпись двух рук.

...