我使用nom板条箱,试图编写一个解析器,该解析器可以从i32
识别带符号的String
数字,即可以将字符串-42
转换为i32
表示形式。
到目前为止,我已经提出了以下建议,但是我未能解析负数:
use nom::types::CompleteStr;
use std::str::FromStr;
named!(
i32_parser<CompleteStr, i32>,
map_res!(nom::digit, |CompleteStr(s)| i32::from_str(s))
);
#[test]
fn parse_i32_positive() {
assert_eq!(
i32_parser(CompleteStr::from("42")),
Ok((CompleteStr::from(""), 42))
);
}
#[test]
fn parse_i32_negative() {
assert_eq!(
i32_parser(CompleteStr::from("-42")),
Ok((CompleteStr::from(""), -42))
);
}
我也尝试了以下方法,但是编译时出现了隐秘的错误:
named!(
i32_parser<CompleteStr, i32>,
map_res!(alt!(char!('-') | nom::digit), |CompleteStr(s)| i32::from_str(s))
);
^ expected char, found struct `nom::types::CompleteStr`
关于如何解决它的任何建议?还是用nom来实现这一目标的更简单方法?
我明确地希望用nom来实现这一点,因为我试图解析一个更复杂的结构。 i32::from_str(s)
适用于简单的字符串,但这不是我想要的。
答案 0 :(得分:2)
recognize!
宏可以为您提供帮助。它返回已解析的输入字符串,而不是解析器输出,然后可以像往常一样将其转换。例如:
named!(i32_parser<&str, i32>,
map_res!(
recognize!(tuple!(opt!(char!('-')), digit)),
FromStr::from_str)
);
答案 1 :(得分:1)
alt!(char!('-') | nom::digit)
“返回”一个字符,因此您的lambda需要接受一个char作为参数。而且可能是'-'
,因此在运行时对其调用i32::from_str
将会失败。
与其将符号和数字同时处理,不如将问题分解为两部分,例如。使用do_parse
。
named!(
i32_parser<CompleteStr, i32>,
do_parse!(
minus: opt!(char!('-')) >>
digits: many1!(digit) >>
({
let sign = if minus.is_some() { -1 } else { 1 };
let mut number = 0;
for digit in digits {
number = number*10 + i32::from_str(digit.0).unwrap();
}
sign * number
})
)
);