sibil/lexer/src/states/number/mod.rs

97 lines
2.2 KiB
Rust

/* lexer/src/states/number/mod.rs
* Eryn Wells <eryn@erynwells.me>
*/
use error::Error;
mod digit;
mod prefix;
mod sign;
pub use self::prefix::Prefix;
pub use self::digit::Digit;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Radix { Bin = 2, Oct = 8, Dec = 10, Hex = 16 }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Sign { Neg = -1, Pos = 1 }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Exact { Yes, No }
#[derive(Copy, Clone, Debug)]
pub struct Builder {
radix: Option<Radix>,
sign: Option<Sign>,
exact: Option<Exact>,
value: i64,
}
impl Radix {
pub fn from(c: char) -> Option<Radix> {
match c {
'b'|'B' => Some(Radix::Bin),
'o'|'O' => Some(Radix::Oct),
'd'|'D' => Some(Radix::Dec),
'x'|'X' => Some(Radix::Hex),
_ => None
}
}
}
impl Exact {
pub fn from(c: char) -> Option<Exact> {
match c {
'i'|'I' => Some(Exact::No),
'e'|'E' => Some(Exact::Yes),
_ => None
}
}
}
impl Builder {
pub fn new() -> Builder {
Builder {
radix: None,
sign: None,
exact: None,
value: 0,
}
}
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) {
self.exact = Some(ex);
}
fn push_radix(&mut self, radix: Radix) {
self.radix = Some(radix);
}
fn push_sign(&mut self, sign: Sign) {
self.sign = Some(sign);
}
fn resolve(&self) -> i64 {
let sign_factor = self.sign_value() as i64;
self.value * sign_factor
}
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 { self.radix.unwrap_or(Radix::Dec) as u8 }
fn sign_value(&self) -> u8 { self.sign.unwrap_or(Sign::Pos) as u8 }
}