Skip to main content

neutron_engine/iris/
parser.rs

1/// Iris Parser - Converts tokens into AST
2
3use super::lexer::{Token, TokenType};
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum Expr {
7    Null,
8    Bool(bool),
9    Number(f64),
10    String(String),
11    Identifier(String),
12    Array(Vec<Expr>),
13    Object(Vec<(String, Expr)>),
14    Binary {
15        left: Box<Expr>,
16        op: BinaryOp,
17        right: Box<Expr>,
18    },
19    Unary {
20        op: UnaryOp,
21        expr: Box<Expr>,
22    },
23    Call {
24        callee: Box<Expr>,
25        args: Vec<Expr>,
26    },
27    Index {
28        object: Box<Expr>,
29        index: Box<Expr>,
30    },
31    Member {
32        object: Box<Expr>,
33        property: String,
34    },
35    Assign {
36        target: Box<Expr>,
37        value: Box<Expr>,
38    },
39    Lambda {
40        params: Vec<String>,
41        body: Vec<Stmt>,
42    },
43}
44
45#[derive(Debug, Clone, PartialEq)]
46pub enum BinaryOp {
47    Add, Sub, Mul, Div, Mod,
48    Eq, Neq, Lt, Gt, Lte, Gte,
49    And, Or,
50}
51
52#[derive(Debug, Clone, PartialEq)]
53pub enum UnaryOp {
54    Neg, Not,
55}
56
57#[derive(Debug, Clone, PartialEq)]
58pub enum Stmt {
59    Expr(Expr),
60    Let {
61        name: String,
62        value: Expr,
63    },
64    Const {
65        name: String,
66        value: Expr,
67    },
68    Fn {
69        name: String,
70        params: Vec<String>,
71        body: Vec<Stmt>,
72    },
73    Block(Vec<Stmt>),
74    If {
75        condition: Expr,
76        then_branch: Vec<Stmt>,
77        else_branch: Option<Vec<Stmt>>,
78    },
79    While {
80        condition: Expr,
81        body: Vec<Stmt>,
82    },
83    For {
84        var: String,
85        iterable: Expr,
86        body: Vec<Stmt>,
87    },
88    Return(Option<Expr>),
89    Break,
90    Continue,
91    Import {
92        path: String,
93    },
94}
95
96pub struct Parser {
97    tokens: Vec<Token>,
98    current: usize,
99}
100
101impl Parser {
102    pub fn new(tokens: Vec<Token>) -> Self {
103        Parser { tokens, current: 0 }
104    }
105
106    pub fn parse(&mut self) -> Result<Vec<Stmt>, String> {
107        let mut stmts = Vec::new();
108        while !self.is_at_end() {
109            if self.match_token(&[TokenType::Newline]) || self.match_token(&[TokenType::Comment(String::new())]) {
110                continue;
111            }
112            stmts.push(self.statement()?);
113        }
114        Ok(stmts)
115    }
116
117    fn statement(&mut self) -> Result<Stmt, String> {
118        if self.match_token(&[TokenType::Import]) {
119            self.import_statement()
120        } else if self.match_token(&[TokenType::Let]) {
121            self.let_statement()
122        } else if self.match_token(&[TokenType::Const]) {
123            self.const_statement()
124        } else if self.match_token(&[TokenType::Fn]) {
125            self.fn_statement()
126        } else if self.match_token(&[TokenType::If]) {
127            self.if_statement()
128        } else if self.match_token(&[TokenType::While]) {
129            self.while_statement()
130        } else if self.match_token(&[TokenType::For]) {
131            self.for_statement()
132        } else if self.match_token(&[TokenType::Return]) {
133            self.return_statement()
134        } else if self.match_token(&[TokenType::Break]) {
135            Ok(Stmt::Break)
136        } else if self.match_token(&[TokenType::Continue]) {
137            Ok(Stmt::Continue)
138        } else if self.check(&TokenType::LBrace) {
139            self.block()
140        } else {
141            let expr = self.expression()?;
142            self.consume_semicolon();
143            Ok(Stmt::Expr(expr))
144        }
145    }
146
147    fn import_statement(&mut self) -> Result<Stmt, String> {
148        let path = match self.peek_token_type() {
149            Some(TokenType::String(s)) => {
150                let s = s.clone();
151                self.advance();
152                s
153            }
154            _ => return Err(format!("Expected string path after 'import' at line {}", self.peek().line)),
155        };
156        self.consume_semicolon();
157        Ok(Stmt::Import { path })
158    }
159
160    fn let_statement(&mut self) -> Result<Stmt, String> {
161        let name = self.consume_identifier("Expected variable name after 'let'")?;
162        self.consume(&TokenType::Assign, "Expected '=' after variable name")?;
163        let value = self.expression()?;
164        self.consume_semicolon();
165        Ok(Stmt::Let { name, value })
166    }
167
168    fn const_statement(&mut self) -> Result<Stmt, String> {
169        let name = self.consume_identifier("Expected constant name after 'const'")?;
170        self.consume(&TokenType::Assign, "Expected '=' after constant name")?;
171        let value = self.expression()?;
172        self.consume_semicolon();
173        Ok(Stmt::Const { name, value })
174    }
175
176    fn fn_statement(&mut self) -> Result<Stmt, String> {
177        let name = self.consume_identifier("Expected function name after 'fn'")?;
178        self.consume(&TokenType::LParen, "Expected '(' after function name")?;
179        let mut params = Vec::new();
180        if !self.check(&TokenType::RParen) {
181            loop {
182                params.push(self.consume_identifier("Expected parameter name")?);
183                if !self.match_token(&[TokenType::Comma]) {
184                    break;
185                }
186            }
187        }
188        self.consume(&TokenType::RParen, "Expected ')' after parameters")?;
189        let body = self.block()?;
190        let body = match body {
191            Stmt::Block(stmts) => stmts,
192            _ => vec![body],
193        };
194        Ok(Stmt::Fn { name, params, body })
195    }
196
197    fn if_statement(&mut self) -> Result<Stmt, String> {
198        let condition = self.expression()?;
199        let then_branch = match self.block()? {
200            Stmt::Block(stmts) => stmts,
201            s => vec![s],
202        };
203        let else_branch = if self.match_token(&[TokenType::Else]) {
204            if self.check(&TokenType::If) {
205                Some(vec![self.if_statement()?])
206            } else {
207                Some(match self.block()? {
208                    Stmt::Block(stmts) => stmts,
209                    s => vec![s],
210                })
211            }
212        } else {
213            None
214        };
215        Ok(Stmt::If { condition, then_branch, else_branch })
216    }
217
218    fn while_statement(&mut self) -> Result<Stmt, String> {
219        let condition = self.expression()?;
220        let body = match self.block()? {
221            Stmt::Block(stmts) => stmts,
222            s => vec![s],
223        };
224        Ok(Stmt::While { condition, body })
225    }
226
227    fn for_statement(&mut self) -> Result<Stmt, String> {
228        let var = self.consume_identifier("Expected variable name after 'for'")?;
229        self.consume(&TokenType::In, "Expected 'in' after for variable")?;
230        let iterable = self.expression()?;
231        let body = match self.block()? {
232            Stmt::Block(stmts) => stmts,
233            s => vec![s],
234        };
235        Ok(Stmt::For { var, iterable, body })
236    }
237
238    fn return_statement(&mut self) -> Result<Stmt, String> {
239        let value = if self.check(&TokenType::Semicolon) || self.check(&TokenType::Newline) || self.check(&TokenType::RBrace) || self.is_at_end() {
240            None
241        } else {
242            Some(self.expression()?)
243        };
244        self.consume_semicolon();
245        Ok(Stmt::Return(value))
246    }
247
248    fn block(&mut self) -> Result<Stmt, String> {
249        self.consume(&TokenType::LBrace, "Expected '{'")?;
250        let mut stmts = Vec::new();
251        while !self.check(&TokenType::RBrace) && !self.is_at_end() {
252            if self.match_token(&[TokenType::Newline]) || self.match_token(&[TokenType::Comment(String::new())]) {
253                continue;
254            }
255            stmts.push(self.statement()?);
256        }
257        self.consume(&TokenType::RBrace, "Expected '}' after block")?;
258        Ok(Stmt::Block(stmts))
259    }
260
261    fn expression(&mut self) -> Result<Expr, String> {
262        self.assignment()
263    }
264
265    fn assignment(&mut self) -> Result<Expr, String> {
266        let expr = self.or()?;
267        if self.match_token(&[TokenType::Assign, TokenType::PlusAssign, TokenType::MinusAssign, TokenType::StarAssign, TokenType::SlashAssign]) {
268            let op = self.previous().token_type.clone();
269            let value = self.assignment()?;
270            match expr {
271                Expr::Identifier(name) => {
272                    let value = match op {
273                        TokenType::PlusAssign => Expr::Binary { left: Box::new(Expr::Identifier(name.clone())), op: BinaryOp::Add, right: Box::new(value) },
274                        TokenType::MinusAssign => Expr::Binary { left: Box::new(Expr::Identifier(name.clone())), op: BinaryOp::Sub, right: Box::new(value) },
275                        TokenType::StarAssign => Expr::Binary { left: Box::new(Expr::Identifier(name.clone())), op: BinaryOp::Mul, right: Box::new(value) },
276                        TokenType::SlashAssign => Expr::Binary { left: Box::new(Expr::Identifier(name.clone())), op: BinaryOp::Div, right: Box::new(value) },
277                        _ => value,
278                    };
279                    Ok(Expr::Assign { target: Box::new(Expr::Identifier(name)), value: Box::new(value) })
280                }
281                Expr::Member { object, property } => {
282                    Ok(Expr::Assign { target: Box::new(Expr::Member { object, property }), value: Box::new(value) })
283                }
284                Expr::Index { object, index } => {
285                    Ok(Expr::Assign { target: Box::new(Expr::Index { object, index }), value: Box::new(value) })
286                }
287                _ => Err("Invalid assignment target".to_string()),
288            }
289        } else {
290            Ok(expr)
291        }
292    }
293
294    fn or(&mut self) -> Result<Expr, String> {
295        let mut expr = self.and()?;
296        while self.match_token(&[TokenType::Or]) {
297            let right = self.and()?;
298            expr = Expr::Binary { left: Box::new(expr), op: BinaryOp::Or, right: Box::new(right) };
299        }
300        Ok(expr)
301    }
302
303    fn and(&mut self) -> Result<Expr, String> {
304        let mut expr = self.equality()?;
305        while self.match_token(&[TokenType::And]) {
306            let right = self.equality()?;
307            expr = Expr::Binary { left: Box::new(expr), op: BinaryOp::And, right: Box::new(right) };
308        }
309        Ok(expr)
310    }
311
312    fn equality(&mut self) -> Result<Expr, String> {
313        let mut expr = self.comparison()?;
314        while self.match_token(&[TokenType::Eq, TokenType::Neq]) {
315            let op = match self.previous().token_type {
316                TokenType::Eq => BinaryOp::Eq,
317                TokenType::Neq => BinaryOp::Neq,
318                _ => unreachable!(),
319            };
320            let right = self.comparison()?;
321            expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right) };
322        }
323        Ok(expr)
324    }
325
326    fn comparison(&mut self) -> Result<Expr, String> {
327        let mut expr = self.term()?;
328        while self.match_token(&[TokenType::Lt, TokenType::Gt, TokenType::Lte, TokenType::Gte]) {
329            let op = match self.previous().token_type {
330                TokenType::Lt => BinaryOp::Lt,
331                TokenType::Gt => BinaryOp::Gt,
332                TokenType::Lte => BinaryOp::Lte,
333                TokenType::Gte => BinaryOp::Gte,
334                _ => unreachable!(),
335            };
336            let right = self.term()?;
337            expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right) };
338        }
339        Ok(expr)
340    }
341
342    fn term(&mut self) -> Result<Expr, String> {
343        let mut expr = self.factor()?;
344        while self.match_token(&[TokenType::Plus, TokenType::Minus]) {
345            let op = match self.previous().token_type {
346                TokenType::Plus => BinaryOp::Add,
347                TokenType::Minus => BinaryOp::Sub,
348                _ => unreachable!(),
349            };
350            let right = self.factor()?;
351            expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right) };
352        }
353        Ok(expr)
354    }
355
356    fn factor(&mut self) -> Result<Expr, String> {
357        let mut expr = self.unary()?;
358        while self.match_token(&[TokenType::Star, TokenType::Slash, TokenType::Percent]) {
359            let op = match self.previous().token_type {
360                TokenType::Star => BinaryOp::Mul,
361                TokenType::Slash => BinaryOp::Div,
362                TokenType::Percent => BinaryOp::Mod,
363                _ => unreachable!(),
364            };
365            let right = self.unary()?;
366            expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right) };
367        }
368        Ok(expr)
369    }
370
371    fn unary(&mut self) -> Result<Expr, String> {
372        if self.match_token(&[TokenType::Minus, TokenType::Not]) {
373            let op = match self.previous().token_type {
374                TokenType::Minus => UnaryOp::Neg,
375                TokenType::Not => UnaryOp::Not,
376                _ => unreachable!(),
377            };
378            let expr = self.unary()?;
379            Ok(Expr::Unary { op, expr: Box::new(expr) })
380        } else {
381            self.call()
382        }
383    }
384
385    fn call(&mut self) -> Result<Expr, String> {
386        let mut expr = self.primary()?;
387        loop {
388            if self.match_token(&[TokenType::LParen]) {
389                let mut args = Vec::new();
390                if !self.check(&TokenType::RParen) {
391                    loop {
392                        args.push(self.expression()?);
393                        if !self.match_token(&[TokenType::Comma]) {
394                            break;
395                        }
396                    }
397                }
398                self.consume(&TokenType::RParen, "Expected ')' after arguments")?;
399                expr = Expr::Call { callee: Box::new(expr), args };
400            } else if self.match_token(&[TokenType::Dot]) {
401                let property = self.consume_identifier("Expected property name after '.'")?;
402                expr = Expr::Member { object: Box::new(expr), property };
403            } else if self.match_token(&[TokenType::LBracket]) {
404                let index = self.expression()?;
405                self.consume(&TokenType::RBracket, "Expected ']' after index")?;
406                expr = Expr::Index { object: Box::new(expr), index: Box::new(index) };
407            } else {
408                break;
409            }
410        }
411        Ok(expr)
412    }
413
414    fn primary(&mut self) -> Result<Expr, String> {
415        if self.match_token(&[TokenType::Null]) {
416            Ok(Expr::Null)
417        } else if self.match_token(&[TokenType::Bool(true)]) {
418            Ok(Expr::Bool(true))
419        } else if self.match_token(&[TokenType::Bool(false)]) {
420            Ok(Expr::Bool(false))
421        } else if let Some(TokenType::Number(n)) = self.peek_token_type() {
422            let n = *n;
423            self.advance();
424            Ok(Expr::Number(n))
425        } else if let Some(TokenType::String(s)) = self.peek_token_type() {
426            let s = s.clone();
427            self.advance();
428            Ok(Expr::String(s))
429        } else if self.match_token(&[TokenType::LBracket]) {
430            let mut elements = Vec::new();
431            if !self.check(&TokenType::RBracket) {
432                loop {
433                    elements.push(self.expression()?);
434                    if !self.match_token(&[TokenType::Comma]) {
435                        break;
436                    }
437                }
438            }
439            self.consume(&TokenType::RBracket, "Expected ']' after array elements")?;
440            Ok(Expr::Array(elements))
441        } else if self.match_token(&[TokenType::LBrace]) {
442            let mut pairs = Vec::new();
443            if !self.check(&TokenType::RBrace) {
444                loop {
445                    let key = self.consume_identifier("Expected object key")?;
446                    self.consume(&TokenType::Colon, "Expected ':' after object key")?;
447                    let value = self.expression()?;
448                    pairs.push((key, value));
449                    if !self.match_token(&[TokenType::Comma]) {
450                        break;
451                    }
452                }
453            }
454            self.consume(&TokenType::RBrace, "Expected '}' after object pairs")?;
455            Ok(Expr::Object(pairs))
456        } else if self.match_token(&[TokenType::Fn]) {
457            self.consume(&TokenType::LParen, "Expected '(' after 'fn'")?;
458            let mut params = Vec::new();
459            if !self.check(&TokenType::RParen) {
460                loop {
461                    params.push(self.consume_identifier("Expected parameter name")?);
462                    if !self.match_token(&[TokenType::Comma]) {
463                        break;
464                    }
465                }
466            }
467            self.consume(&TokenType::RParen, "Expected ')' after parameters")?;
468            let body = match self.block()? {
469                Stmt::Block(stmts) => stmts,
470                s => vec![s],
471            };
472            Ok(Expr::Lambda { params, body })
473        } else if let Some(TokenType::Identifier(name)) = self.peek_token_type() {
474            let name = name.clone();
475            self.advance();
476            Ok(Expr::Identifier(name))
477        } else {
478            Err(format!("Unexpected token: {:?}", self.peek()))
479        }
480    }
481
482    // Helper methods
483    fn match_token(&mut self, types: &[TokenType]) -> bool {
484        for t in types {
485            if self.check(t) {
486                self.advance();
487                return true;
488            }
489        }
490        false
491    }
492
493    fn check(&self, token_type: &TokenType) -> bool {
494        if self.is_at_end() {
495            return false;
496        }
497        match (&self.peek().token_type, token_type) {
498            (TokenType::Comment(_), TokenType::Comment(_)) => true,
499            (a, b) => std::mem::discriminant(a) == std::mem::discriminant(b),
500        }
501    }
502
503    fn advance(&mut self) -> &Token {
504        if !self.is_at_end() {
505            self.current += 1;
506        }
507        self.previous()
508    }
509
510    fn is_at_end(&self) -> bool {
511        matches!(self.peek().token_type, TokenType::Eof)
512    }
513
514    fn peek(&self) -> &Token {
515        &self.tokens[self.current]
516    }
517
518    fn peek_token_type(&self) -> Option<&TokenType> {
519        if self.is_at_end() {
520            None
521        } else {
522            Some(&self.peek().token_type)
523        }
524    }
525
526    fn previous(&self) -> &Token {
527        &self.tokens[self.current - 1]
528    }
529
530    fn consume(&mut self, token_type: &TokenType, message: &str) -> Result<(), String> {
531        if self.check(token_type) {
532            self.advance();
533            Ok(())
534        } else {
535            Err(format!("{} at line {}, column {} (got {:?})", 
536                message, self.peek().line, self.peek().column, self.peek().token_type))
537        }
538    }
539
540    fn consume_identifier(&mut self, message: &str) -> Result<String, String> {
541        if let Some(TokenType::Identifier(name)) = self.peek_token_type() {
542            let name = name.clone();
543            self.advance();
544            Ok(name)
545        } else {
546            Err(format!("{} at line {}, column {} (got {:?})", 
547                message, self.peek().line, self.peek().column, self.peek().token_type))
548        }
549    }
550
551    fn consume_semicolon(&mut self) {
552        self.match_token(&[TokenType::Semicolon]);
553    }
554}
555
556pub fn parse(tokens: &[Token]) -> Result<Vec<Stmt>, String> {
557    let mut parser = Parser::new(tokens.to_vec());
558    parser.parse()
559}
560