diff options
author | visil <workregor@mail.ru> | 2023-11-20 00:37:09 +0300 |
---|---|---|
committer | visil <workregor@mail.ru> | 2023-11-20 00:37:09 +0300 |
commit | 0f496a8e5d2678ce3d81e402ab612534af787917 (patch) | |
tree | e98918dcae8d0226aeca2f6eedf9d69a8de5f5b6 /src/parser.rs |
Diffstat (limited to 'src/parser.rs')
-rw-r--r-- | src/parser.rs | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..fe414b0 --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,91 @@ +extern crate core; +use core::str::Chars; + +#[derive(Debug, PartialEq)] +pub enum Token { + Number(i32), + Plus, + Minus, + Multiply, + Divide, +} + +pub struct Lexer<'a> { + chars: Chars<'a>, +} + +impl<'a> Lexer<'a> { + // Constructor + pub fn new(input: &'a str) -> Self { + Lexer { chars: input.chars() } +} + + fn next_token(&mut self) -> Option<Token> { + let next_char = self.chars.next()?; + + match next_char { + '+' => Some(Token::Plus), + '-' => Some(Token::Minus), + '*' => Some(Token::Multiply), + '/' => Some(Token::Divide), + '1'..='9' => { + let mut number = next_char.to_digit(10)? as i32; + while let Some(next_char) = self.chars.clone().next() { + if let Some(digit) = next_char.to_digit(10) { + number = number * 10 + digit as i32; + self.chars.next(); + } else { + break; + } + } + Some(Token::Number(number)) + } + '0' => { + let base = match self.chars.next().unwrap() { + 'b' => Some(2), + 'o' => Some(8), + 'x' => Some(16), + _ => None, + }; + if base.is_none() { + return None; + } + + let mut number = next_char.to_digit(base.clone().unwrap())?; + while let Some(next_char) = self.chars.clone().next() { + if let Some(digit) = next_char.to_digit(base.clone().unwrap()) { + number = number * base.clone().unwrap() + digit; + self.chars.next(); + } else { + break; + } + } + Some(Token::Number(number as i32)) + } + _ => None, + } + } + + pub fn tokenize(&mut self) -> Vec<Token> { + let mut tokens = Vec::new(); + while let Some(token) = self.next_token() { + tokens.push(token); + } + tokens + } +} + +fn main() { + let mut lexer = Lexer::new("0x6A+0b001101*0o13"); + let tokens = lexer.tokenize(); + assert_eq!( + tokens, + vec![ + Token::Number(106), + Token::Plus, + Token::Number(13), + Token::Multiply, + Token::Number(11), + ] + ); +}
\ No newline at end of file |