aoc-rs-2021/src/day_12/parsing.rs
2021-12-13 07:35:55 +01:00

73 lines
2.1 KiB
Rust

use yap::Tokens;
use crate::parsing::{newline, parse_n};
use super::{Cave, CaveSystem};
pub fn parse_cave_system(tokens: &mut impl Tokens<Item = char>) -> Option<CaveSystem> {
let edges = tokens.sep_by(|t| parse_edge(t), |t| newline(t)).collect();
CaveSystem::new(edges).ok()
}
pub fn parse_edge(tokens: &mut impl Tokens<Item = char>) -> Option<[Cave; 2]> {
parse_n(tokens, |t| parse_cave(t), |t| t.token('-'))
}
pub fn parse_cave(tokens: &mut impl Tokens<Item = char>) -> Option<Cave> {
yap::one_of!(ts from tokens;
parse_start(ts),
parse_end(ts),
parse_big(ts),
parse_small(ts),
)
}
pub fn parse_start(tokens: &mut impl Tokens<Item = char>) -> Option<Cave> {
tokens.tokens("start".chars()).then(|| Cave::Start)
}
pub fn parse_end(tokens: &mut impl Tokens<Item = char>) -> Option<Cave> {
tokens.tokens("end".chars()).then(|| Cave::End)
}
pub fn parse_big(tokens: &mut impl Tokens<Item = char>) -> Option<Cave> {
let cave: String = tokens.tokens_while(|c| c.is_ascii_uppercase()).collect();
(!cave.is_empty()).then(|| Cave::Big(cave))
}
pub fn parse_small(tokens: &mut impl Tokens<Item = char>) -> Option<Cave> {
let cave: String = tokens.tokens_while(|c| c.is_ascii_lowercase()).collect();
(!cave.is_empty()).then(|| Cave::Small(cave))
}
#[cfg(test)]
mod test {
use yap::IntoTokens;
use super::super::Cave;
#[test]
fn parse_cave() {
assert_eq!(
super::parse_cave(&mut "start".into_tokens()),
Some(Cave::Start)
);
assert_eq!(super::parse_cave(&mut "end".into_tokens()), Some(Cave::End));
assert_eq!(
super::parse_cave(&mut "a".into_tokens()),
Some(Cave::Small(String::from("a")))
);
assert_eq!(
super::parse_cave(&mut "BBBB".into_tokens()),
Some(Cave::Big(String::from("BBBB")))
);
}
#[test]
fn parse_edge() {
assert!(super::parse_edge(&mut "start-DX".into_tokens()).is_some());
assert!(super::parse_edge(&mut "a-DX".into_tokens()).is_some());
assert!(super::parse_edge(&mut "AAA-b".into_tokens()).is_some());
}
}