From 60f0d1cadc824c613b6b6ba56345104568b95f8f Mon Sep 17 00:00:00 2001 From: YannAhlgrim Date: Tue, 12 May 2026 18:27:35 +0200 Subject: [PATCH] extend the interpreter --- src/lexer/mod.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- src/main.rs | 15 +++++++++++++-- src/token/mod.rs | 18 ++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index 8d321e0..4740f70 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -1,16 +1,24 @@ use crate::token::lookup_ident; use super::token::ASSIGN; +use super::token::ASTERISK; +use super::token::BANG; use super::token::COMMA; use super::token::EOF; +use super::token::EQ; +use super::token::GT; use super::token::ILLEGAL; use super::token::INT; use super::token::LBRACE; use super::token::LPAREN; +use super::token::LT; +use super::token::MINUS; +use super::token::NQ; use super::token::PLUS; use super::token::RBRACE; use super::token::RPAREN; use super::token::SEMICOLON; +use super::token::SLASH; use super::token::Token; pub struct Lexer { @@ -26,6 +34,7 @@ pub trait LexerTraits { fn read_identifier(&mut self) -> String; fn skip_whitespace(&mut self); fn read_number(&mut self) -> String; + fn peek_char(&self) -> u8; } pub fn new(input_str: String) -> Lexer { @@ -66,12 +75,34 @@ impl LexerTraits for Lexer { match c { '\0' => tok = new_token(EOF, lit), - '=' => tok = new_token(ASSIGN, lit), + '=' => { + if char::from(self.peek_char()) == '=' { + self.read_char(); + let lit = String::from("=="); + tok = new_token_from_str(EQ, lit); + } else { + tok = new_token(ASSIGN, lit); + } + } ';' => tok = new_token(SEMICOLON, lit), '(' => tok = new_token(LPAREN, lit), ')' => tok = new_token(RPAREN, lit), ',' => tok = new_token(COMMA, lit), '+' => tok = new_token(PLUS, lit), + '-' => tok = new_token(MINUS, lit), + '!' => { + if char::from(self.peek_char()) == '=' { + self.read_char(); + let lit = String::from("!="); + tok = new_token_from_str(NQ, lit); + } else { + tok = new_token(BANG, lit); + } + } + '/' => tok = new_token(SLASH, lit), + '*' => tok = new_token(ASTERISK, lit), + '<' => tok = new_token(LT, lit), + '>' => tok = new_token(GT, lit), '{' => tok = new_token(LBRACE, lit), '}' => tok = new_token(RBRACE, lit), _ => { @@ -123,6 +154,16 @@ impl LexerTraits for Lexer { let res = &res[position..read_pos]; String::from(res) } + + fn peek_char(&self) -> u8 { + let read_pos = self.read_pos.unwrap() as usize; + if read_pos >= self.input.len() { + 0 + } else { + let res = self.input.as_bytes(); + res[read_pos] + } + } } fn new_token(token_type: &str, ch: u8) -> Token { diff --git a/src/main.rs b/src/main.rs index 28d45ec..b6b35bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,11 +10,22 @@ fn main() { let add = fn(x, y) { x + y; }; - let result = add(five, ten);"; + let result = add(five, ten); + !-/*5; + 5 < 10 > 5; + + if (5 < 10) { + return true; + } else { + return false; + } + + 10 == 10; + 10 != 9;"; let mut l = new(input.to_string()); - for (_i, tok) in (0..37).map(|_| l.next_token()).enumerate() { + for (_i, tok) in (0..80).map(|_| l.next_token()).enumerate() { println!("{}: {:?}", tok.type_, tok.literal); } } diff --git a/src/token/mod.rs b/src/token/mod.rs index eae46e4..0d99dc9 100644 --- a/src/token/mod.rs +++ b/src/token/mod.rs @@ -12,6 +12,12 @@ pub const IDENT: &str = "IDENT"; pub const INT: &str = "INT"; pub const ASSIGN: &str = "="; pub const PLUS: &str = "+"; +pub const MINUS: &str = "-"; +pub const BANG: &str = "!"; +pub const ASTERISK: &str = "*"; +pub const SLASH: &str = "/"; +pub const LT: &str = "<"; +pub const GT: &str = ">"; pub const COMMA: &str = ","; pub const SEMICOLON: &str = ";"; pub const LPAREN: &str = "("; @@ -20,11 +26,23 @@ pub const LBRACE: &str = "{"; pub const RBRACE: &str = "}"; pub const FUNCTION: &str = "FUNCTION"; pub const LET: &str = "LET"; +pub const TRUE: &str = "TRUE"; +pub const FALSE: &str = "FALSE"; +pub const IF: &str = "IF"; +pub const ELSE: &str = "ELSE"; +pub const RETURN: &str = "RETURN"; +pub const EQ: &str = "EQ"; +pub const NQ: &str = "NQ"; pub fn lookup_ident(ident: &str) -> &'static str { match ident { "fn" => FUNCTION, "let" => LET, + "true" => TRUE, + "false" => FALSE, + "if" => IF, + "else" => ELSE, + "return" => RETURN, _ => IDENT, } }