[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,6 +38,14 @@ 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