diff --git a/lexer/src/states/number/digit.rs b/lexer/src/states/number/digit.rs new file mode 100644 index 0000000..d571cbb --- /dev/null +++ b/lexer/src/states/number/digit.rs @@ -0,0 +1,44 @@ +/* lexer/src/states/number/digit.rs + * Eryn Wells + */ + +use chars::Lexable; +use error::Error; +use states::{State, StateResult}; +use states::number::{Builder, Radix, Exact}; +use states::number::sign::Sign; +use token::Token; + +#[derive(Debug)] pub struct Digit(Builder); + +impl Digit { + pub fn new(b: Builder) -> Digit { + Digit(b) + } + + pub fn with_char(b: Builder, c: char) -> Option { + let mut b = b.clone(); + if !b.seen_radix() { + b.push_radix(Radix::Dec); + } + match b.push_digit(c) { + Ok(_) => Some(Digit::new(b)), + // TODO: Deal with this error properly. Don't just ignore it. + Err(_) => None, + } + } +} + +impl State for Digit { + fn lex(&mut self, c: char) -> StateResult { + if self.0.push_digit(c).is_ok() { + StateResult::Continue + } else { + StateResult::fail(Error::invalid_char(c)) + } + } + + fn none(&mut self) -> Result, Error> { + Err(Error::unexpected_eof()) + } +} diff --git a/lexer/src/states/number/mod.rs b/lexer/src/states/number/mod.rs index 27d0315..daeecde 100644 --- a/lexer/src/states/number/mod.rs +++ b/lexer/src/states/number/mod.rs @@ -2,24 +2,14 @@ * Eryn Wells */ +use error::Error; + +mod digit; mod prefix; mod sign; pub use self::prefix::Prefix; -trait NumberLexable { - /// Returns the value of this character interpreted as the indicator for a - /// base. In Scheme, you indicate the base of a number by prefixing it with - /// #[bodx]. - fn base_value(&self) -> Option; - /// Returns the value of the character interpreted as a numerical digit. - fn digit_value(&self) -> Option; - fn sign_value(&self) -> Option; - fn is_dot(&self) -> bool; - fn is_hash(&self) -> bool; - fn is_sign(&self) -> bool; -} - #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Radix { Bin = 2, Oct = 8, Dec = 10, Hex = 16 } @@ -65,12 +55,19 @@ impl Builder { radix: None, sign: None, exact: None, - value: 0 + value: 0, } } - fn push_digit(&mut self, digit: u8) { - //self.value = self.value * self.base_value() as i64 + digit as i64; + fn push_digit(&mut self, c: char) -> Result<(), Error> { + let rx = self.radix_value(); + match c.to_digit(rx as u32) { + Some(d) => { + self.value = self.value * rx as i64 + d as i64; + Ok(()) + }, + None => Err(Error::invalid_char(c)) + } } fn push_exact(&mut self, ex: Exact) { @@ -94,4 +91,12 @@ impl Builder { fn seen_exact(&self) -> bool { self.exact.is_some() } fn seen_radix(&self) -> bool { self.radix.is_some() } fn seen_sign(&self) -> bool { self.sign.is_some() } + + fn radix_value(&self) -> u8 { + let rx = match self.radix { + Some(r) => r, + None => Radix::Dec, + }; + rx as u8 + } } diff --git a/lexer/src/states/number/prefix.rs b/lexer/src/states/number/prefix.rs index dddadfa..6003b81 100644 --- a/lexer/src/states/number/prefix.rs +++ b/lexer/src/states/number/prefix.rs @@ -50,7 +50,7 @@ impl State for Prefix { } fn none(&mut self) -> Result, Error> { - Err(Error::new("blah".to_string())) + Err(Error::unexpected_eof()) } }