Skip to main content

openpql_range_parser/ast/
list.rs

1use super::{
2    Display, Error, LalrError, Loc, RangeCard, RankConst, SuitConst, ToString,
3};
4
5/// Element of a bracketed card list.
6#[derive(Copy, Clone, PartialEq, Eq, Debug, Display)]
7pub enum ListElem {
8    /// Concrete rank and concrete suit.
9    #[display("{_0}{_1}")]
10    CC(RankConst, SuitConst),
11    /// Concrete rank with any suit.
12    #[display("{_0}")]
13    CA(RankConst),
14    /// Any rank with concrete suit.
15    #[display("{_0}")]
16    AC(SuitConst),
17}
18
19fn to_str(elems: &[ListElem]) -> String {
20    format!(
21        "[{}]",
22        elems
23            .iter()
24            .map(ToString::to_string)
25            .collect::<Vec<_>>()
26            .join(",")
27    )
28}
29
30/// Bracketed list of simple cards.
31#[derive(Clone, PartialEq, Eq, Debug, derive_more::From, Display)]
32#[display("{}", to_str(_0))]
33pub struct List(pub Vec<ListElem>);
34
35impl TryFrom<(Loc, Vec<RangeCard>, Loc)> for List {
36    type Error = LalrError<'static>;
37
38    fn try_from(
39        (l, v, r): (Loc, Vec<RangeCard>, Loc),
40    ) -> Result<Self, Self::Error> {
41        let mut inner = vec![];
42
43        for c in v {
44            match c {
45                RangeCard::CC(r, s) => {
46                    inner.push(ListElem::CC(r, s));
47                }
48                RangeCard::CA(r) => {
49                    inner.push(ListElem::CA(r));
50                }
51                RangeCard::AC(s) => {
52                    inner.push(ListElem::AC(s));
53                }
54                _ => {
55                    return Err(Error::InvalidList((l, r)).into());
56                }
57            }
58        }
59
60        Ok(Self(inner))
61    }
62}
63
64#[cfg(test)]
65#[cfg_attr(coverage_nightly, coverage(off))]
66mod tests {
67    use super::*;
68    use crate::*;
69
70    fn assert_list(src: &str, expected: &str) {
71        let list = parse_list(src).unwrap();
72
73        assert_eq!(list.to_string(), expected, "{src} != {expected}");
74    }
75
76    #[quickcheck]
77    fn test_list(c: RangeCard) {
78        let src = format!("[{c}]");
79        let res = parse_list(&src);
80
81        let is_err = match c {
82            RangeCard::CC(_, _) | RangeCard::CA(_) | RangeCard::AC(_) => false,
83            RangeCard::CV(_, _)
84            | RangeCard::VC(_, _)
85            | RangeCard::VV(_, _)
86            | RangeCard::VA(_)
87            | RangeCard::AV(_)
88            | RangeCard::AA => true,
89        };
90
91        if is_err {
92            assert_eq!(res, Err(Error::InvalidList((0, src.len())).into()));
93        } else {
94            assert_eq!(res, Ok((0, vec![c], 0).try_into().unwrap()));
95        }
96    }
97
98    #[test]
99    fn test_list_ok() {
100        assert_list("[A, s]", "[A,s]");
101    }
102
103    #[test]
104    fn test_list_error() {
105        assert_eq!(parse_list("[B] "), Err(Error::InvalidList((0, 3)).into()));
106        assert_eq!(parse_list("[Bs]"), Err(Error::InvalidList((0, 4)).into()));
107        assert_eq!(parse_list("[*w]"), Err(Error::InvalidList((0, 4)).into()));
108        assert_eq!(parse_list("[Aw]"), Err(Error::InvalidList((0, 4)).into()));
109        assert_eq!(parse_list("[Bw]"), Err(Error::InvalidList((0, 4)).into()));
110        assert_eq!(parse_list("[*] "), Err(Error::InvalidList((0, 3)).into()));
111    }
112}