Как мне создать анализатор пробелов nom, который также пропускает комментарии, ориентированные на строки?

#rust #comments #nom

#Ржавчина #Комментарии #nom

Вопрос:

Я пишу анализатор для текстового формата в nom 4.2.2, и я использую средство пробела для пропуска пробелов. Я должен использовать пользовательский анализатор, потому что этот формат обрабатывает некоторые необычные символы как пробелы. Следуя примеру на этой странице, я создал его с помощью eat_separator .

Как мне эффективно расширить мой анализатор пробелов, чтобы он также использовал комментарии к строке от # до конца строки? Эти комментарии могут появляться где угодно, кроме строк. Я всегда хочу выбросить содержимое комментария: нет ничего похожего на директивы препроцессора.

Ответ №1:

Это сложная проблема; у меня тоже была такая при написании анализатора Python.

Вот как я в итоге реализовал «разрыв строки, которому необязательно предшествует комментарий»:

 named!(pub newline<StrSpan, ()>,
  map!(
    many1!(
      tuple!(
        spaces_nonl,
        opt!(preceded!(char!('#'), many0!(none_of!("n")))),
        char!('n')
      )
    ),
    |_| ()
  )
);

named!(pub spaces_nl<StrSpan, ()>,
  map!(many0!(alt!(one_of!(" tx0c") => { |_|() } | escaped_newline | newline)), |_| ())
);
named!(pub spaces_nonl<StrSpan, ()>,
  map!(many0!(alt!(one_of!(" tx0c") => { |_| () }|escaped_newline)), |_| ())
);
  

Который затем можно использовать для перезаписи ws! для использования этой новой функции (я скопировал-вставил код из nom и заменил имя аргумента sep! ):

 /// Like `ws!()`, but ignores comments as well
macro_rules! ws_comm (
  ($i:expr, $($args:tt)*) => (
    {
      use nom::Convert;
      use nom::Err;

      match sep!($i, spaces_nl, $($args)*) {
        Err(e) => Err(e),
        Ok((i1,o))    => {
          match spaces_nl(i1) {
            Err(e) => Err(Err::convert(e)),
            Ok((i2,_))    => Ok((i2, o))
          }
        }
      }
    }
  )
);
  

Связанный код, на случай, если вам интересно: https://github.com/ProgVal/rust-python-parser/blob/1e03122f030e183096d7d3271907106678036f56/src/helpers.rs