From 8110985e6636e511f0a2e85a6f30aa8ff109320d Mon Sep 17 00:00:00 2001 From: tslil clingman <> Date: Sun, 19 Jan 2020 23:26:29 -0800 Subject: Parsing `by hand', gui in separate module --- src/parser.rs | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/parser.rs (limited to 'src/parser.rs') diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..49ded9b --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,134 @@ +// #[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) +// } +// } -- cgit v1.3.1