diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index 98a0e4a..eb65cee 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -2,6 +2,7 @@ mod compound_identifier_state; mod hex_number_state; mod identifier_state; mod number_state; +mod polymorph_state; mod state; mod string_state; @@ -17,6 +18,7 @@ use crate::{ token::{StringLiteral, StringModifier, Token, TokenKind}, }; use compound_identifier_state::CompoundIdentifierState; +use polymorph_state::PolymorphState; pub struct Lexer { characters: T, @@ -36,6 +38,7 @@ impl Lexer { State::Idle => self.feed_idle(), State::Identifier(_) => self.feed_identifier(), State::CompoundIdentifier(_) => self.feed_compound_identifier(), + State::Polymorph(_) => self.feed_polymorph(), State::String(_) => self.feed_string(), State::Number(_) => self.feed_number(), State::HexNumber(_) => self.feed_hex_number(), @@ -326,6 +329,13 @@ impl Lexer { }); Waiting } + '$' => { + self.state = State::Polymorph(PolymorphState { + identifier: String::new(), + start_source: source, + }); + Waiting + } _ if c.is_alphabetic() || c == '_' => { self.state = State::Identifier(IdentifierState { identifier: String::from(c), @@ -385,6 +395,24 @@ impl Lexer { } } + fn feed_polymorph(&mut self) -> FeedResult { + use FeedResult::*; + + let state = self.state.as_mut_polymorph(); + + match self.characters.peek() { + Character::At(c, _) if c.is_alphabetic() || c.is_ascii_digit() || c == '_' => { + state.identifier.push(self.characters.next().unwrap().0); + Waiting + } + _ => { + let token = state.finalize(); + self.state = State::Idle; + Has(token) + } + } + } + fn feed_string(&mut self) -> FeedResult { use FeedResult::*; diff --git a/src/lexer/polymorph_state.rs b/src/lexer/polymorph_state.rs new file mode 100644 index 0000000..930b4b6 --- /dev/null +++ b/src/lexer/polymorph_state.rs @@ -0,0 +1,16 @@ +use crate::{ + source_files::Source, + token::{Token, TokenKind}, +}; + +pub struct PolymorphState { + pub identifier: String, + pub start_source: Source, +} + +impl PolymorphState { + pub fn finalize(&mut self) -> Token { + let identifier = std::mem::take(&mut self.identifier); + TokenKind::Polymorph(identifier).at(self.start_source) + } +} diff --git a/src/lexer/state.rs b/src/lexer/state.rs index 7231342..871c41a 100644 --- a/src/lexer/state.rs +++ b/src/lexer/state.rs @@ -1,6 +1,7 @@ use super::{ compound_identifier_state::CompoundIdentifierState, hex_number_state::HexNumberState, - identifier_state::IdentifierState, number_state::NumberState, string_state::StringState, + identifier_state::IdentifierState, number_state::NumberState, polymorph_state::PolymorphState, + string_state::StringState, }; use derive_more::Unwrap; @@ -9,6 +10,7 @@ pub enum State { Idle, Identifier(IdentifierState), CompoundIdentifier(CompoundIdentifierState), + Polymorph(PolymorphState), String(StringState), Number(NumberState), HexNumber(HexNumberState), @@ -29,6 +31,13 @@ impl State { } } + pub fn as_mut_polymorph(&mut self) -> &mut PolymorphState { + match self { + State::Polymorph(polymorph) => polymorph, + _ => panic!(), + } + } + pub fn as_mut_string(&mut self) -> &mut StringState { match self { State::String(state) => state, diff --git a/src/token.rs b/src/token.rs index b219f34..e4d51f2 100644 --- a/src/token.rs +++ b/src/token.rs @@ -54,6 +54,7 @@ pub enum TokenKind { Error(String), Newline, Identifier(String), + Polymorph(String), NamespacedIdentifier(Name), OpenCurly, CloseCurly, @@ -139,6 +140,7 @@ impl Display for TokenKind { TokenKind::Error(message) => write!(f, "'lex error - {}'", message), TokenKind::Newline => f.write_str("'newline'"), TokenKind::Identifier(name) => write!(f, "(identifier) '{}'", name), + TokenKind::Polymorph(name) => write!(f, "'${}'", name), TokenKind::NamespacedIdentifier(name) => write!( f, "(namespaced identifier) '{}{}'", @@ -272,6 +274,7 @@ impl TokenKind { | TokenKind::Error(_) | TokenKind::Newline | TokenKind::Identifier(_) + | TokenKind::Polymorph(_) | TokenKind::NamespacedIdentifier(_) | TokenKind::CloseCurly | TokenKind::OpenParen