From 14ea07e4414f83e0cc48611ea2a386589027a1f7 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Mon, 3 Sep 2018 12:27:09 -0700 Subject: [PATCH] [lexer] Move Bool state to its own file --- lexer/src/states/bool.rs | 68 ++++++++++++++++++++++++++++++++ lexer/src/states/hash.rs | 83 +++++++--------------------------------- lexer/src/states/mod.rs | 13 +++++-- 3 files changed, 91 insertions(+), 73 deletions(-) create mode 100644 lexer/src/states/bool.rs diff --git a/lexer/src/states/bool.rs b/lexer/src/states/bool.rs new file mode 100644 index 0000000..20796f2 --- /dev/null +++ b/lexer/src/states/bool.rs @@ -0,0 +1,68 @@ +/* lexer/src/states/bool.rs + * Eryn Wells + */ + +use chars::Lexable; +use states::{Resume, State, StateResult}; +use token::Token; + +const TRUE_SHORT: &'static str = "t"; +const TRUE: &'static str = "true"; +const FALSE_SHORT: &'static str = "f"; +const FALSE: &'static str = "false"; + +#[derive(Debug)] pub struct Bool(String); + +impl Bool { + pub fn new(buf: &str) -> Bool { + Bool(buf.to_string()) + } + + fn handle_delimiter(&self) -> Option { + if self.0 == TRUE || self.0 == TRUE_SHORT { + Some(Token::Bool(true)) + } else if self.0 == FALSE || self.0 == FALSE_SHORT { + Some(Token::Bool(false)) + } else { + None + } + } +} + +impl State for Bool { + fn lex(&mut self, c: char) -> StateResult { + match c { + c if c.is_identifier_delimiter() => match self.handle_delimiter() { + Some(token) => StateResult::Emit(token, Resume::Here), + None => { + let msg = format!("Invalid character: {}", c); + StateResult::fail(msg.as_str()) + }, + }, + _ => { + let buf = { + let mut b = String::from(self.0.as_str()); + b.push(c); + b + }; + if TRUE.starts_with(&buf) || FALSE.starts_with(&buf) { + StateResult::advance(Box::new(Bool(buf))) + } else { + let msg = format!("Invalid character: {}", c); + StateResult::fail(msg.as_str()) + } + }, + } + } + + fn none(&mut self) -> Result, String> { + match self.handle_delimiter() { + Some(token) => Ok(Some(token)), + None => { + let msg = format!("Found EOF while trying to parse a bool"); + Err(msg) + } + } + } +} + diff --git a/lexer/src/states/hash.rs b/lexer/src/states/hash.rs index 1823bb0..14ef37b 100644 --- a/lexer/src/states/hash.rs +++ b/lexer/src/states/hash.rs @@ -2,19 +2,16 @@ * Eryn Wells */ -//! Lexer states for handling tokens that begin with hash marks '#'. - -use chars::Lexable; -use states::{Resume, State, StateResult}; +use states::{State, StateResult}; +use states::bool::Bool; use token::Token; -const TRUE_SHORT: &'static str = "t"; -const TRUE: &'static str = "true"; -const FALSE_SHORT: &'static str = "f"; -const FALSE: &'static str = "false"; +trait HashLexable { + fn is_bool_initial(&self) -> bool; + fn is_slash(&self) -> bool; +} #[derive(Debug)] pub struct Hash; -#[derive(Debug)] pub struct BoolSub(String); impl Hash { pub fn new() -> Hash { Hash{} } @@ -23,14 +20,14 @@ impl Hash { impl State for Hash { fn lex(&mut self, c: char) -> StateResult { match c { - c if TRUE.starts_with(c) || FALSE.starts_with(c) => { - let buf = c.to_lowercase().to_string(); - StateResult::Advance { to: Box::new(BoolSub(buf)) } - } + c if c.is_bool_initial() => { + let buf = c.to_ascii_lowercase().to_string(); + StateResult::advance(Box::new(Bool::new(buf.as_str()))) + }, _ => { let msg = format!("Invalid character: {}", c); - StateResult::Fail { msg } - } + StateResult::fail(msg.as_str()) + }, } } @@ -39,61 +36,7 @@ impl State for Hash { } } -impl BoolSub { - fn handle_delimiter(&self) -> Result<(Token, Resume), ()> { - if self.0 == TRUE || self.0 == TRUE_SHORT { - Ok((Token::Bool(true), Resume::Here)) - } else if self.0 == FALSE || self.0 == FALSE_SHORT { - Ok((Token::Bool(false), Resume::Here)) - } else { - Err(()) - } - } -} - -impl State for BoolSub { - fn lex(&mut self, c: char) -> StateResult { - match c { - c if c.is_identifier_delimiter() => match self.handle_delimiter() { - Ok((token, resume)) => StateResult::Emit(token, resume), - Err(_) => { - let msg = format!("Invalid character: {}", c); - StateResult::Fail { msg } - } - }, - _ => { - let buf = { - let mut b = String::from(self.0.as_str()); - b.push(c); - b - }; - if TRUE.starts_with(&buf) || FALSE.starts_with(&buf) { - StateResult::Advance { to: Box::new(BoolSub(buf)) } - } else { - let msg = format!("Invalid character: {}", c); - StateResult::Fail { msg } - } - } - } - } - - fn none(&mut self) -> Result, String> { - match self.handle_delimiter() { - Ok((token, _)) => Ok(Some(token)), - Err(_) => { - let msg = format!("Found EOF while trying to parse a bool"); - Err(msg) - } - } - } -} - -trait HashLexable { - fn is_tf(&self) -> bool; - fn is_slash(&self) -> bool; -} - impl HashLexable for char { - fn is_tf(&self) -> bool { "tfTF".contains(*self) } + fn is_bool_initial(&self) -> bool { "tf".contains(self.to_ascii_lowercase()) } fn is_slash(&self) -> bool { *self == '\\' } } diff --git a/lexer/src/states/mod.rs b/lexer/src/states/mod.rs index a9c45a0..e8b244e 100644 --- a/lexer/src/states/mod.rs +++ b/lexer/src/states/mod.rs @@ -6,12 +6,11 @@ use std::fmt::Debug; use token::Token; mod begin; +mod bool; mod hash; -mod number; mod id; pub use self::begin::Begin; -pub use self::number::BeginNumber; #[derive(Debug)] pub enum StateResult { @@ -39,7 +38,15 @@ pub trait State: Debug { } impl StateResult { + pub fn advance(to: Box) -> StateResult { + StateResult::Advance { to } + } + + pub fn emit(token: Token, at: Resume) -> StateResult { + StateResult::Emit(token, at) + } + pub fn fail(msg: &str) -> StateResult { StateResult::Fail { msg: msg.to_string() } } -} \ No newline at end of file +}