我正在尝试编写一个识别多行注释的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
,但只是想让以后遇到这个问题的人更清楚。