Merge branch 'parser2' into 'master'

Add shitty parser

See merge request mhart/DancingDroids!36
This commit is contained in:
Martin HART 2020-10-30 16:37:20 +01:00
commit a4760690ec
2 changed files with 149 additions and 7 deletions

View File

@ -46,31 +46,147 @@ fn check_collisions(
}
/// Parse the config file, generate the world and robot pool.
fn parse_config(conf: String, pool: &mut Vec<robot::Robot>) -> Result<world::World, &'static str> {
fn parse_config(conf: String, pool: &mut Vec<robot::Robot>) -> Result<world::World, String> {
let mut lines = conf.lines();
// The first line of the config file should be the World.
let raw_line: &str = match lines.next() {
Some(raw) => raw,
None => return Err("Could not read the first line of the config file !"),
None => {
return Err(String::from(
"Could not read the first line of the config file !",
))
}
};
let mut tokens = raw_line.split_whitespace();
let token1 = match tokens.next() {
Some(raw) => raw,
None => return Err("Could not read the first token of the first line !"),
None => {
return Err(String::from(
"Could not read the first token of the first line !",
))
}
};
let token2 = match tokens.next() {
Some(raw) => raw,
None => return Err("Could not read the second token of the first line !"),
None => {
return Err(String::from(
"Could not read the second token of the first line !",
))
}
};
let x: i32 = match token1.parse::<i32>() {
Ok(x) => x,
Err(_) => return Err("Could not convert token one from the first string to i32"),
Err(_) => {
return Err(String::from(
"Could not convert token one from the first string to i32",
))
}
};
let y: i32 = match token2.parse::<i32>() {
Ok(x) => x,
Err(_) => return Err("Could not convert token two from the first string to i32"),
Err(_) => {
return Err(String::from(
"Could not convert token two from the first string to i32",
))
}
};
Ok(world::World { x, y })
let w = world::World { x, y };
let mut r_id: u32 = 0;
loop {
r_id += 1;
// This line should be empty.
let empty_line = match lines.next() {
None => break,
Some(x) => x,
};
if !empty_line.is_empty() {
return Err(String::from("This line should be empty !"));
}
let raw_setup = match lines.next() {
None => return Err(String::from("This line should be the config !")),
Some(raw) => raw,
};
if raw_setup.is_empty() {
return Err(String::from("This line should not be empty !"));
}
let raw_inst = match lines.next() {
None => return Err(String::from("This line should be the instruction !")),
Some(raw) => raw,
};
if raw_inst.is_empty() {
return Err(String::from("This line should not be empty !"));
}
// Parse the setup line of the robot.
let mut setup = raw_setup.split_whitespace();
let pos_x = match setup.next() {
None => {
return Err(String::from(
"Could not read the first token of the setup line !",
))
}
Some(raw) => raw,
};
let pos_y = match setup.next() {
None => {
return Err(String::from(
"Could not read the second token of the setup line !",
))
}
Some(raw) => raw,
};
let orientation = match setup.next() {
None => {
return Err(String::from(
"Could not read the third token of the setup line !",
))
}
Some(raw) => raw,
};
// Convert values of the setup line
let r_x = match pos_x.parse::<i32>() {
Err(_) => {
return Err(String::from(
"Could not convert the first token of the setup ligne to i32 !",
))
}
Ok(raw) => raw,
};
let r_y = match pos_y.parse::<i32>() {
Err(_) => {
return Err(String::from(
"Could not convert the second token of the setup ligne to i32 !",
))
}
Ok(raw) => raw,
};
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 !",
))
}
};
// Convert instructions line.
let inst: Vec<char> = raw_inst.chars().collect();
if !world::is_instructions(&inst) {
return Err(String::from("Invalid instructions !"));
}
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, &w) {
Ok(()) => pool.push(r),
Err(err) => return Err(err),
}
}
Ok(w)
}
/// Retrieve the content of a file and return it as a string.

View File

@ -56,6 +56,19 @@ pub struct Position {
pub y: i32,
}
/// Check if instructions list is valid.
pub fn is_instructions(v: &Vec<char>) -> bool {
for c in v {
match c {
'F' => continue,
'R' => continue,
'L' => continue,
_ => return false,
}
}
true
}
#[cfg(test)]
mod tests {
use super::*;
@ -95,4 +108,17 @@ mod tests {
assert_eq!(r.p.x, 0);
assert_eq!(r.p.y, 3);
}
#[test]
fn is_instructions_test() {
let v = vec!['F', 'R', 'L', 'F'];
assert!(is_instructions(&v));
}
#[test]
#[should_panic]
fn is_instructions_test_fail() {
let v = vec!['F', 'R', 'L', 'Z'];
assert!(is_instructions(&v));
}
}