如何使用 nom 将带符号的字符串解析为 i32?
How do I use nom to parse a string with sign into an i32?
使用 nom crate,我正在尝试编写一个解析器来识别 String
中的带符号 i32
数字,即可以转换字符串 -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)
适用于简单的字符串,但这不是我要找的。
alt!(char!('-') | nom::digit)
"returns" 一个字符,所以你的 lambda 需要接受一个字符作为参数。并且它可能是 '-'
,因此在其上调用 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
})
)
);
recognize!
宏可以帮助您。它 returns 解析的输入字符串而不是解析器输出,然后可以像往常一样进行转换。例如:
named!(i32_parser<&str, i32>,
map_res!(
recognize!(tuple!(opt!(char!('-')), digit)),
FromStr::from_str)
);
使用 nom crate,我正在尝试编写一个解析器来识别 String
中的带符号 i32
数字,即可以转换字符串 -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)
适用于简单的字符串,但这不是我要找的。
alt!(char!('-') | nom::digit)
"returns" 一个字符,所以你的 lambda 需要接受一个字符作为参数。并且它可能是 '-'
,因此在其上调用 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
})
)
);
recognize!
宏可以帮助您。它 returns 解析的输入字符串而不是解析器输出,然后可以像往常一样进行转换。例如:
named!(i32_parser<&str, i32>,
map_res!(
recognize!(tuple!(opt!(char!('-')), digit)),
FromStr::from_str)
);