[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>
|
* Eryn Wells <eryn@erynwells.me>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Lexer states for handling tokens that begin with hash marks '#'.
|
use states::{State, StateResult};
|
||||||
|
use states::bool::Bool;
|
||||||
use chars::Lexable;
|
|
||||||
use states::{Resume, State, StateResult};
|
|
||||||
use token::Token;
|
use token::Token;
|
||||||
|
|
||||||
const TRUE_SHORT: &'static str = "t";
|
trait HashLexable {
|
||||||
const TRUE: &'static str = "true";
|
fn is_bool_initial(&self) -> bool;
|
||||||
const FALSE_SHORT: &'static str = "f";
|
fn is_slash(&self) -> bool;
|
||||||
const FALSE: &'static str = "false";
|
}
|
||||||
|
|
||||||
#[derive(Debug)] pub struct Hash;
|
#[derive(Debug)] pub struct Hash;
|
||||||
#[derive(Debug)] pub struct BoolSub(String);
|
|
||||||
|
|
||||||
impl Hash {
|
impl Hash {
|
||||||
pub fn new() -> Hash { Hash{} }
|
pub fn new() -> Hash { Hash{} }
|
||||||
|
@ -23,14 +20,14 @@ impl Hash {
|
||||||
impl State for Hash {
|
impl State for Hash {
|
||||||
fn lex(&mut self, c: char) -> StateResult {
|
fn lex(&mut self, c: char) -> StateResult {
|
||||||
match c {
|
match c {
|
||||||
c if TRUE.starts_with(c) || FALSE.starts_with(c) => {
|
c if c.is_bool_initial() => {
|
||||||
let buf = c.to_lowercase().to_string();
|
let buf = c.to_ascii_lowercase().to_string();
|
||||||
StateResult::Advance { to: Box::new(BoolSub(buf)) }
|
StateResult::advance(Box::new(Bool::new(buf.as_str())))
|
||||||
}
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let msg = format!("Invalid character: {}", c);
|
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 {
|
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 == '\\' }
|
fn is_slash(&self) -> bool { *self == '\\' }
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,11 @@ use std::fmt::Debug;
|
||||||
use token::Token;
|
use token::Token;
|
||||||
|
|
||||||
mod begin;
|
mod begin;
|
||||||
|
mod bool;
|
||||||
mod hash;
|
mod hash;
|
||||||
mod number;
|
|
||||||
mod id;
|
mod id;
|
||||||
|
|
||||||
pub use self::begin::Begin;
|
pub use self::begin::Begin;
|
||||||
pub use self::number::BeginNumber;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum StateResult {
|
pub enum StateResult {
|
||||||
|
@ -39,7 +38,15 @@ pub trait State: Debug {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StateResult {
|
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 {
|
pub fn fail(msg: &str) -> StateResult {
|
||||||
StateResult::Fail { msg: msg.to_string() }
|
StateResult::Fail { msg: msg.to_string() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue