68 lines
1.9 KiB
Rust
68 lines
1.9 KiB
Rust
|
|
use nom::{
|
|
branch::alt,
|
|
bytes::complete::{tag_no_case, take_while1},
|
|
character::{
|
|
complete::{space0, space1},
|
|
*,
|
|
},
|
|
combinator::{map, map_opt, opt},
|
|
sequence::tuple,
|
|
IResult,
|
|
};
|
|
|
|
use crate::Direction;
|
|
|
|
pub fn optional_separator<'a>(sep: char) -> impl FnMut(&'a str) -> IResult<&'a str, ()> {
|
|
map(
|
|
alt((
|
|
map(tuple((space0, complete::char(sep), space0)), std::mem::drop),
|
|
map(space1, std::mem::drop),
|
|
)),
|
|
std::mem::drop,
|
|
)
|
|
}
|
|
|
|
pub fn parse_direction(i: &str) -> IResult<&str, Direction> {
|
|
alt((
|
|
map(tag_no_case("north"), |_| Direction::North),
|
|
map(tag_no_case("south"), |_| Direction::South),
|
|
map(tag_no_case("east"), |_| Direction::East),
|
|
map(tag_no_case("west"), |_| Direction::West),
|
|
map(tag_no_case("n"), |_| Direction::North),
|
|
map(tag_no_case("s"), |_| Direction::South),
|
|
map(tag_no_case("e"), |_| Direction::East),
|
|
map(tag_no_case("w"), |_| Direction::West),
|
|
))(i)
|
|
}
|
|
|
|
pub fn parse_f64(i: &str) -> IResult<&str, f64> {
|
|
map_opt(
|
|
tuple((
|
|
opt(complete::char('-')),
|
|
take_while1(|c: char| c.is_ascii_digit() || c == '.'),
|
|
)),
|
|
|(neg, n_str): (Option<char>, &str)| {
|
|
n_str
|
|
.parse::<f64>()
|
|
.map(|n| n * if neg.is_some() { -1.0_f64 } else { 1.0_f64 })
|
|
.ok()
|
|
},
|
|
)(i)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_parse_f64() {
|
|
assert_eq!(parse_f64("1"), Ok(("", 1_f64)));
|
|
assert_eq!(parse_f64("1.0"), Ok(("", 1.0_f64)));
|
|
assert_eq!(parse_f64("1.0e2"), Ok(("e2", 1.0_f64)));
|
|
assert_eq!(parse_f64("1.0x"), Ok(("x", 1.0_f64)));
|
|
assert_eq!(parse_f64("-1.0x"), Ok(("x", -1.0_f64)));
|
|
assert_eq!(parse_f64("-1.0-x"), Ok(("-x", -1.0_f64)));
|
|
}
|
|
}
|