Как использовать nom take_ while и is_digit для ввода & str

Я пытаюсь изучить nom, но у меня проблема, когда take_while не принимает is_digit или любой другой is_xxxx.

У меня есть строки, которые я хочу проанализировать, которые выглядят так

#123 = ABCDEF (...);

где я хочу получить часть «123» (и, в конечном итоге, части ABCDEF и (...). Но в то время я думаю, что одно).

Мой парсер в настоящее время выглядит так

use nom::{
  bytes::complete::take_while,
  character::is_digit,
  error::ParseError,
  IResult
};

// Get row id
fn id<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
    take_while(is_digit)(i)
}

Определение is_digit выглядит так

pub fn is_digit(chr: u8) -> bool

А поскольку синтаксический анализатор id принимает &str, он будет жаловаться на несоответствие типов. Но можно ли вообще как-то использовать is_digit? Могу ли я где-нибудь выполнить преобразование типа, не выделяя ничего. Я действительно хочу, чтобы это было максимально эффективно.

Кажется, что в таких ситуациях следует использовать предоставленные is_xxxx функции, но я могу ошибаться.

Спасибо!


person mottosson    schedule 05.09.2019    source источник


Ответы (2)


Вы можете легко адаптировать is_digit к char. Во-первых, все цифры являются действительными ASCII, поэтому мы должны сначала проверить, является ли символ ASCII. Если это ASCII, мы можем безопасно преобразовать в u8.

// pub fn is_digit(chr: u8) -> bool;

pub fn is_char_digit(chr: char) -> bool {
    return chr.is_ascii() && is_digit(chr as u8)
}

Вы также можете использовать метод признака is_dec_digit , который является просто оболочкой для char.is_digit .

person Alexander Huszagh    schedule 05.09.2019
comment
Это похоже на изящную технику. Имеет ли это какое-либо влияние на производительность? - person mottosson; 07.09.2019
comment
Не особенно, если вы его встраиваете. Если вы хотите, чтобы это было быстрее, вы можете напрямую сравнить с помощью char.is_digit, что должно быть немного быстрее (или is_dec_digit, поскольку это означает меньшее количество сравнений. На самом деле, это в значительной степени то, как это делает nom (с использованием is_dec_digit): docs.rs/nom/4.0.0/src/nom/nom.rs .html # 216 - person Alexander Huszagh; 07.09.2019

Я знаю, что он не дает прямого ответа на ваш вопрос, потому что он не использует напрямую take_while, но вы можете использовать синтаксический анализатор digit1 в character::complete::digit1.

Он принимает &str, использует 1 или более цифр в [0..9] и возвращает &str

person Steve    schedule 05.09.2019
comment
Спасибо! Не отвечая на мой вопрос, как вы говорите, но определенно правильный способ сделать это :) - person mottosson; 07.09.2019