[lexer] Move Bool state to its own file
This commit is contained in:
		
							parent
							
								
									e339b519de
								
							
						
					
					
						commit
						14ea07e441
					
				
					 3 changed files with 91 additions and 73 deletions
				
			
		
							
								
								
									
										68
									
								
								lexer/src/states/bool.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								lexer/src/states/bool.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | |||
| /* lexer/src/states/bool.rs
 | ||||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
| 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<Token> { | ||||
|         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<Option<Token>, String> { | ||||
|         match self.handle_delimiter() { | ||||
|             Some(token) => Ok(Some(token)), | ||||
|             None => { | ||||
|                 let msg = format!("Found EOF while trying to parse a bool"); | ||||
|                 Err(msg) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -2,19 +2,16 @@ | |||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
| //! 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<Option<Token>, 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 == '\\' } | ||||
| } | ||||
|  |  | |||
|  | @ -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<State>) -> 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() } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue