Skip to main content

rusty_rubik/
parser.rs

1//! A parser used to parse scramble sequences into a Rust representation.
2
3use crate::cube::*;
4use regex::Regex;
5use std::str::FromStr;
6
7fn parse_base_move(token: &str) -> Result<BaseMoveToken, strum::ParseError> {
8    BaseMoveToken::from_str(token)
9}
10
11/// Parses a scramble sequence from a string.ALL_MOVES
12///
13/// Returns a Result object indicating whether the parse was successful.
14pub fn parse_scramble(scramble: &str) -> Result<Vec<MoveInstance>, strum::ParseError> {
15    let mut parsed = vec![];
16    let re_normal = Regex::new(r"^([UDLRFB])$").unwrap();
17    let re_prime = Regex::new(r"^([UDLRFB])'").unwrap();
18    let re_double = Regex::new(r"^([UDLRFB])2").unwrap();
19    let mut parse_error = "";
20    'tokens: for token in scramble.split_whitespace() {
21        if re_normal.is_match(token) {
22            for cap in re_normal.captures_iter(token) {
23                let basemove = parse_base_move(&cap[1])?;
24                parsed.push(MoveInstance {
25                    basemove,
26                    dir: Direction::Normal,
27                })
28            }
29        } else if re_prime.is_match(token) {
30            for cap in re_prime.captures_iter(token) {
31                let basemove = parse_base_move(&cap[1])?;
32                parsed.push(MoveInstance {
33                    basemove,
34                    dir: Direction::Prime,
35                })
36            }
37        } else if re_double.is_match(token) {
38            for cap in re_double.captures_iter(token) {
39                let basemove = parse_base_move(&cap[1])?;
40                parsed.push(MoveInstance {
41                    basemove,
42                    dir: Direction::Double,
43                })
44            }
45        } else {
46            parse_error = token;
47            break 'tokens;
48        }
49    }
50    if parse_error.len() > 0 {
51        Err(strum::ParseError::VariantNotFound)
52    } else {
53        Ok(parsed)
54    }
55}