[lexer] Let states handle their own creation in from_char

This commit is contained in:
Eryn Wells 2018-09-03 16:06:52 -07:00
parent eabc8f98e8
commit 176686b3a7
2 changed files with 18 additions and 22 deletions

View file

@ -6,7 +6,7 @@ use chars::Lexable;
use error::Error; use error::Error;
use states::{State, StateResult}; use states::{State, StateResult};
use states::bool::Bool; use states::bool::Bool;
use states::number::Prefix; use states::number::{Builder, Prefix};
use token::Token; use token::Token;
trait HashLexable { trait HashLexable {
@ -28,7 +28,7 @@ impl State for Hash {
StateResult::advance(Box::new(Bool::new(buf.as_str()))) StateResult::advance(Box::new(Bool::new(buf.as_str())))
}, },
c if c.is_radix() || c.is_exactness() => { c if c.is_radix() || c.is_exactness() => {
if let Some(st) = Prefix::with_char(c) { if let Some(st) = Prefix::with_char(Builder::new(), c) {
StateResult::advance(Box::new(st)) StateResult::advance(Box::new(st))
} else { } else {
StateResult::fail(Error::new(format!("invalid numeric prefix character: {}", c))) StateResult::fail(Error::new(format!("invalid numeric prefix character: {}", c)))

View file

@ -17,16 +17,24 @@ impl Prefix {
Prefix(b) Prefix(b)
} }
pub fn with_char(c: char) -> Option<Prefix> { pub fn with_char(b: Builder, c: char) -> Option<Prefix> {
let mut builder = Builder::new();
if let Some(ex) = Exact::from(c) { if let Some(ex) = Exact::from(c) {
builder.push_exact(ex); if b.seen_exact() {
return None;
}
let mut b = b.clone();
b.push_exact(ex);
Some(Prefix::new(b))
} else if let Some(rx) = Radix::from(c) { } else if let Some(rx) = Radix::from(c) {
builder.push_radix(rx); if b.seen_radix() {
return None;
}
let mut b = b.clone();
b.push_radix(rx);
Some(Prefix::new(b))
} else { } else {
return None; None
} }
Some(Prefix::new(builder))
} }
} }
@ -48,20 +56,8 @@ impl State for Prefix {
impl State for Hash { impl State for Hash {
fn lex(&mut self, c: char) -> StateResult { fn lex(&mut self, c: char) -> StateResult {
if let Some(ex) = Exact::from(c) { if let Some(st) = Prefix::with_char(self.0, c) {
if !self.0.seen_exact() { StateResult::advance(Box::new(st))
self.0.push_exact(ex);
StateResult::advance(Box::new(Prefix::new(self.0)))
} else {
StateResult::fail(Error::invalid_char(c))
}
} else if let Some(rx) = Radix::from(c) {
if !self.0.seen_radix() {
self.0.push_radix(rx);
StateResult::advance(Box::new(Prefix::new(self.0)))
} else {
StateResult::fail(Error::invalid_char(c))
}
} else { } else {
StateResult::fail(Error::invalid_char(c)) StateResult::fail(Error::invalid_char(c))
} }