use std::cmp::Ordering; use gentoo_utils::{ Parseable, atom::{Atom, Cpv}, }; use mon::{Parser, input::InputIter, tag}; static PORTHOLE_TXT: &'static str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/testdata/porthole.txt" )); enum Operator { Comment, Yes, No, Eq, Gt, Lt, } fn parse_operator<'a>() -> impl Parser<&'a str, Output = Operator> { let comment = tag("***").map(|_| Operator::Comment); let yes = tag("+").map(|_| Operator::Yes); let no = tag("-").map(|_| Operator::No); let eq = tag("=").map(|_| Operator::Eq); let gt = tag(">").map(|_| Operator::Gt); let lt = tag("<").map(|_| Operator::Lt); comment.or(yes).or(no).or(eq).or(gt).or(lt) } #[test] fn test_porthole() { for line in PORTHOLE_TXT.lines() { if line.is_empty() { continue; } let operator = parse_operator() .parse_finished(InputIter::new( line.split_ascii_whitespace().nth(0).unwrap(), )) .unwrap(); match &operator { Operator::Comment => continue, Operator::Yes => { let a = Atom::parser() .parse_finished(InputIter::new( line.split_ascii_whitespace().nth(1).unwrap(), )) .unwrap(); assert_eq!( line.split_ascii_whitespace().nth(1).unwrap(), &a.to_string() ); } Operator::No => { assert!( Atom::parser() .parse_finished(InputIter::new( line.split_ascii_whitespace().nth(1).unwrap() )) .is_err() ); } Operator::Eq | Operator::Gt | Operator::Lt => { let a = Cpv::parser() .parse_finished(InputIter::new( line.split_ascii_whitespace().nth(1).unwrap(), )) .unwrap(); let b = Cpv::parser() .parse_finished(InputIter::new( line.split_ascii_whitespace().nth(2).unwrap(), )) .unwrap(); assert_eq!( a.partial_cmp(&b).unwrap(), match &operator { Operator::Eq => Ordering::Equal, Operator::Gt => Ordering::Greater, Operator::Lt => Ordering::Less, _ => unreachable!(), } ); } } } }