summaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
authortslil clingman <>2020-01-19 23:26:29 -0800
committertslil clingman <>2020-01-19 23:26:29 -0800
commit8110985e6636e511f0a2e85a6f30aa8ff109320d (patch)
tree7e6c1b38d04db474aac5cdac2593878f167cac8a /src/parser.rs
parent4d18fad08c185e07d030f6574963ec6de8441ee5 (diff)
Parsing `by hand', gui in separate module
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs134
1 files changed, 134 insertions, 0 deletions
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<Action, String> {
+ 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<u8> = 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::<u32>();
+ 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<Action, String> {
+ Ok(Action::Place(player, Position { x: 0, y: 0 }, Stone::Flat))
+}
+
+pub fn parse_action(player: Player, act: &str) -> Result<Action, String> {
+ if act
+ .chars()
+ .any(|c| c == '+' || c == '-' || c == '>' || c == '<')
+ {
+ parse_move(player, act)
+ } else {
+ parse_place(player, act)
+ }
+}
+
+// fn parse_move(mv: &str) -> Result<Action, Err<&str>> {
+// one_of!("abcdefgh");
+// Ok(Action::Place(
+// Player::Black,
+// Position { x: 0, y: 0 },
+// Stone::Flat,
+// ))
+// }
+
+// fn parse_place(pl: &str) -> Result<Action, Err<&str>> {
+// Ok(Action::Place(
+// Player::Black,
+// Position { x: 0, y: 0 },
+// Stone::Flat,
+// ))
+// }
+
+// pub fn parse_action(act: &str) -> Result<Action, Err<&str>> {
+// if act
+// .chars()
+// .any(|c| c == '+' || c == '-' || c == '>' || c == '<')
+// {
+// parse_move(act)
+// } else {
+// parse_place(act)
+// }
+// }