[lexer] WIP number::Digit state
This commit is contained in:
parent
176686b3a7
commit
d272b211ae
3 changed files with 66 additions and 17 deletions
44
lexer/src/states/number/digit.rs
Normal file
44
lexer/src/states/number/digit.rs
Normal 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())
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue