From 108ebfba69207e0a293a33f4af0a6ea9dfe4a923 Mon Sep 17 00:00:00 2001 From: Mahmoud Abumandour Date: Sat, 2 Sep 2023 18:29:02 -0700 Subject: [PATCH] Support lexing integer literals --- Cargo.toml | 3 +- src/lexer.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 ++- 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 src/lexer.rs diff --git a/Cargo.toml b/Cargo.toml index 22429b2..bf2acca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,5 @@ name = "rustyc" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] +rstest = "0.18.2" \ No newline at end of file diff --git a/src/lexer.rs b/src/lexer.rs new file mode 100644 index 0000000..370433a --- /dev/null +++ b/src/lexer.rs @@ -0,0 +1,83 @@ +pub struct Lexer { + src: String, + pos: usize, +} +#[derive(Debug, PartialEq, Eq)] +enum TokenType { + Identifier, + Type, + Keyword, + Equals, + Plus, + SemiColon, + IntegerLiteral, + Eof, +} + +#[derive(Debug)] +pub struct Token { + value: String, + token_type: TokenType, + pos: usize, +} + +static EOF: char = '\0'; +impl Lexer { + + pub fn new(src: String) -> Self { + Self { src, pos: 0 } + } + fn consume(&mut self) -> char { + let curr = self.current(); + self.pos += 1; + curr + } + + fn current(&self) -> char { + if self.pos >= self.src.len() { + return EOF; + } + + self.src.chars().nth(self.pos).unwrap() + } + + fn lex_integer(&mut self) -> Token { + let mut value = String::new(); + let start = self.pos; + let mut c = self.consume(); + while c.is_digit(10) { + value.push(c); + c = self.consume(); + } + + Token { value, token_type: TokenType::IntegerLiteral, pos: start } + } + + pub fn lex(&mut self) -> Vec { + let mut result = Vec::new(); + loop { + let c = self.current(); + if c == EOF { break; } + if c.is_digit(10) { + result.push(self.lex_integer()); + } + } + result + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[rstest::rstest] + #[case("0")] + #[case("1")] + #[case("123")] + fn test_lex_integer(#[case] test_case: String) { + let tokens = Lexer::new(test_case.clone()).lex(); + assert_eq!(1, tokens.len()); + assert_eq!(test_case, tokens[0].value); + assert_eq!(TokenType::IntegerLiteral, tokens[0].token_type); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e7a11a9..07601e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +mod lexer; + fn main() { - println!("Hello, world!"); } +