From eabc8f98e8d42c26e2258f883ac07c414b77f2f8 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Mon, 3 Sep 2018 15:49:13 -0700 Subject: [PATCH] [lexer] Add number::Sign state --- lexer/src/error.rs | 4 +++ lexer/src/states/number/prefix.rs | 14 +++++---- lexer/src/states/number/sign.rs | 47 +++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 lexer/src/states/number/sign.rs diff --git a/lexer/src/error.rs b/lexer/src/error.rs index c7aa1ce..ca05e36 100644 --- a/lexer/src/error.rs +++ b/lexer/src/error.rs @@ -18,5 +18,9 @@ impl Error { Error::new(format!("invalid character: {}", c)) } + pub fn unexpected_eof() -> Error { + Error::new("unexpected EOF".to_string()) + } + pub fn msg(&self) -> &str { &self.message } } diff --git a/lexer/src/states/number/prefix.rs b/lexer/src/states/number/prefix.rs index fbb7460..0bf8a39 100644 --- a/lexer/src/states/number/prefix.rs +++ b/lexer/src/states/number/prefix.rs @@ -2,10 +2,11 @@ * Eryn Wells */ +use chars::Lexable; use error::Error; use states::{State, StateResult}; -use states::number::{Radix, Exact}; -use states::number::Builder; +use states::number::{Builder, Radix, Exact}; +use states::number::sign::Sign; use token::Token; #[derive(Debug)] pub struct Prefix(Builder); @@ -31,9 +32,12 @@ impl Prefix { impl State for Prefix { fn lex(&mut self, c: char) -> StateResult { - match c { - '#' => StateResult::advance(Box::new(Hash(self.0))), - _ => StateResult::fail(Error::invalid_char(c)) + if c.is_hash() { + StateResult::advance(Box::new(Hash(self.0))) + } else if let Some(sn) = Sign::with_char(self.0, c) { + StateResult::advance(Box::new(sn)) + } else { + StateResult::fail(Error::invalid_char(c)) } } diff --git a/lexer/src/states/number/sign.rs b/lexer/src/states/number/sign.rs new file mode 100644 index 0000000..11310aa --- /dev/null +++ b/lexer/src/states/number/sign.rs @@ -0,0 +1,47 @@ +/* lexer/src/states/number/sign.rs + * Eryn Wells + */ + +use error::Error; +use states::{State, StateResult}; +use states::number::Builder; +use states::number::Sign as Sgn; +use token::Token; + +#[derive(Debug)] pub struct Sign(Builder); + +impl Sign { + pub fn new(b: Builder) -> Sign { + Sign(b) + } + + pub fn with_char(b: Builder, c: char) -> Option { + if !b.seen_sign() { + match c { + '+' => { + let mut b = b.clone(); + b.push_sign(Sgn::Pos); + Some(Sign::new(b)) + }, + '-' => { + let mut b = b.clone(); + b.push_sign(Sgn::Neg); + Some(Sign::new(b)) + }, + _ => None + } + } else { + None + } + } +} + +impl State for Sign { + fn lex(&mut self, c: char) -> StateResult { + StateResult::fail(Error::invalid_char(c)) + } + + fn none(&mut self) -> Result, Error> { + Err(Error::unexpected_eof()) + } +}