use yap::Tokens; use crate::parsing::{newline, parse_digit}; use super::model::SnailfishNumber; pub fn parse_regular(tokens: &mut impl Tokens) -> Option { parse_digit(tokens).map(|digit: isize| digit.into()) } pub fn parse_pair(tokens: &mut impl Tokens) -> Option { tokens.optional(|t| { if !t.token('[') { return None; } let lhs = parse_snailfish_number(t)?; if !t.token(',') { return None; } let rhs = parse_snailfish_number(t)?; if !t.token(']') { return None; } Some((lhs, rhs).into()) }) } pub fn parse_snailfish_number(tokens: &mut impl Tokens) -> Option { yap::one_of!(t from tokens; parse_regular(t), parse_pair(t), ) } pub fn parse_number_list(tokens: &mut impl Tokens) -> Option> { tokens.optional(|t| { let vec: Vec = t .sep_by(|t| parse_snailfish_number(t), |t| newline(t)) .collect(); if !vec.is_empty() { Some(vec) } else { None } }) } #[cfg(test)] mod test { use yap::IntoTokens; #[test] fn test_parsing() { let number = super::parse_snailfish_number( &mut "[[[[1,3],[5,3]],[[1,3],[8,7]]],[[[4,9],[6,9]],[[8,2],[7,3]]]]".into_tokens(), ); assert_eq!( number, Some( ( (((1, 3), (5, 3)), ((1, 3), (8, 7))), (((4, 9), (6, 9)), ((8, 2), (7, 3))) ) .into() ) ); } }