Skip to main content

ternlang_core/
parser.rs

1use crate::lexer::Token;
2use crate::ast::*;
3use logos::{Logos, Lexer};
4
5pub struct Parser<'a> {
6    lex: Lexer<'a, Token>,
7}
8
9#[derive(Debug)]
10pub enum ParseError {
11    UnexpectedToken(String),
12    ExpectedToken(String, String),
13    InvalidTrit(String),
14    NonExhaustiveMatch(String),
15}
16
17impl std::fmt::Display for ParseError {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        match self {
20            Self::UnexpectedToken(tok) =>
21                write!(f, "[PARSE-001] Unexpected token '{tok}' — the lexer hit something it didn't expect. Binary habit? Check 'fn' vs 'func', trit vs bool.\n            → details: stdlib/errors/PARSE-001.tern  |  ternlang errors PARSE-001"),
22            Self::ExpectedToken(expected, found) =>
23                write!(f, "[PARSE-002] Expected {expected} but found '{found}'. Missing type annotation, brace, or semicolon?\n            → details: stdlib/errors/PARSE-002.tern  |  ternlang errors PARSE-002"),
24            Self::InvalidTrit(val) =>
25                write!(f, "[PARSE-003] '{val}' is not a valid trit. Trits are -1, 0, or +1 — the universe has exactly three states.\n            → details: stdlib/errors/PARSE-003.tern  |  ternlang errors PARSE-003"),
26            Self::NonExhaustiveMatch(msg) =>
27                write!(f, "[PARSE-004] Non-exhaustive match: {msg}. Ternary has three states — cover -1, 0, and +1 or the compiler won't let you through.\n            → details: stdlib/errors/PARSE-004.tern  |  ternlang errors PARSE-004"),
28        }
29    }
30}
31
32impl<'a> Parser<'a> {
33    pub fn new(input: &'a str) -> Self {
34        Self { lex: Token::lexer(input) }
35    }
36
37    pub fn parse_program(&mut self) -> Result<Program, ParseError> {
38        let mut imports = Vec::new();
39        let mut structs = Vec::new();
40        let mut agents = Vec::new();
41        let mut functions = Vec::new();
42        let mut toplevel_stmts: Vec<Stmt> = Vec::new();
43
44        while self.peek_token().is_ok() {
45            match self.peek_token()? {
46                Token::Use => {
47                    if let Stmt::Use { path } = self.parse_stmt()? {
48                        imports.push(path);
49                    }
50                }
51                Token::Struct => structs.push(self.parse_struct_def()?),
52                Token::Agent  => agents.push(self.parse_agent_def()?),
53                Token::Fn | Token::At => functions.push(self.parse_function()?),
54                // Top-level statements (scripts / snippets without explicit fn main)
55                _ => toplevel_stmts.push(self.parse_stmt()?),
56            }
57        }
58
59        // Wrap any top-level statements in a synthetic fn main() -> trit { ... }
60        // only when no explicit main function is defined.
61        if !toplevel_stmts.is_empty() && !functions.iter().any(|f| f.name == "main") {
62            functions.push(Function {
63                name: "main".to_string(),
64                params: vec![],
65                return_type: Type::Trit,
66                body: toplevel_stmts,
67                directive: None,
68            });
69        }
70
71        Ok(Program { imports, structs, agents, functions })
72    }
73
74    fn parse_agent_def(&mut self) -> Result<AgentDef, ParseError> {
75        self.expect(Token::Agent)?;
76        let name = match self.next_token()? {
77            Token::Ident(n) => n,
78            t => return Err(ParseError::ExpectedToken("agent name".into(), format!("{:?}", t))),
79        };
80        self.expect(Token::LBrace)?;
81        let mut methods = Vec::new();
82        while self.peek_token()? != Token::RBrace {
83            methods.push(self.parse_function()?);
84        }
85        self.expect(Token::RBrace)?;
86        Ok(AgentDef { name, methods })
87    }
88
89    fn parse_struct_def(&mut self) -> Result<StructDef, ParseError> {
90        self.expect(Token::Struct)?;
91        let name = match self.next_token()? {
92            Token::Ident(n) => n,
93            t => return Err(ParseError::ExpectedToken("struct name".into(), format!("{:?}", t))),
94        };
95        self.expect(Token::LBrace)?;
96        let mut fields = Vec::new();
97        while self.peek_token()? != Token::RBrace {
98            let field_name = match self.next_token()? {
99                Token::Ident(n) => n,
100                t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
101            };
102            self.expect(Token::Colon)?;
103            let field_type = self.parse_type()?;
104            fields.push((field_name, field_type));
105            if let Ok(Token::Comma) = self.peek_token() { self.next_token()?; }
106        }
107        self.expect(Token::RBrace)?;
108        Ok(StructDef { name, fields })
109    }
110
111    pub fn parse_function(&mut self) -> Result<Function, ParseError> {
112        let directive = if let Ok(Token::At) = self.peek_token() {
113            self.next_token()?;
114            let dir = match self.next_token()? {
115                Token::SparseSkip  => "sparseskip".to_string(),
116                Token::Ident(n)    => n,
117                t => return Err(ParseError::ExpectedToken("directive".into(), format!("{:?}", t))),
118            };
119            Some(dir)
120        } else {
121            None
122        };
123
124        self.expect(Token::Fn)?;
125        let name = match self.next_token()? {
126            Token::Ident(n) => n,
127            t => return Err(ParseError::ExpectedToken("function name".into(), format!("{:?}", t))),
128        };
129
130        self.expect(Token::LParen)?;
131        let mut params = Vec::new();
132        if self.peek_token()? != Token::RParen {
133            loop {
134                let p_name = match self.next_token()? {
135                    Token::Ident(n) => n,
136                    t => return Err(ParseError::ExpectedToken("parameter name".into(), format!("{:?}", t))),
137                };
138                self.expect(Token::Colon)?;
139                let p_type = self.parse_type()?;
140                params.push((p_name, p_type));
141                if self.peek_token()? == Token::Comma { self.next_token()?; } else { break; }
142            }
143        }
144        self.expect(Token::RParen)?;
145        self.expect(Token::Arrow)?;
146        let return_type = self.parse_type()?;
147        let body = match self.parse_block()? {
148            Stmt::Block(stmts) => stmts,
149            _ => unreachable!(),
150        };
151        Ok(Function { name, params, return_type, body, directive })
152    }
153
154    fn next_token(&mut self) -> Result<Token, ParseError> {
155        self.lex.next()
156            .map(|res| res.map_err(|_| ParseError::UnexpectedToken("Invalid token".into())))
157            .transpose()?
158            .ok_or(ParseError::UnexpectedToken("EOF".into()))
159    }
160
161    fn peek_token(&mut self) -> Result<Token, ParseError> {
162        let mut cloned = self.lex.clone();
163        cloned.next()
164            .map(|res| res.map_err(|_| ParseError::UnexpectedToken("Invalid token".into())))
165            .transpose()?
166            .ok_or(ParseError::UnexpectedToken("EOF".into()))
167    }
168
169    pub fn parse_expr(&mut self) -> Result<Expr, ParseError> {
170        self.parse_binary_expr(0)
171    }
172
173    fn parse_binary_expr(&mut self, min_prec: i8) -> Result<Expr, ParseError> {
174        let mut lhs = self.parse_unary_expr()?;
175        loop {
176            let Ok(op_token) = self.peek_token() else { break };
177            let prec = self.get_precedence(&op_token);
178            if prec < min_prec { break; }
179            self.next_token()?;
180            let rhs = self.parse_binary_expr(prec + 1)?;
181            lhs = Expr::BinaryOp {
182                op: self.token_to_binop(op_token),
183                lhs: Box::new(lhs),
184                rhs: Box::new(rhs),
185            };
186        }
187        Ok(lhs)
188    }
189
190    fn get_precedence(&self, token: &Token) -> i8 {
191        match token {
192            Token::Or                      => 0,
193            Token::And                     => 1,
194            Token::Equal | Token::NotEqual => 2,
195            Token::LAngle | Token::RAngle  => 2, // Comparisons
196            Token::LessEqual | Token::GreaterEqual => 2,
197            Token::Plus  | Token::Minus    => 3,
198            Token::Star | Token::Slash | Token::Percent => 4,
199            _ => -1,
200        }
201    }
202
203    fn token_to_binop(&self, token: Token) -> BinOp {
204        match token {
205            Token::Plus     => BinOp::Add,
206            Token::Minus    => BinOp::Sub,
207            Token::Star     => BinOp::Mul,
208            Token::Slash    => BinOp::Div,
209            Token::Percent  => BinOp::Mod,
210            Token::Equal    => BinOp::Equal,
211            Token::NotEqual => BinOp::NotEqual,
212            Token::And      => BinOp::And,
213            Token::Or       => BinOp::Or,
214            Token::LAngle   => BinOp::Less,
215            Token::RAngle   => BinOp::Greater,
216            Token::LessEqual => BinOp::LessEqual,
217            Token::GreaterEqual => BinOp::GreaterEqual,
218            _ => unreachable!(),
219        }
220    }
221
222    /// Parse unary prefix expressions, then wrap with postfix (field access, indexing, `?`).
223    fn parse_unary_expr(&mut self) -> Result<Expr, ParseError> {
224        let mut expr = self.parse_primary_expr()?;
225        loop {
226            match self.peek_token()? {
227                Token::Dot => {
228                    self.next_token()?; // consume `.`
229                    let field = match self.next_token()? {
230                        Token::Ident(n) => n,
231                        t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
232                    };
233                    expr = Expr::FieldAccess { object: Box::new(expr), field };
234                }
235                Token::LBracket => {
236                    self.next_token()?; // consume `[`
237                    let row = self.parse_expr()?;
238                    if let Ok(Token::Comma) = self.peek_token() {
239                        self.next_token()?; // consume `,`
240                        let col = self.parse_expr()?;
241                        self.expect(Token::RBracket)?;
242                        expr = Expr::Index { object: Box::new(expr), row: Box::new(row), col: Box::new(col) };
243                    } else {
244                        self.expect(Token::RBracket)?;
245                        // Use row as the single index, 0 as column (for 1D logic in VM)
246                        expr = Expr::Index { object: Box::new(expr), row: Box::new(row), col: Box::new(Expr::IntLiteral(0)) };
247                    }
248                }
249                Token::UncertainBranch => {
250                    // Postfix `?` — ternary error propagation.
251                    // Disambiguate from `if cond ? { }`: if the token after `?` is `{`, this
252                    // `?` belongs to the enclosing if/while statement — don't consume it.
253                    let mut lookahead = self.lex.clone();
254                    lookahead.next(); // skip `?`
255                    let after_q = lookahead.next();
256                    let is_uncertain_branch = matches!(after_q, Some(Ok(Token::LBrace)));
257                    if !is_uncertain_branch {
258                        self.next_token()?; // consume `?`
259                        expr = Expr::Propagate { expr: Box::new(expr) };
260                    } else {
261                        break;
262                    }
263                }
264                _ => break,
265            }
266        }
267        Ok(expr)
268    }
269
270    fn parse_primary_expr(&mut self) -> Result<Expr, ParseError> {
271        let token = self.next_token()?;
272        match token {
273            // spawn AgentName           — local agent
274            // spawn remote "addr" Name  — remote agent (Phase 5.1)
275            Token::Spawn => {
276                let node_addr = if let Ok(Token::Remote) = self.peek_token() {
277                    self.next_token()?; // consume `remote`
278                    match self.next_token()? {
279                        Token::StringLit(addr) => Some(addr),
280                        t => return Err(ParseError::ExpectedToken("node address string".into(), format!("{:?}", t))),
281                    }
282                } else {
283                    None
284                };
285                let agent_name = match self.next_token()? {
286                    Token::Ident(n) => n,
287                    t => return Err(ParseError::ExpectedToken("agent name".into(), format!("{:?}", t))),
288                };
289                Ok(Expr::Spawn { agent_name, node_addr })
290            }
291            // await <agentref_expr> — receive from agent mailbox
292            Token::Await => {
293                let target = self.parse_unary_expr()?;
294                Ok(Expr::Await { target: Box::new(target) })
295            }
296            Token::NodeId => Ok(Expr::NodeId),
297            Token::Minus => {
298                let expr = self.parse_unary_expr()?;
299                Ok(Expr::UnaryOp { op: UnOp::Neg, expr: Box::new(expr) })
300            }
301            Token::LBracket => {
302                let mut vals = Vec::new();
303                loop {
304                    match self.next_token()? {
305                        Token::TritLiteral => {
306                            let s = self.lex.slice();
307                            let v = s.parse::<i8>().unwrap_or(0);
308                            vals.push(v);
309                        }
310                        Token::Int(v) => vals.push(v as i8),
311                        Token::Minus => {
312                            match self.next_token()? {
313                                Token::Int(v) => vals.push(-(v as i8)),
314                                t => return Err(ParseError::UnexpectedToken(format!("tensor literal element after '-': {:?}", t))),
315                            }
316                        }
317                        Token::Affirm => vals.push(1),
318                        Token::Tend => vals.push(0),
319                        Token::Reject => vals.push(-1),
320                        t => return Err(ParseError::UnexpectedToken(format!("tensor literal element: {:?}", t))),
321                    }
322                    if self.peek_token()? == Token::Comma {
323                        self.next_token()?;
324                    } else {
325                        break;
326                    }
327                }
328                self.expect(Token::RBracket)?;
329                Ok(Expr::TritTensorLiteral(vals))
330            }
331            Token::TritLiteral => {
332                let slice = self.lex.slice();
333                let val = slice.parse::<i8>()
334                    .map_err(|_| ParseError::InvalidTrit(slice.to_string()))?;
335                Ok(Expr::TritLiteral(val))
336            }
337            // Semantic trit keywords: affirm=+1, tend=0, reject=-1
338            Token::Affirm => Ok(Expr::TritLiteral(1)),
339            Token::Tend   => Ok(Expr::TritLiteral(0)),
340            Token::Reject => Ok(Expr::TritLiteral(-1)),
341            Token::Int(val) => Ok(Expr::IntLiteral(val)),
342            Token::Float(val) => Ok(Expr::FloatLiteral(val)),
343            Token::StringLit(s) => Ok(Expr::StringLiteral(s)),
344            Token::Ident(name) => {
345                // cast(expr) built-in: returns Cast node
346                if name == "cast" {
347                    if let Ok(Token::LParen) = self.peek_token() {
348                        self.next_token()?;
349                        let inner = self.parse_expr()?;
350                        self.expect(Token::RParen)?;
351                        // Type is resolved by context (the let binding ty)
352                        // Emit with placeholder Trit — semantic pass refines this
353                        return Ok(Expr::Cast { expr: Box::new(inner), ty: Type::Trit });
354                    }
355                }
356
357                if let Ok(Token::LParen) = self.peek_token() {
358                    // Function call
359                    self.next_token()?;
360                    let mut args = Vec::new();
361                    if self.peek_token()? != Token::RParen {
362                        loop {
363                            args.push(self.parse_expr()?);
364                            if self.peek_token()? == Token::Comma {
365                                self.next_token()?;
366                            } else {
367                                break;
368                            }
369                        }
370                    }
371                    self.expect(Token::RParen)?;
372                    Ok(Expr::Call { callee: name, args })
373                } else {
374                    Ok(Expr::Ident(name))
375                }
376            }
377            Token::LParen => {
378                let expr = self.parse_expr()?;
379                self.expect(Token::RParen)?;
380                Ok(expr)
381            }
382            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
383        }
384    }
385
386    pub fn parse_stmt(&mut self) -> Result<Stmt, ParseError> {
387        let token = self.peek_token()?;
388        match token {
389            Token::At => {
390                self.next_token()?;
391                let dir = match self.next_token()? {
392                    Token::SparseSkip  => "sparseskip".to_string(),
393                    Token::Ident(n)    => n,
394                    t => return Err(ParseError::ExpectedToken("directive".into(), format!("{:?}", t))),
395                };
396                let stmt = self.parse_stmt()?;
397                Ok(Stmt::Decorated { directive: dir, stmt: Box::new(stmt) })
398            }
399
400            Token::Use => {
401                self.next_token()?;
402                let mut path = Vec::new();
403                loop {
404                    // Accept both identifiers and reserved type keywords as path segments
405                    let segment = match self.next_token()? {
406                        Token::Ident(n)   => n,
407                        Token::TritType   => "trit".to_string(),
408                        Token::TritTensor => "trittensor".to_string(),
409                        t => return Err(ParseError::ExpectedToken("module path segment".into(), format!("{:?}", t))),
410                    };
411                    path.push(segment);
412                    if let Ok(Token::DoubleColon) = self.peek_token() {
413                        self.next_token()?;
414                    } else {
415                        break;
416                    }
417                }
418                self.expect(Token::Semicolon)?;
419                Ok(Stmt::Use { path })
420            }
421
422            Token::Let => {
423                self.next_token()?;
424                // optional mut
425                let _mutable = if let Ok(Token::Mut) = self.peek_token() {
426                    self.next_token()?; true
427                } else { false };
428
429                let name = match self.next_token()? {
430                    Token::Ident(n) => n,
431                    t => return Err(ParseError::ExpectedToken("identifier".into(), format!("{:?}", t))),
432                };
433                self.expect(Token::Colon)?;
434                let ty = self.parse_type()?;
435                let value = if let Ok(Token::Assign) = self.peek_token() {
436                    self.next_token()?;
437                    self.parse_expr()?
438                } else {
439                    Expr::TritLiteral(0)
440                };
441                self.expect(Token::Semicolon)?;
442                Ok(Stmt::Let { name, ty, value })
443            }
444
445            Token::If => {
446                self.next_token()?;
447                let condition = self.parse_expr()?;
448                if let Ok(Token::UncertainBranch) = self.peek_token() {
449                    self.next_token()?;
450                    let on_pos  = Box::new(self.parse_block()?);
451                    self.expect(Token::Else)?;
452                    let on_zero = Box::new(self.parse_block()?);
453                    self.expect(Token::Else)?;
454                    let on_neg  = Box::new(self.parse_block()?);
455                    Ok(Stmt::IfTernary { condition, on_pos, on_zero, on_neg })
456                } else {
457                    // Binary if: if cond { A } else { B }
458                    // Maps to IfTernary(cond, A, B, B)
459                    let then_branch = Box::new(self.parse_block()?);
460                    let else_branch = if let Ok(Token::Else) = self.peek_token() {
461                        self.next_token()?;
462                        Box::new(self.parse_block()?)
463                    } else {
464                        Box::new(Stmt::Block(vec![]))
465                    };
466                    Ok(Stmt::IfTernary {
467                        condition,
468                        on_pos: then_branch,
469                        on_zero: else_branch.clone(),
470                        on_neg: else_branch,
471                    })
472                }
473            }
474
475            Token::Match => {
476                self.next_token()?;
477                let condition = self.parse_expr()?;
478                self.expect(Token::LBrace)?;
479                let mut arms = Vec::new();
480                while self.peek_token()? != Token::RBrace {
481                    let val = match self.next_token()? {
482                        Token::TritLiteral => {
483                            let slice = self.lex.slice();
484                            slice.parse::<i64>().map_err(|_| ParseError::InvalidTrit(slice.to_string()))?
485                        }
486                        Token::Int(v) => v,
487                        Token::Minus => {
488                            match self.next_token()? {
489                                Token::Int(v) => -v,
490                                t => return Err(ParseError::ExpectedToken("integer literal after '-'".into(), format!("{:?}", t))),
491                            }
492                        }
493                        Token::Affirm => 1,
494                        Token::Tend   => 0,
495                        Token::Reject => -1,
496                        t => return Err(ParseError::ExpectedToken("pattern (int or trit)".into(), format!("{:?}", t))),
497                    };
498                    self.expect(Token::FatArrow)?;
499                    let stmt = self.parse_stmt()?;
500                    arms.push((val, stmt));
501                }
502                self.expect(Token::RBrace)?;
503
504                Ok(Stmt::Match { condition, arms })
505            }
506
507            // for <var> in <expr> { body }
508            Token::For => {
509                self.next_token()?;
510                let var = match self.next_token()? {
511                    Token::Ident(n) => n,
512                    t => return Err(ParseError::ExpectedToken("loop variable".into(), format!("{:?}", t))),
513                };
514                self.expect(Token::In)?;
515                let iter = self.parse_expr()?;
516                let body = Box::new(self.parse_block()?);
517                Ok(Stmt::ForIn { var, iter, body })
518            }
519
520            // while <condition> [?] { on_pos } [else { on_zero } else { on_neg }]
521            Token::While => {
522                self.next_token()?;
523                let condition = self.parse_expr()?;
524                if let Ok(Token::UncertainBranch) = self.peek_token() {
525                    self.next_token()?;
526                    let on_pos  = Box::new(self.parse_block()?);
527                    self.expect(Token::Else)?;
528                    let on_zero = Box::new(self.parse_block()?);
529                    self.expect(Token::Else)?;
530                    let on_neg  = Box::new(self.parse_block()?);
531                    Ok(Stmt::WhileTernary { condition, on_pos, on_zero, on_neg })
532                } else {
533                    // Binary while: while cond { body }
534                    // Maps to WhileTernary(cond, body, Break, Break)
535                    let body = Box::new(self.parse_block()?);
536                    Ok(Stmt::WhileTernary {
537                        condition,
538                        on_pos: body,
539                        on_zero: Box::new(Stmt::Break),
540                        on_neg: Box::new(Stmt::Break),
541                    })
542                }
543            }
544
545            // loop { body }
546            Token::Loop => {
547                self.next_token()?;
548                let body = Box::new(self.parse_block()?);
549                Ok(Stmt::Loop { body })
550            }
551
552            // send <target_expr> <message_expr>;
553            Token::Send => {
554                self.next_token()?;
555                let target = self.parse_expr()?;
556                let message = self.parse_expr()?;
557                self.expect(Token::Semicolon)?;
558                Ok(Stmt::Send { target, message })
559            }
560
561            Token::Break => {
562                self.next_token()?;
563                self.expect(Token::Semicolon)?;
564                Ok(Stmt::Break)
565            }
566
567            Token::Continue => {
568                self.next_token()?;
569                self.expect(Token::Semicolon)?;
570                Ok(Stmt::Continue)
571            }
572
573            Token::Return => {
574                self.next_token()?;
575                let expr = self.parse_expr()?;
576                self.expect(Token::Semicolon)?;
577                Ok(Stmt::Return(expr))
578            }
579
580            Token::LBrace => self.parse_block(),
581
582            _ => {
583                // Could be: expr; OR assignment: ident.field = value; OR ident[row, col] = value;
584                let expr = self.parse_expr()?;
585
586                // Check for assignment
587                if let Ok(Token::Assign) = self.peek_token() {
588                    match expr {
589                        Expr::FieldAccess { object, field } => {
590                            if let Expr::Ident(obj_name) = *object {
591                                self.next_token()?; // consume `=`
592                                let value = self.parse_expr()?;
593                                self.expect(Token::Semicolon)?;
594                                return Ok(Stmt::FieldSet { object: obj_name, field, value });
595                            }
596                        }
597                        Expr::Index { object, row, col } => {
598                            if let Expr::Ident(obj_name) = *object {
599                                self.next_token()?; // consume `=`
600                                let value = self.parse_expr()?;
601                                self.expect(Token::Semicolon)?;
602                                return Ok(Stmt::IndexSet { object: obj_name, row: *row, col: *col, value });
603                            }
604                        }
605                        Expr::Ident(name) => {
606                            self.next_token()?; // consume `=`
607                            let value = self.parse_expr()?;
608                            self.expect(Token::Semicolon)?;
609                            return Ok(Stmt::Set { name, value });
610                        }
611                        _ => {}
612                    }
613                    return Err(ParseError::UnexpectedToken("invalid assignment target".into()));
614                }
615
616                self.expect(Token::Semicolon)?;
617                Ok(Stmt::Expr(expr))
618            }
619        }
620    }
621
622    fn parse_block(&mut self) -> Result<Stmt, ParseError> {
623        self.expect(Token::LBrace)?;
624        let mut stmts = Vec::new();
625        while self.peek_token()? != Token::RBrace {
626            stmts.push(self.parse_stmt()?);
627        }
628        self.expect(Token::RBrace)?;
629        Ok(Stmt::Block(stmts))
630    }
631
632    fn parse_type(&mut self) -> Result<Type, ParseError> {
633        let token = self.next_token()?;
634        match token {
635            Token::TritType   => {
636                if let Ok(Token::LBracket) = self.peek_token() {
637                    self.next_token()?;
638                    self.expect(Token::RBracket)?;
639                    Ok(Type::TritTensor { dims: vec![0] })
640                } else {
641                    Ok(Type::Trit)
642                }
643            }
644            Token::AgentRef   => Ok(Type::AgentRef),
645            Token::TritTensor => {
646                self.expect(Token::LAngle)?;
647                let mut dims = Vec::new();
648                loop {
649                    let d = match self.next_token()? {
650                        Token::Int(v) => v as usize,
651                        // TritLiteral matches "0" and "1" — accept them as dims
652                        Token::TritLiteral => {
653                            let s = self.lex.slice();
654                            s.parse::<i8>().unwrap_or(0).max(0) as usize
655                        }
656                        t => return Err(ParseError::ExpectedToken("dimension".into(), format!("{:?}", t))),
657                    };
658                    dims.push(d);
659                    if self.peek_token()? == Token::Ident("x".to_string()) {
660                        self.next_token()?;
661                    } else {
662                        break;
663                    }
664                }
665                self.expect(Token::RAngle)?;
666                Ok(Type::TritTensor { dims })
667            }
668            Token::Ident(ref name) => match name.as_str() {
669                "int"    => Ok(Type::Int),
670                "float"  => Ok(Type::Float),
671                "bool"   => Ok(Type::Bool),
672                "string" => Ok(Type::String),
673                // Named struct type
674                _        => Ok(Type::Named(name.clone())),
675            },
676            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
677        }
678    }
679
680    fn expect(&mut self, expected: Token) -> Result<(), ParseError> {
681        let token = self.next_token()?;
682        if token == expected {
683            Ok(())
684        } else {
685            Err(ParseError::ExpectedToken(format!("{:?}", expected), format!("{:?}", token)))
686        }
687    }
688}
689
690#[cfg(test)]
691mod tests {
692    use super::*;
693
694    #[test]
695    fn test_parse_function() {
696        let input = "fn invert(signal: trit) -> trit { return -signal; }";
697        let mut parser = Parser::new(input);
698        let func = parser.parse_function().unwrap();
699        assert_eq!(func.name, "invert");
700        assert_eq!(func.params[0].1, Type::Trit);
701        assert_eq!(func.return_type, Type::Trit);
702    }
703
704    #[test]
705    fn test_parse_match() {
706        let input = "match x { 1 => return 1; 0 => return 0; -1 => return -1; }";
707        let mut parser = Parser::new(input);
708        let stmt = parser.parse_stmt().unwrap();
709        if let Stmt::Match { arms, .. } = stmt {
710            assert_eq!(arms.len(), 3);
711            assert_eq!(arms[0].0, 1);
712            assert_eq!(arms[1].0, 0);
713            assert_eq!(arms[2].0, -1);
714        } else {
715            panic!("Expected Match");
716        }
717    }
718
719    #[test]
720    fn test_match_parses_non_exhaustive() {
721        // Missing hold (0) arm — now parses (exhaustiveness moved to semantic)
722        let input = "match x { 1 => return 1; -1 => return -1; }";
723        let mut parser = Parser::new(input);
724        let result = parser.parse_stmt();
725        assert!(result.is_ok(), "should parse successfully even if non-exhaustive");
726    }
727
728    #[test]
729    fn test_parse_for_loop() {
730        let input = "for item in weights { return item; }";
731        let mut parser = Parser::new(input);
732        let stmt = parser.parse_stmt().unwrap();
733        assert!(matches!(stmt, Stmt::ForIn { .. }));
734    }
735
736    #[test]
737    fn test_parse_loop_break() {
738        let input = "loop { break; }";
739        let mut parser = Parser::new(input);
740        let stmt = parser.parse_stmt().unwrap();
741        assert!(matches!(stmt, Stmt::Loop { .. }));
742    }
743
744    #[test]
745    fn test_parse_use() {
746        let input = "use std::trit;";
747        let mut parser = Parser::new(input);
748        let stmt = parser.parse_stmt().unwrap();
749        if let Stmt::Use { path } = stmt {
750            assert_eq!(path, vec!["std", "trit"]);
751        } else {
752            panic!("Expected Use");
753        }
754    }
755
756    #[test]
757    fn test_parse_mut_let() {
758        let input = "let mut signal: trit = 1;";
759        let mut parser = Parser::new(input);
760        let stmt = parser.parse_stmt().unwrap();
761        assert!(matches!(stmt, Stmt::Let { .. }));
762    }
763
764    #[test]
765    fn test_parse_struct_def() {
766        let input = "struct Signal { value: trit, weight: trit }";
767        let mut parser = Parser::new(input);
768        let s = parser.parse_struct_def().unwrap();
769        assert_eq!(s.name, "Signal");
770        assert_eq!(s.fields.len(), 2);
771        assert_eq!(s.fields[0], ("value".to_string(), Type::Trit));
772        assert_eq!(s.fields[1], ("weight".to_string(), Type::Trit));
773    }
774
775    #[test]
776    fn test_parse_field_access() {
777        let input = "let v: trit = sig.value;";
778        let mut parser = Parser::new(input);
779        let stmt = parser.parse_stmt().unwrap();
780        if let Stmt::Let { value: Expr::FieldAccess { field, .. }, .. } = stmt {
781            assert_eq!(field, "value");
782        } else {
783            panic!("Expected FieldAccess in let binding");
784        }
785    }
786
787    #[test]
788    fn test_parse_field_set() {
789        let input = "sig.value = 1;";
790        let mut parser = Parser::new(input);
791        let stmt = parser.parse_stmt().unwrap();
792        assert!(matches!(stmt, Stmt::FieldSet { .. }));
793    }
794
795    #[test]
796    fn test_parse_cast() {
797        let input = "let t: trit = cast(flag);";
798        let mut parser = Parser::new(input);
799        let stmt = parser.parse_stmt().unwrap();
800        if let Stmt::Let { value: Expr::Cast { .. }, .. } = stmt {
801            // ok
802        } else {
803            panic!("Expected Cast in let binding");
804        }
805    }
806
807    #[test]
808    fn test_parse_named_type() {
809        let input = "let s: Signal;";
810        let mut parser = Parser::new(input);
811        let stmt = parser.parse_stmt().unwrap();
812        if let Stmt::Let { ty: Type::Named(name), .. } = stmt {
813            assert_eq!(name, "Signal");
814        } else {
815            panic!("Expected Named type");
816        }
817    }
818
819    #[test]
820    fn test_parse_agent_def() {
821        let input = r#"
822            agent Voter {
823                fn handle(msg: trit) -> trit {
824                    match msg {
825                         1 => { return  1; }
826                         0 => { return  0; }
827                        -1 => { return -1; }
828                    }
829                }
830            }
831        "#;
832        let mut parser = Parser::new(input);
833        let agent = parser.parse_agent_def().unwrap();
834        assert_eq!(agent.name, "Voter");
835        assert_eq!(agent.methods.len(), 1);
836        assert_eq!(agent.methods[0].name, "handle");
837    }
838
839    #[test]
840    fn test_parse_spawn() {
841        let input = "let v: agentref = spawn Voter;";
842        let mut parser = Parser::new(input);
843        let stmt = parser.parse_stmt().unwrap();
844        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
845            assert_eq!(agent_name, "Voter");
846            assert_eq!(node_addr, None);
847        } else {
848            panic!("Expected spawn in let binding");
849        }
850    }
851
852    #[test]
853    fn test_parse_spawn_remote() {
854        let input = r#"let v: agentref = spawn remote "10.0.0.1:7373" Voter;"#;
855        let mut parser = Parser::new(input);
856        let stmt = parser.parse_stmt().unwrap();
857        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
858            assert_eq!(agent_name, "Voter");
859            assert_eq!(node_addr, Some("10.0.0.1:7373".to_string()));
860        } else {
861            panic!("Expected remote spawn in let binding");
862        }
863    }
864
865    #[test]
866    fn test_parse_send() {
867        let input = "send v 1;";
868        let mut parser = Parser::new(input);
869        let stmt = parser.parse_stmt().unwrap();
870        assert!(matches!(stmt, Stmt::Send { .. }));
871    }
872
873    #[test]
874    fn test_parse_await() {
875        let input = "let reply: trit = await v;";
876        let mut parser = Parser::new(input);
877        let stmt = parser.parse_stmt().unwrap();
878        if let Stmt::Let { value: Expr::Await { .. }, .. } = stmt {
879            // ok
880        } else {
881            panic!("Expected await in let binding");
882        }
883    }
884}