// #[macro_use] // extern crate nom; // use nom::*; use crate::game::*; fn parse_move(player: Player, mv: &str) -> Result { let mut chars = mv.chars(); let c = chars.next(); if c.is_none() { return Err(String::from("Empty string cannot be parsed.")); } let dc = c.unwrap(); if (dc < '1') || ('9' < dc) { return Err(String::from( "Moves must begin with a digit in 1-8 indicating the number of drops.", )); } let sum_drops = dc.to_digit(10).unwrap(); let c = chars.next(); if c.is_none() { return Err(String::from("Moves must specify a stack position.")); } let x = c.unwrap(); if (x < 'a') || (x > 'h') { return Err(String::from( "Moves must specify a position on the game board.", )); } let x: u8 = x as u8 - 'a' as u8; let c = chars.next(); if c.is_none() { return Err(String::from("Moves must specify a stack position.")); } let y = c.unwrap(); if (y < '1') || (y > '8') { return Err(String::from( "Moves must specify a position on the game board.", )); } let y: u8 = (y.to_digit(10).unwrap() - 1) as u8; let c = chars.next(); if c.is_none() { return Err(String::from("Moves must specify a move direction.")); } let c = c.unwrap(); let mut dir = Direction::Up; match c { '+' => dir = Direction::Up, '-' => dir = Direction::Down, '<' => dir = Direction::Left, '>' => dir = Direction::Right, _ => return Err(String::from("The valid directions are +,-,<, and >.")), } let mut drops: Vec = Vec::new(); for d in chars { if let Some(u) = d.to_digit(10) { if u > 9 { return Err(String::from( "No more than 8 pieces may be dropped on a given square.", )); } else { drops.push(u as u8) } } else { return Err(String::from( "A move must specify a number of pieces dropped for each square.", )); } } let sum = drops.iter().map(|&d| d as u32).sum::(); if sum != sum_drops { return Err(format!( "The move called for {} stones, but {} were dropped.", sum_drops, sum )); } Ok(Action::Move(player, Position { x: x, y: y }, dir, drops)) } fn parse_place(player: Player, pl: &str) -> Result { Ok(Action::Place(player, Position { x: 0, y: 0 }, Stone::Flat)) } pub fn parse_action(player: Player, act: &str) -> Result { if act .chars() .any(|c| c == '+' || c == '-' || c == '>' || c == '<') { parse_move(player, act) } else { parse_place(player, act) } } // fn parse_move(mv: &str) -> Result> { // one_of!("abcdefgh"); // Ok(Action::Place( // Player::Black, // Position { x: 0, y: 0 }, // Stone::Flat, // )) // } // fn parse_place(pl: &str) -> Result> { // Ok(Action::Place( // Player::Black, // Position { x: 0, y: 0 }, // Stone::Flat, // )) // } // pub fn parse_action(act: &str) -> Result> { // if act // .chars() // .any(|c| c == '+' || c == '-' || c == '>' || c == '<') // { // parse_move(act) // } else { // parse_place(act) // } // }