69 lines
1.7 KiB
Rust
69 lines
1.7 KiB
Rust
use yap::Tokens;
|
|
|
|
use crate::parsing::{newline, parse_digit};
|
|
|
|
use super::model::SnailfishNumber;
|
|
|
|
pub fn parse_regular(tokens: &mut impl Tokens<Item = char>) -> Option<SnailfishNumber> {
|
|
parse_digit(tokens).map(|digit: isize| digit.into())
|
|
}
|
|
|
|
pub fn parse_pair(tokens: &mut impl Tokens<Item = char>) -> Option<SnailfishNumber> {
|
|
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<Item = char>) -> Option<SnailfishNumber> {
|
|
yap::one_of!(t from tokens;
|
|
parse_regular(t),
|
|
parse_pair(t),
|
|
)
|
|
}
|
|
|
|
pub fn parse_number_list(tokens: &mut impl Tokens<Item = char>) -> Option<Vec<SnailfishNumber>> {
|
|
tokens.optional(|t| {
|
|
let vec: Vec<SnailfishNumber> = 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()
|
|
)
|
|
);
|
|
}
|
|
}
|