diff --git a/conf.pest b/conf.pest index 3b8810b..5ed23cc 100644 --- a/conf.pest +++ b/conf.pest @@ -1,3 +1,5 @@ -world = { ASCII_DIGIT+ ~ " " ~ ASCII_DIGIT+ } -robot_init = { ASCII_DIGIT+ ~ " " ~ ASCII_DIGIT+ ~ " " ~ ("S" | "N" | "W" | "E") } -robot_instructions = { ASCII_ALPHA_UPPER+ } +World = { HeaderWorld ~ NEWLINE+ ~ Robot+ } +HeaderWorld = { ASCII_DIGIT+ ~ " " ~ ASCII_DIGIT+ } +Robot = { HeaderRobot ~ NEWLINE ~ Instructions ~ NEWLINE+ } +HeaderRobot = { ASCII_DIGIT+ ~ " " ~ ASCII_DIGIT+ ~ " " ~ ("S" | "N" | "W" | "E") } +Instructions = { ("F" | "L" | "R")+ } diff --git a/src/main.rs b/src/main.rs index a3e574e..68460dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,77 +75,71 @@ fn gen_random_instructions() -> String { /// Parse the config file, generate the world and robot pool. fn parse_config(conf: String, pool: &mut Vec) -> Result { - let mut lines: Vec<&str> = conf.split('\n').collect(); - let raw_world = match ConfParser::parse(Rule::world, lines.remove(0)) { - Ok(s) => s.as_str(), - Err(_) => return Err(String::from("World config is broken.")), + let pairs = match ConfParser::parse(Rule::World, &conf) { + Ok(p) => p, + Err(_) => return Err(String::from("Config is broken.")), }; - let mut w: Vec = Vec::with_capacity(2); - for n in raw_world.split_whitespace() { - let v: i32 = n.parse::().unwrap(); - w.push(v); + + let mut world = world::World { x: 0, y: 0 }; + let mut id = 1; + for pair in pairs { + for inner in pair.into_inner() { + match inner.as_rule() { + Rule::HeaderWorld => { + let mut w: Vec = Vec::with_capacity(2); + for n in inner.as_str().split_whitespace() { + let v: i32 = n.parse::().unwrap(); + w.push(v); + } + world = world::World { x: w[0], y: w[1] }; + } + Rule::Robot => { + let mut vpos: Vec = Vec::new(); + let mut vor: Vec = Vec::new(); + let mut vinst: Vec> = Vec::new(); + for inner_robot in inner.into_inner() { + match inner_robot.as_rule() { + Rule::HeaderRobot => { + let mut setup = inner_robot.as_str().split_whitespace(); + let rx = setup.next().unwrap(); + let ry = setup.next().unwrap(); + let ro = setup.next().unwrap(); + vpos.push(robot::Position { + x: rx.parse::().unwrap(), + y: ry.parse::().unwrap(), + }); + vor.push(match ro { + "N" => robot::Orientation::N, + "E" => robot::Orientation::E, + "S" => robot::Orientation::S, + _ => robot::Orientation::W, + }) + } + Rule::Instructions => { + let instructions = inner_robot.as_str(); + vinst.push(robot::instructions_from_string( + instructions.chars().rev().collect::(), + )?); + let r = robot::Robot::new( + id, + vor.pop().unwrap(), + vpos.pop().unwrap(), + vinst.pop().unwrap(), + ); + match check_map(&r, &world) { + Ok(()) => pool.push(r), + Err(err) => return Err(err), + } + id += 1; + } + _ => unreachable!(), + } + } + } + _ => unreachable!(), + }; + } } - let world = world::World { x: w[0], y: w[1] }; - lines.remove(0); - let mut r_id: u32 = 0; - loop { - r_id += 1; - if lines.len() == 0 { - break; - } - let raw_setup = match ConfParser::parse(Rule::robot_init, lines.remove(0)) { - Ok(s) => s.as_str(), - Err(_) => return Err(String::from("Robot setup is broken.")), - }; - - let rand_instructions = gen_random_instructions(); - let l = lines.remove(0); - - let instructions = match ConfParser::parse(Rule::robot_instructions, l) { - Ok(s) => s.as_str(), - Err(_) => rand_instructions.as_str(), - }; - - let mut setup = raw_setup.split_whitespace(); - let pos_x = setup.next().unwrap(); - let pos_y = setup.next().unwrap(); - let orientation = setup.next().unwrap(); - // Convert values of the setup line - let r_x = pos_x.parse::().unwrap(); - let r_y = pos_y.parse::().unwrap(); - let r_o = match orientation { - "N" => robot::Orientation::N, - "E" => robot::Orientation::E, - "S" => robot::Orientation::S, - "W" => robot::Orientation::W, - _ => { - return Err(String::from( - "The third token of the setup line do not match any orientations !", - )) - } - }; - if !robot::is_instructions(instructions) { - return Err(String::from("Invalid instructions !")); - } - - let inst = robot::instructions_from_string(instructions.chars().rev().collect::())?; - - let r = robot::Robot::new(r_id, r_o, robot::Position { x: r_x, y: r_y }, inst); - // Load robot inside the pool. - match check_map(&r, &world) { - Ok(()) => pool.push(r), - Err(err) => return Err(err), - } - - if lines.len() == 0 { - break; - } - if l.len() == 0 { - continue; - } - lines.remove(0); - } - Ok(world) } diff --git a/src/robot.rs b/src/robot.rs index 6d12f87..79c9877 100644 --- a/src/robot.rs +++ b/src/robot.rs @@ -9,7 +9,7 @@ pub struct Robot { pub id: u32, pub o: Orientation, pub p: Position, - i: Vec, + pub i: Vec, } impl Robot {