在RFC1738中,BNFdomainlabel
如下:
域标签 = 字母数字 | 字母数字 * [ 字母数字 | "-" ] 字母数字
也就是说,它要么是一个字母数字,要么是一个字符串,其中第一个/最后一个字符必须是一个字母数字,但中间字符可以是一个字母数字或破折号。
我如何用nom实现这个?忽略单字符场景以简化案例,我最后的尝试是:
fn domain_label(s: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> {
let left = take_while_m_n(1, 1, is_alphanumeric);
let middle = take_while(|c| is_alphanumeric(c) || c == b'-');
let right = take_while_m_n(1, 1, is_alphanumeric);
let whole = tuple((left, middle, right));
whole(s)
}
这样做的问题是middle
可以消耗最后一个字符,因此right
失败,因为没有要消耗的字符。
println!("{:?}", domain_label(b"abcde"));
Err(Error(([], TakeWhileMN)))
解析器应该能够尝试所有可能的消费路径,但如何做到这一点nom
?