myopic_board/parse/
patterns.rs1use 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
113const 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
120const PGN_PIECE: StrConst = r"(N|B|R|Q|K)";
122const PGN_CASTLE: StrConst = r"(O-O(-O)?)";
123
124const 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
130const 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}