Browse Source

added a parser for GTP entities

master
Weird Constructor 4 years ago
parent
commit
d4229109e1
  1. 137
      src/gtp_client.rs
  2. 11
      src/lib.rs

137
src/gtp_client.rs

@ -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;

11
src/lib.rs

@ -54,6 +54,17 @@ mod tests {
}
#[test]
fn check_entity_parser() {
let mut ep = EntityParser::new("10 10.2 ok WHite t19");
ep.i().f().s().mv();
let res = ep.result().unwrap();
assert_eq!(res[0].to_string(), "10");
assert_eq!(res[1].to_string(), "10.2");
assert_eq!(res[2].to_string(), "ok");
assert_eq!(res[3].to_string(), "w T19");
}
#[test]
fn check_build_command() {
let mut c = Command::new("list_commands");
c.args(|eb| eb.i(10).f(10.20).s("OK").list());

Loading…
Cancel
Save