如何制作一个 nom 空白解析器来跳过面向行的注释?

Dan*_*lme 7 comments rust nom

我正在 nom 4.2.2 中为基于文本的格式编写解析器,并且我正在使用空格工具来跳过空格。我必须使用自定义解析器,因为这种格式将一些不寻常的字符视为空格。按照该页面上的示例,我使用eat_separator.

如何有效地扩展我的空间解析器以也使用从行注释#到行尾的行注释?这些注释可以出现在字符串之外的任何地方。我总是想扔掉评论的内容:没有什么比预处理器指令更好的了。

Val*_*ntz 8

这是一个棘手的问题;我在编写 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!(" \t\x0c") => { |_|() } | escaped_newline | newline)), |_| ())
);
named!(pub spaces_nonl<StrSpan, ()>,
  map!(many0!(alt!(one_of!(" \t\x0c") => { |_| () }|escaped_newline)), |_| ())
);
Run Code Online (Sandbox Code Playgroud)

然后您可以使用它来重写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))
          }
        }
      }
    }
  )
);
Run Code Online (Sandbox Code Playgroud)

相关代码,如果您好奇的话:https://github.com/ProgVal/rust-python-parser/blob/1e03122f030e183096d7d3271907106678036f56/src/helpers.rs