From 34d612a832db08362b170c190721f04056bc057b Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Thu, 6 Sep 2018 18:07:40 -0700 Subject: [PATCH] [lexer] Add state for finding Dots at the beginning of input This happens to be a valid token by itself and the beginning of a decimal number. --- lexer/src/chars.rs | 16 ++++++++++------ lexer/src/states/begin.rs | 9 ++++----- lexer/src/states/dot.rs | 33 +++++++++++++++++++++++++++++++++ lexer/src/states/mod.rs | 1 + lexer/src/token.rs | 1 + lexer/tests/single_tokens.rs | 7 +++++++ 6 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 lexer/src/states/dot.rs diff --git a/lexer/src/chars.rs b/lexer/src/chars.rs index f1507b1..ae17af1 100644 --- a/lexer/src/chars.rs +++ b/lexer/src/chars.rs @@ -3,18 +3,22 @@ */ pub trait Lexable { - fn is_left_paren(&self) -> bool; - fn is_right_paren(&self) -> bool; + fn is_dot(&self) -> bool; + fn is_exactness(&self) -> bool; + fn is_hash(&self) -> bool; + fn is_identifier_delimiter(&self) -> bool; fn is_identifier_initial(&self) -> bool; fn is_identifier_subsequent(&self) -> bool; - fn is_identifier_delimiter(&self) -> bool; - - fn is_exactness(&self) -> bool; + fn is_left_paren(&self) -> bool; fn is_radix(&self) -> bool; - fn is_hash(&self) -> bool; + fn is_right_paren(&self) -> bool; } impl Lexable for char { + fn is_dot(&self) -> bool { + *self == '.' + } + fn is_exactness(&self) -> bool { *self == 'i' || *self == 'e' } diff --git a/lexer/src/states/begin.rs b/lexer/src/states/begin.rs index c1bdec4..4daff23 100644 --- a/lexer/src/states/begin.rs +++ b/lexer/src/states/begin.rs @@ -6,13 +6,13 @@ use chars::Lexable; use error::Error; use token::Token; use states::{Resume, State, StateResult}; +use states::dot::Dot; use states::id::IdSub; use states::hash::Hash; use states::number::{Builder, Digit}; use states::whitespace::Whitespace; -#[derive(Debug)] -pub struct Begin; +#[derive(Debug)] pub struct Begin; impl Begin { pub fn new() -> Begin { @@ -28,9 +28,8 @@ impl State for Begin { StateResult::Emit(Token::LeftParen, Resume::AtNext) } else if c.is_right_paren() { StateResult::Emit(Token::RightParen, Resume::AtNext) - } else if c.is_whitespace() { - // TODO: Figure out some way to track newlines. - StateResult::Continue + } else if c.is_dot() { + StateResult::advance(Box::new(Dot::new())) } else if c.is_identifier_initial() { StateResult::advance(Box::new(IdSub{})) } else if c.is_hash() { diff --git a/lexer/src/states/dot.rs b/lexer/src/states/dot.rs new file mode 100644 index 0000000..45bdfc8 --- /dev/null +++ b/lexer/src/states/dot.rs @@ -0,0 +1,33 @@ +/* lexer/src/states/dot.rs + * Eryn Wells + */ + +use chars::Lexable; +use error::Error; +use states::{Resume, State, StateResult}; +use states::number::{Builder, Digit}; +use token::Token; + +#[derive(Debug)] pub struct Dot; + +impl Dot { + pub fn new() -> Dot { + Dot{} + } +} + +impl State for Dot { + fn lex(&mut self, c: char) -> StateResult { + if c.is_identifier_delimiter() { + StateResult::emit(Token::Dot, Resume::Here) + } else if let Some(st) = Digit::with_char(&Builder::new(), c) { + StateResult::advance(Box::new(st)) + } else { + StateResult::fail(Error::invalid_char(c)) + } + } + + fn none(&mut self) -> Result, Error> { + Ok(Some(Token::Dot)) + } +} diff --git a/lexer/src/states/mod.rs b/lexer/src/states/mod.rs index d4fd04f..5b8c788 100644 --- a/lexer/src/states/mod.rs +++ b/lexer/src/states/mod.rs @@ -8,6 +8,7 @@ use token::Token; mod begin; mod bool; +mod dot; mod hash; mod number; mod id; diff --git a/lexer/src/token.rs b/lexer/src/token.rs index 2cc77bb..57135b5 100644 --- a/lexer/src/token.rs +++ b/lexer/src/token.rs @@ -13,6 +13,7 @@ pub struct Lex { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Token { Bool(bool), + Dot, Num(i64), LeftParen, RightParen, diff --git a/lexer/tests/single_tokens.rs b/lexer/tests/single_tokens.rs index 0578934..acd7c3d 100644 --- a/lexer/tests/single_tokens.rs +++ b/lexer/tests/single_tokens.rs @@ -88,3 +88,10 @@ fn integers_in_alternative_bases() { assert_eq!(lex.next(), Some(Ok(Lex::new(Token::Num(0b11001), "#b11001", 0, 5)))); assert_eq!(lex.next(), None); } + +#[test] +fn dot() { + let mut lex = Lexer::new(".".chars()); + assert_eq!(lex.next(), Some(Ok(Lex::new(Token::Dot, ".", 0, 0)))); + assert_eq!(lex.next(), None); +}