|
|
|
@ -214,6 +214,139 @@ impl Entity {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)] |
|
|
|
|
pub struct EntityParser { |
|
|
|
|
buffer: String, |
|
|
|
|
entities: Vec<Entity>, |
|
|
|
|
parse_error: bool, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl EntityParser { |
|
|
|
|
pub fn new(s: &str) -> Self { |
|
|
|
|
EntityParser { |
|
|
|
|
buffer: String::from(s), |
|
|
|
|
entities: Vec::new(), |
|
|
|
|
parse_error: false, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn result(&self) -> Option<Vec<Entity>> { |
|
|
|
|
if self.parse_error { return None; } |
|
|
|
|
return Some(self.entities.clone()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn next(&mut self) -> String { |
|
|
|
|
self.buffer = self.buffer.chars().skip_while(|c| *c == ' ' || *c == '\n').collect(); |
|
|
|
|
|
|
|
|
|
let mut s = String::from(""); |
|
|
|
|
let mut skip_count = 0; |
|
|
|
|
for c in self.buffer.chars() { |
|
|
|
|
skip_count += 1; |
|
|
|
|
if c == ' ' { break; } |
|
|
|
|
s.push(c); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
self.buffer = self.buffer.chars().skip(skip_count).collect(); |
|
|
|
|
println!("NEXT: '{}'", s); |
|
|
|
|
s |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn is_eof(&self) -> bool { self.buffer.is_empty() } |
|
|
|
|
|
|
|
|
|
pub fn s(&mut self) -> &mut Self { |
|
|
|
|
let s = self.next(); |
|
|
|
|
if s.is_empty() { self.parse_error = true; return self; } |
|
|
|
|
self.entities.push(Entity::String(s)); |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn i(&mut self) -> &mut Self { |
|
|
|
|
let s = self.next(); |
|
|
|
|
if let Ok(i) = s.parse::<u32>() { |
|
|
|
|
self.entities.push(Entity::Int(i)); |
|
|
|
|
} else { |
|
|
|
|
self.parse_error = true; |
|
|
|
|
} |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn f(&mut self) -> &mut Self { |
|
|
|
|
let s = self.next(); |
|
|
|
|
if let Ok(f) = s.parse::<f32>() { |
|
|
|
|
self.entities.push(Entity::Float(f)); |
|
|
|
|
} else { |
|
|
|
|
self.parse_error = true; |
|
|
|
|
} |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn color(&mut self) -> &mut Self { |
|
|
|
|
let s = self.next(); |
|
|
|
|
let s = s.to_lowercase(); |
|
|
|
|
if s == "w" || s == "white" { self.entities.push(Entity::Color(Color::W)); return self; } |
|
|
|
|
if s == "b" || s == "black" { self.entities.push(Entity::Color(Color::B)); return self; } |
|
|
|
|
self.parse_error = true; |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn vertex(&mut self) -> &mut Self { |
|
|
|
|
let s = self.next(); |
|
|
|
|
let s = s.to_uppercase(); |
|
|
|
|
if s == "PASS" { self.entities.push(Entity::Vertex((0, 0))); return self; } |
|
|
|
|
if s.len() < 2 || s.len() > 3 { |
|
|
|
|
self.parse_error = true; |
|
|
|
|
return self; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let h = s.chars().nth(0).unwrap(); |
|
|
|
|
if !h.is_ascii_alphabetic() { |
|
|
|
|
self.parse_error = true; |
|
|
|
|
return self; |
|
|
|
|
} |
|
|
|
|
let h = h as u32; |
|
|
|
|
let mut h = (h - ('A' as u32)) + 1; |
|
|
|
|
if h > 8 { h -= 1; } |
|
|
|
|
|
|
|
|
|
let v : String = s.chars().skip(1).collect(); |
|
|
|
|
if let Ok(v) = i32::from_str_radix(&v, 10) { |
|
|
|
|
self.entities.push(Entity::Vertex((h as i32, v))); |
|
|
|
|
} else { |
|
|
|
|
self.parse_error = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn mv(&mut self) -> &mut Self { |
|
|
|
|
self.color(); |
|
|
|
|
if self.parse_error { return self; } |
|
|
|
|
self.vertex(); |
|
|
|
|
if self.parse_error { self.entities.pop(); } |
|
|
|
|
|
|
|
|
|
let m = self.entities.pop().unwrap(); |
|
|
|
|
let c = self.entities.pop().unwrap(); |
|
|
|
|
|
|
|
|
|
if let Entity::Vertex((h, v)) = m { |
|
|
|
|
if let Entity::Color(c) = c { |
|
|
|
|
self.entities.push(Entity::Move((c, (h, v)))); |
|
|
|
|
return self; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
self.parse_error = true; |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn bool(&mut self) -> &mut Self { |
|
|
|
|
let s = self.next(); |
|
|
|
|
let s = s.to_uppercase(); |
|
|
|
|
if s == "TRUE" { self.entities.push(Entity::Boolean(true)); return self; } |
|
|
|
|
if s == "FALSE" { self.entities.push(Entity::Boolean(false)); return self; } |
|
|
|
|
self.parse_error = true; |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)] |
|
|
|
|
pub struct Command { |
|
|
|
|
id: Option<u32>, |
|
|
|
|
name: String, |
|
|
|
@ -300,6 +433,10 @@ impl ResponseParser {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn next_line(&mut self) -> Option<String> { |
|
|
|
|
self.buffer = |
|
|
|
|
self.buffer.chars() |
|
|
|
|
.skip_while(|c| *c == ' ' || *c == '\x09').collect(); |
|
|
|
|
|
|
|
|
|
let mut s = String::from(""); |
|
|
|
|
|
|
|
|
|
let mut skip_count = 0; |
|
|
|
|