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