use std::cmp::Ordering; use gentoo_utils::{ Parseable, atom::{Cp, Cpv}, }; use mon::{Parser, ParserIter, input::InputIter, tag}; static PORTHOLE_TXT: &'static str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/testdata/porthole.txt" )); enum Operator { Cpv(bool), Cp(bool), Eq, Ne, Gt, Lt, } fn parse_operator<'a>() -> impl Parser<&'a str, Output = Operator> { let cpvyes = tag("cpv+").map(|_: &str| Operator::Cpv(true)); let cpvno = tag("cpv-").map(|_: &str| Operator::Cpv(false)); let cpyes = tag("cp+").map(|_| Operator::Cp(true)); let cpno = tag("cp-").map(|_: &str| Operator::Cp(false)); let eq = tag("=").map(|_| Operator::Eq); let ne = tag("!=").map(|_: &str| Operator::Ne); let gt = tag(">").map(|_| Operator::Gt); let lt = tag("<").map(|_| Operator::Lt); cpvyes .or(cpvno) .or(cpyes) .or(cpno) .or(eq) .or(ne) .or(gt) .or(lt) } #[test] fn test_porthole() { for line in PORTHOLE_TXT.lines() { if line.is_empty() || line.starts_with("*") { continue; } let operator = parse_operator() .parse_finished(InputIter::new( line.split_ascii_whitespace().nth(0).unwrap(), )) .unwrap(); match &operator { Operator::Cpv(is_err) => { let col = line.split_ascii_whitespace().nth(1).unwrap(); let cpv = Cpv::parser().parse_finished(InputIter::new(col)); match (dbg!(cpv), is_err) { (Ok(cpv), true) => { assert_eq!(&cpv.to_string(), col); } (Err(_), false) => (), _ => { panic!("{line}"); } }; } Operator::Cp(is_err) => { let col = line.split_ascii_whitespace().nth(1).unwrap(); let cp = Cp::parser().parse_finished(InputIter::new(col)); match (cp, is_err) { (Ok(cp), true) => { assert_eq!(&cp.to_string(), col); } (Err(_), false) => (), _ => { panic!("{line}"); } }; } Operator::Eq | Operator::Ne => { 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.eq(&b), match &operator { Operator::Eq => true, Operator::Ne => false, _ => unreachable!(), } ); } 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::Gt => Ordering::Greater, Operator::Lt => Ordering::Less, _ => unreachable!(), } ); } } } }