[lexer] WIP number::Digit state

This commit is contained in:
Eryn Wells 2018-09-03 17:08:05 -07:00
parent 176686b3a7
commit d272b211ae
3 changed files with 66 additions and 17 deletions

View file

@ -0,0 +1,44 @@
/* lexer/src/states/number/digit.rs
* Eryn Wells <eryn@erynwells.me>
*/
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<Digit> {
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<Option<Token>, Error> {
Err(Error::unexpected_eof())
}
}

View file

@ -2,24 +2,14 @@
* Eryn Wells <eryn@erynwells.me>
*/
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<Radix>;
/// Returns the value of the character interpreted as a numerical digit.
fn digit_value(&self) -> Option<u8>;
fn sign_value(&self) -> Option<Sign>;
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
}
}

View file

@ -50,7 +50,7 @@ impl State for Prefix {
}
fn none(&mut self) -> Result<Option<Token>, Error> {
Err(Error::new("blah".to_string()))
Err(Error::unexpected_eof())
}
}