我正在用标语4.2.2编写基于文本格式的解析器,并且使用the whitespace facility来跳过空格。我必须使用自定义解析器,因为这种格式会将一些不寻常的字符视为空白。按照该页面上的示例,我使用eat_separator
制作了一个。
如何有效地扩展空间解析器,以同时使用从#
到行尾的行注释?这些注释可以出现在字符串中以外的任何位置。我总是想抛弃评论的内容:没有什么比预处理器指令更重要了。
答案 0 :(得分:3)
这是一个棘手的问题;编写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)), |_| ())
);
然后您可以用来重写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))
}
}
}
}
)
);