Skip to main content

dar_core/
lexer.rs

1// crates/dar-core/src/lexer.rs
2use crate::token::Token;
3pub struct Lexer {
4    input: Vec<char,>,
5    pos: usize,
6}
7impl Lexer {
8    pub fn new(input: &str,) -> Self {
9        Self { input: input.chars().collect(), pos: 0, }
10    }
11    fn peek(&self,) -> Option<char,> {
12        self.input.get(self.pos,).copied()
13    }
14    fn advance(&mut self,) {
15        self.pos += 1;
16    }
17    fn skip_whitespace(&mut self,) {
18        while let Some(c,) = self.peek() {
19            if !c.is_whitespace() {
20                break;
21            }
22            self.advance();
23        }
24    }
25    fn read_identifier(&mut self,) -> String {
26        let start = self.pos;
27        while let Some(c,) = self.peek() {
28            if c.is_alphanumeric() || c == '_' {
29                self.advance();
30            } else {
31                break;
32            }
33        }
34        self.input[start..self.pos].iter().collect()
35    }
36    fn read_string(&mut self,) -> Result<String, String,> {
37        self.advance(); // skip "
38        let start = self.pos;
39        while let Some(c,) = self.peek() {
40            match c {
41                '"' => {
42                    let s: String =
43                        self.input[start..self.pos].iter().collect();
44                    self.advance();
45                    return Ok(s,);
46                },
47                '\\' => {
48                    self.advance();
49                    if self.peek().is_none() {
50                        return Err("Unterminated escape".to_string(),);
51                    }
52                    self.advance();
53                },
54                _ => self.advance(),
55            }
56        }
57        Err("Unterminated string literal".to_string(),)
58    }
59    pub fn next_token(&mut self,) -> Result<Token, String,> {
60        self.skip_whitespace();
61        let c = match self.peek() {
62            Some(ch,) => ch,
63            None => return Ok(Token::Eof,),
64        };
65        match c {
66            '(' => {
67                self.advance();
68                Ok(Token::LParen,)
69            },
70            ')' => {
71                self.advance();
72                Ok(Token::RParen,)
73            },
74            '{' => {
75                self.advance();
76                Ok(Token::LBrace,)
77            },
78            '}' => {
79                self.advance();
80                Ok(Token::RBrace,)
81            },
82            ',' => {
83                self.advance();
84                Ok(Token::Comma,)
85            },
86            ':' => {
87                self.advance();
88                Ok(Token::Colon,)
89            },
90            '.' => {
91                self.advance();
92                Ok(Token::Dot,)
93            },
94            '=' => {
95                self.advance();
96                Ok(Token::Equal,)
97            },
98            '"' => {
99                let lit = self.read_string()?;
100                Ok(Token::StringLiteral(lit,),)
101            },
102            _ if c.is_alphabetic() || c == '_' => {
103                let ident = self.read_identifier();
104                match ident.as_str() {
105                    "text" => Ok(Token::KeywordText,),
106                    "print" => Ok(Token::KeywordPrint,),
107                    "external" => Ok(Token::KeywordExternal,),
108                    "lua" => Ok(Token::KeywordLua,),
109                    "mod" => Ok(Token::KeywordMod,),
110                    "Upper" => Ok(Token::Upper,),
111                    "empty" => Ok(Token::Empty,),
112                    _ => Ok(Token::Identifier(ident,),),
113                }
114            },
115            _ => Err(format!("Unexpected character: '{}'", c),),
116        }
117    }
118}