myopic_board/parse/
patterns.rs

1use std::str::FromStr;
2
3use regex::Regex;
4
5pub fn space() -> &'static Regex {
6    lazy_static! {
7        static ref RE: Regex = rgx(SPACE.to_owned());
8    }
9    &RE
10}
11
12pub fn file() -> &'static Regex {
13    lazy_static! {
14        static ref RE: Regex = rgx(FILE.to_owned());
15    }
16    &RE
17}
18
19pub fn rank() -> &'static Regex {
20    lazy_static! {
21        static ref RE: Regex = rgx(RANK.to_owned());
22    }
23    &RE
24}
25
26pub fn square() -> &'static Regex {
27    lazy_static! {
28        static ref RE: Regex = rgx(SQUARE.to_owned());
29    }
30    &RE
31}
32
33pub fn fen() -> &'static Regex {
34    lazy_static! {
35        static ref RE: Regex = rgx(format!(
36            r"{} {} {} {} {} {}",
37            fen_positions().as_str(),
38            FEN_SIDE,
39            FEN_RIGHTS,
40            FEN_EP,
41            INT,
42            INT
43        ));
44    }
45    &RE
46}
47
48pub fn fen_positions() -> &'static Regex {
49    lazy_static! {
50        static ref RE: Regex = rgx(format!(r"(({}/){{7}}{})", FEN_RNK, FEN_RNK));
51    }
52    &RE
53}
54
55pub fn fen_rank() -> &'static Regex {
56    lazy_static! {
57        static ref RE: Regex = rgx(FEN_RNK.to_owned());
58    }
59    &RE
60}
61
62pub fn fen_rights() -> &'static Regex {
63    lazy_static! {
64        static ref RE: Regex = rgx(format!("{}", FEN_RIGHTS));
65    }
66    &RE
67}
68
69pub fn pgn_piece() -> &'static Regex {
70    lazy_static! {
71        static ref RE: Regex = rgx(PGN_PIECE.to_owned());
72    }
73    &RE
74}
75
76pub fn pgn_move() -> &'static Regex {
77    lazy_static! {
78        static ref RE: Regex = rgx(format!(
79            "({}|{})",
80            pgn_non_castle_move().as_str(),
81            pgn_castle_move().as_str()
82        ));
83    }
84    &RE
85}
86
87pub fn pgn_castle_move() -> &'static Regex {
88    lazy_static! {
89        static ref RE: Regex = rgx(PGN_CASTLE.to_owned());
90    }
91    &RE
92}
93
94pub fn pgn_non_castle_move() -> &'static Regex {
95    lazy_static! {
96        static ref RE: Regex = rgx(format!(
97            r"({}?({}|{}|{})?x?{}(=[NBRQ])?[+#]?)",
98            PGN_PIECE, RANK, FILE, SQUARE, SQUARE
99        ));
100    }
101    &RE
102}
103
104pub fn uci_move() -> &'static Regex {
105    lazy_static! {
106        static ref RE: Regex = rgx(UCI_MOVE.to_owned());
107    }
108    &RE
109}
110
111type StrConst = &'static str;
112
113/// Standard patterns
114const FILE: StrConst = r"([a-h])";
115const RANK: StrConst = r"([1-8])";
116const SQUARE: StrConst = r"([a-h][1-8])";
117const INT: StrConst = "([0-9]+)";
118const SPACE: StrConst = r"(\s+)";
119
120/// PGN patterns
121const PGN_PIECE: StrConst = r"(N|B|R|Q|K)";
122const PGN_CASTLE: StrConst = r"(O-O(-O)?)";
123
124/// FEN patterns
125const FEN_RNK: StrConst = "([pnbrqkPNBRQK1-8]{1,8})";
126const FEN_SIDE: StrConst = "([bw])";
127const FEN_RIGHTS: StrConst = r"(-|([kqKQ]{1,4}))";
128const FEN_EP: StrConst = r"(-|([a-h][1-8]))";
129
130/// UCI patterns
131const UCI_MOVE: StrConst = r"(([a-h][1-8]){2}[nbrq]?)";
132
133fn rgx(pattern: String) -> Regex {
134    Regex::from_str(pattern.as_ref()).unwrap()
135}
136
137#[cfg(test)]
138mod test {
139    use super::*;
140
141    #[test]
142    fn test_fen_regex() {
143        assert!(fen().is_match("4r1r1/pb1Q2bp/1p1Rnkp1/5p2/2P1P3/4BP2/qP2B1PP/2R3K1 w - - 1 0"));
144        assert!(fen().is_match("3r4/4RRpk/5n1N/8/p1p2qPP/P1Qp1P2/1P4K1/3b4 w Qk c2 5 21"));
145        assert!(fen().is_match("8/7p/4Nppk/R7/6PP/3n2K1/Pr6/8 w KkQq - 0 10"));
146    }
147
148    #[test]
149    fn test_move_regex() {
150        let re = pgn_move();
151        assert!(re.is_match("e4"));
152        assert!(re.is_match("Re1"));
153        assert!(re.is_match("Nf3"));
154        assert!(re.is_match("Bxf7+"));
155        assert!(re.is_match("Qe4xe7#"));
156        assert!(re.is_match("fxg8+"));
157        assert!(re.is_match("dxc8=Q+"))
158    }
159
160    #[test]
161    fn test_uci_move_regex() {
162        let re = uci_move();
163        assert!(re.is_match("e2e4"));
164        assert!(re.is_match("c7d8q"));
165    }
166}