用nom分析多行注释



我正在尝试编写一个识别多行注释的nom解析器。。。

/*
yo!
*/

并消耗/丢弃(同样的东西,对吧?(结果:

use nom::{
bytes::complete::{tag, take_until},
error::{ErrorKind, ParseError},
sequence::preceded,
IResult,
};
fn multiline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
preceded(tag("/*"), take_until("*/"))(i)
}

这几乎奏效了。我知道take_until在*/之前停止,但我不知道该怎么做才能将其包含在内。

#[test]
fn should_consume_multiline_comments() {
assert_eq!(
multiline_comment::<(&str, ErrorKind)>("/*abcnndef*/"),
Ok(("", "/*abcnndef*/"))
);
}

给出结果

thread 'should_consume_multiline_comments' panicked at 'assertion failed: `(left == right)`
left: `Ok(("*/", "abcnndef"))`,
right: `Ok(("", "/*abcnndef*/"))`'

所以我的问题是,我如何获得完整的评论,包括结尾的*/

谢谢!

我假设您并不真的希望返回的字符串前面的/*和后面的*/都完好无损——因为preceded总是丢弃第一个解析器中的匹配,所以使用preceded永远不会得到匹配。我想您主要关心的是确保最后的*/被实际消耗掉。

为此,您可以使用delimited而不是preceded:

fn multiline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
delimited(tag("/*"), is_not("*/"), tag("*/"))(i)
}

这通过了这个测试:

assert_eq!(
multiline_comment1::<(&str, ErrorKind)>("/*abcnndef*/"),
Ok(("", "abcnndef"))
);

因此可以确定关闭的CCD_ 10已经被消耗。

只是添加到harmic 的答案中

你会想做

fn multiline_comment<'a, E: ParseError<&'a str>>(s: &'a str) -> IResult<&'a str, &'a str, E> {
delimited(tag("/*"), take_until("*/"), tag("*/"))(s)
}

注意:我们使用take_until()而不是is_not()

当命中模式中的任何字符时,is_not都将停止,这意味着如果注释中的任何位置都有*/,它将无法解析。

最初的问题是使用take_until,但只是想让以后遇到这个问题的人更清楚。

相关内容

  • 没有找到相关文章

最新更新