2023-03-19 23:19:19 -04:00

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)));
}
}