Используйте nom, чтобы найти несколько элементов в строке

Я пытаюсь написать парсер, который принимает &str и возвращает Vec<&str> где строки Vec - это IP-адреса. Единственный парсер, который я действительно могу получить, это Vec<Option<&str>> где None представляет байт, который не был частью IP. Как я могу "пропустить" байты, которые не являются частью IP, без их захвата?

Мой код парсера:

named!(ip<&str,&str>,
  recognize!(
    do_parse!(
      digit >>
      tag_s!(".") >>
      digit >>
      tag_s!(".") >>
      digit >>
      tag_s!(".") >>
      digit >>
      (
        ""
      )
    )
  )
);

named!(extract_ips<&str,Vec<(&str)>>,
  do_parse!(
      list: many0!(
        alt!(
            do_parse!(
                s: ip >>
                (
                    Some(s)
                )
            ) |
            do_parse!(
                anychar >>
                (
                    None
                )
            )
          )
        ) >> ({
            list.into_iter().filter_map(|entry| {
              match entry {
                None => None,
                other => other
              }
            }).collect()
        })
  )
);

Как видите, я использую alt!() выразить "либо потреблять IP или потреблять байт", а затем many0!() будет повторяться до тех пор, пока не будет выполнено использование строки. Я исправляю тип подписи, запустив filter_map против разобранного результата. Как я могу пропустить использование одного байта и просто двигаться вперед в буфере? У этого синтаксического анализатора есть другая проблема, где, если строка не заканчивается IP nom, будет считать это неполным анализом.

Работает:

let msg1 = r##"a1.2.3.4a3.14a5.6.7.8"##;
let res: IResult<&str, Vec<&str>> = extract_ips(msg1);

Не работает:

let msg1 = r##"a1.2.3.4a3.14a5.6.7.8FOO"##;
let res: IResult<&str, Vec<&str>> = extract_ips(msg1);

0 ответов

Другие вопросы по тегам