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 import_specs = Vec::new();
40        let mut structs = Vec::new();
41        let mut agents = Vec::new();
42        let mut functions = Vec::new();
43        let mut toplevel_stmts: Vec<Stmt> = Vec::new();
44
45        while self.peek_token().is_ok() {
46            match self.peek_token()? {
47                Token::Use => {
48                    if let Stmt::Use { path } = self.parse_stmt()? {
49                        imports.push(path);
50                    }
51                }
52                Token::From => {
53                    if let Stmt::FromImport { spec } = self.parse_stmt()? {
54                        import_specs.push(spec);
55                    }
56                }
57                Token::Struct => structs.push(self.parse_struct_def()?),
58                Token::Agent  => agents.push(self.parse_agent_def()?),
59                Token::Fn | Token::At => functions.push(self.parse_function()?),
60                // Top-level statements (scripts / snippets without explicit fn main)
61                _ => toplevel_stmts.push(self.parse_stmt()?),
62            }
63        }
64
65        // Wrap any top-level statements in a synthetic fn main() -> trit { ... }
66        // only when no explicit main function is defined.
67        // VM-GLOBAL-001: when an explicit main IS defined but there are also top-level
68        // statements (e.g. `let counter: int = 42;` before `fn main`), prepend those
69        // stmts to main's body so they are visible as locals inside main.
70        if !toplevel_stmts.is_empty() {
71            if let Some(main_fn) = functions.iter_mut().find(|f| f.name == "main") {
72                // Separate call-stmts (e.g. `main();`) from declarations/assignments so
73                // we don't accidentally re-invoke main recursively.
74                let mut decls: Vec<Stmt> = Vec::new();
75                for s in toplevel_stmts {
76                    match &s {
77                        Stmt::Expr(Expr::Call { callee, .. }) if callee == "main" => {
78                            // Skip bare `main();` — it's just the script entry-point call
79                        }
80                        _ => decls.push(s),
81                    }
82                }
83                // Prepend declarations to main's body so they are accessible as locals
84                let mut new_body = decls;
85                new_body.append(&mut main_fn.body);
86                main_fn.body = new_body;
87            } else {
88                // No explicit main — synthesize one as before
89                functions.push(Function {
90                    name: "main".to_string(),
91                    params: vec![],
92                    return_type: Type::Trit,
93                    body: toplevel_stmts,
94                    directive: None,
95                });
96            }
97        }
98
99        Ok(Program { imports, import_specs, structs, agents, functions })
100    }
101
102    pub fn parse_agent_def(&mut self) -> Result<AgentDef, ParseError> {
103        self.expect(Token::Agent)?;
104        let name = match self.next_token()? {
105            Token::Ident(n) => n,
106            t => return Err(ParseError::ExpectedToken("agent name".into(), format!("{:?}", t))),
107        };
108        self.expect(Token::LBrace)?;
109        let mut methods = Vec::new();
110        while self.peek_token()? != Token::RBrace {
111            methods.push(self.parse_function()?);
112        }
113        self.expect(Token::RBrace)?;
114        Ok(AgentDef { name, methods })
115    }
116
117    pub fn parse_struct_def(&mut self) -> Result<StructDef, ParseError> {
118        self.expect(Token::Struct)?;
119        let name = match self.next_token()? {
120            Token::Ident(n) => n,
121            t => return Err(ParseError::ExpectedToken("struct name".into(), format!("{:?}", t))),
122        };
123        self.expect(Token::LBrace)?;
124        let mut fields = Vec::new();
125        while self.peek_token()? != Token::RBrace {
126            let field_name = match self.next_token()? {
127                Token::Ident(n) => n,
128                t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
129            };
130            self.expect(Token::Colon)?;
131            let field_type = self.parse_type()?;
132            fields.push((field_name, field_type));
133            if let Ok(Token::Comma) = self.peek_token() { self.next_token()?; }
134        }
135        self.expect(Token::RBrace)?;
136        Ok(StructDef { name, fields })
137    }
138
139    pub fn parse_function(&mut self) -> Result<Function, ParseError> {
140        let directive = if let Ok(Token::At) = self.peek_token() {
141            self.next_token()?;
142            let dir = match self.next_token()? {
143                Token::SparseSkip  => "sparseskip".to_string(),
144                Token::Ident(n)    => n,
145                t => return Err(ParseError::ExpectedToken("directive".into(), format!("{:?}", t))),
146            };
147            Some(dir)
148        } else {
149            None
150        };
151
152        self.expect(Token::Fn)?;
153        let name = match self.next_token()? {
154            Token::Ident(n) => n,
155            t => return Err(ParseError::ExpectedToken("function name".into(), format!("{:?}", t))),
156        };
157
158        self.expect(Token::LParen)?;
159        let mut params = Vec::new();
160        if self.peek_token()? != Token::RParen {
161            loop {
162                let p_name = match self.next_token()? {
163                    Token::Ident(n) => n,
164                    t => return Err(ParseError::ExpectedToken("parameter name".into(), format!("{:?}", t))),
165                };
166                self.expect(Token::Colon)?;
167                let p_type = self.parse_type()?;
168                params.push((p_name, p_type));
169                if self.peek_token()? == Token::Comma { self.next_token()?; } else { break; }
170            }
171        }
172        self.expect(Token::RParen)?;
173        self.expect(Token::Arrow)?;
174        let return_type = self.parse_type()?;
175        let body = match self.parse_block()? {
176            Stmt::Block(stmts) => stmts,
177            _ => unreachable!(),
178        };
179        Ok(Function { name, params, return_type, body, directive })
180    }
181
182    fn next_token(&mut self) -> Result<Token, ParseError> {
183        self.lex.next()
184            .map(|res| res.map_err(|_| ParseError::UnexpectedToken("Invalid token".into())))
185            .transpose()?
186            .ok_or(ParseError::UnexpectedToken("EOF".into()))
187    }
188
189    pub fn peek_token(&mut self) -> Result<Token, ParseError> {
190        let mut cloned = self.lex.clone();
191        match cloned.next() {
192            Some(Ok(t)) => Ok(t),
193            Some(Err(_)) => Err(ParseError::UnexpectedToken("Invalid token during peek".into())),
194            None => Err(ParseError::UnexpectedToken("EOF".into())),
195        }
196    }
197
198    pub fn parse_expr(&mut self) -> Result<Expr, ParseError> {
199        self.parse_binary_expr(0)
200    }
201
202    fn parse_binary_expr(&mut self, min_prec: i8) -> Result<Expr, ParseError> {
203        let mut lhs = self.parse_unary_expr()?;
204        loop {
205            let Ok(op_token) = self.peek_token() else { break };
206            if op_token == Token::RBrace || op_token == Token::Comma || op_token == Token::RParen || op_token == Token::Semicolon || op_token == Token::Return { break; }
207            let prec = self.get_precedence(&op_token);
208            if prec < min_prec { break; }
209            self.next_token()?;
210            let rhs = self.parse_binary_expr(prec + 1)?;
211            lhs = Expr::BinaryOp {
212                op: self.token_to_binop(op_token),
213                lhs: Box::new(lhs),
214                rhs: Box::new(rhs),
215            };
216        }
217        Ok(lhs)
218    }
219
220    fn get_precedence(&self, token: &Token) -> i8 {
221        match token {
222            Token::Or                      => 0,
223            Token::And                     => 1,
224            Token::Equal | Token::NotEqual => 2,
225            Token::LAngle | Token::RAngle  => 2, // Comparisons
226            Token::LessEqual | Token::GreaterEqual => 2,
227            Token::Plus  | Token::Minus    => 3,
228            Token::Star | Token::Slash | Token::Percent => 4,
229            _ => -1,
230        }
231    }
232
233    fn token_to_binop(&self, token: Token) -> BinOp {
234        match token {
235            Token::Plus     => BinOp::Add,
236            Token::Minus    => BinOp::Sub,
237            Token::Star     => BinOp::Mul,
238            Token::Slash    => BinOp::Div,
239            Token::Percent  => BinOp::Mod,
240            Token::Equal    => BinOp::Equal,
241            Token::NotEqual => BinOp::NotEqual,
242            Token::And      => BinOp::And,
243            Token::Or       => BinOp::Or,
244            Token::LAngle   => BinOp::Less,
245            Token::RAngle   => BinOp::Greater,
246            Token::LessEqual => BinOp::LessEqual,
247            Token::GreaterEqual => BinOp::GreaterEqual,
248            _ => unreachable!(),
249        }
250    }
251
252    /// Parse unary prefix expressions, then wrap with postfix (field access, indexing, `?`).
253    fn parse_unary_expr(&mut self) -> Result<Expr, ParseError> {
254        let mut expr = self.parse_primary_expr()?;
255        loop {
256            match self.peek_token()? {
257                Token::Dot => {
258                    self.next_token()?; // consume `.`
259                    let field = match self.next_token()? {
260                        Token::Ident(n) => n,
261                        t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
262                    };
263                    expr = Expr::FieldAccess { object: Box::new(expr), field };
264                }
265                Token::LBracket => {
266                    self.next_token()?; // consume `[`
267                    let row = self.parse_expr()?;
268                    if let Ok(Token::Comma) = self.peek_token() {
269                        self.next_token()?; // consume `,`
270                        let col = self.parse_expr()?;
271                        self.expect(Token::RBracket)?;
272                        expr = Expr::Index { object: Box::new(expr), row: Box::new(row), col: Box::new(col) };
273                    } else {
274                        self.expect(Token::RBracket)?;
275                        // Single-index access: sentinel col=-1 signals flat indexing in VM
276                        expr = Expr::Index { object: Box::new(expr), row: Box::new(row), col: Box::new(Expr::IntLiteral(-1)) };
277                    }
278                }
279                Token::UncertainBranch => {
280                    // Postfix `?` — ternary error propagation.
281                    // Disambiguate from `if cond ? { }`: if the token after `?` is `{`, this
282                    // `?` belongs to the enclosing if/while statement — don't consume it.
283                    let mut lookahead = self.lex.clone();
284                    lookahead.next(); // skip `?`
285                    let after_q = lookahead.next();
286                    let is_uncertain_branch = matches!(after_q, Some(Ok(Token::LBrace)));
287                    if !is_uncertain_branch {
288                        self.next_token()?; // consume `?`
289                        expr = Expr::Propagate { expr: Box::new(expr) };
290                    } else {
291                        break;
292                    }
293                }
294                _ => break,
295            }
296        }
297        Ok(expr)
298    }
299
300    fn parse_primary_expr(&mut self) -> Result<Expr, ParseError> {
301        let token = self.next_token()?;
302        match token {
303            // spawn AgentName           — local agent
304            // spawn remote "addr" Name  — remote agent (Phase 5.1)
305            Token::Spawn => {
306                let node_addr = if let Ok(Token::Remote) = self.peek_token() {
307                    self.next_token()?; // consume `remote`
308                    match self.next_token()? {
309                        Token::StringLit(addr) => Some(addr),
310                        t => return Err(ParseError::ExpectedToken("node address string".into(), format!("{:?}", t))),
311                    }
312                } else {
313                    None
314                };
315                let agent_name = match self.next_token()? {
316                    Token::Ident(n) => n,
317                    t => return Err(ParseError::ExpectedToken("agent name".into(), format!("{:?}", t))),
318                };
319                Ok(Expr::Spawn { agent_name, node_addr })
320            }
321            // await <agentref_expr> — receive from agent mailbox
322            Token::Await => {
323                let target = self.parse_unary_expr()?;
324                Ok(Expr::Await { target: Box::new(target) })
325            }
326            Token::NodeId => Ok(Expr::NodeId),
327            Token::Minus => {
328                let expr = self.parse_unary_expr()?;
329                Ok(Expr::UnaryOp { op: UnOp::Neg, expr: Box::new(expr) })
330            }
331            Token::LBracket => {
332                let mut vals = Vec::new();
333                loop {
334                    match self.next_token()? {
335                        Token::TritLiteral => {
336                            let s = self.lex.slice();
337                            let v = s.parse::<i8>().unwrap_or(0);
338                            vals.push(v);
339                        }
340                        Token::Int(v) => vals.push(v as i8),
341                        Token::Minus => {
342                            match self.next_token()? {
343                                Token::Int(v) => vals.push(-(v as i8)),
344                                t => return Err(ParseError::UnexpectedToken(format!("tensor literal element after '-': {:?}", t))),
345                            }
346                        }
347                        Token::Affirm => vals.push(1),
348                        Token::Tend => vals.push(0),
349                        Token::Reject => vals.push(-1),
350                        t => return Err(ParseError::UnexpectedToken(format!("tensor literal element: {:?}", t))),
351                    }
352                    if self.peek_token()? == Token::Comma {
353                        self.next_token()?;
354                    } else {
355                        break;
356                    }
357                }
358                self.expect(Token::RBracket)?;
359                Ok(Expr::TritTensorLiteral(vals))
360            }
361            Token::TritLiteral => {
362                let slice = self.lex.slice();
363                let val = slice.parse::<i8>()
364                    .map_err(|_| ParseError::InvalidTrit(slice.to_string()))?;
365                Ok(Expr::TritLiteral(val))
366            }
367            // Semantic trit keywords: affirm=+1, tend=0, reject=-1
368            Token::Affirm => Ok(Expr::TritLiteral(1)),
369            Token::Tend   => Ok(Expr::TritLiteral(0)),
370            Token::Reject => Ok(Expr::TritLiteral(-1)),
371            Token::Int(val) => Ok(Expr::IntLiteral(val)),
372            Token::Float(val) => Ok(Expr::FloatLiteral(val)),
373            Token::StringLit(s) => Ok(Expr::StringLiteral(s)),
374            Token::Ident(name) => {
375                // cast(expr) built-in: returns Cast node
376                if name == "cast" {
377                    if let Ok(Token::LParen) = self.peek_token() {
378                        self.next_token()?;
379                        let inner = self.parse_expr()?;
380                        self.expect(Token::RParen)?;
381                        // Type is resolved by context (the let binding ty)
382                        // Emit with Architecture defined Trit — semantic pass refines this
383                        return Ok(Expr::Cast { expr: Box::new(inner), ty: Type::Trit });
384                    }
385                }
386
387                if let Ok(Token::LParen) = self.peek_token() {
388                    // Function call
389                    self.next_token()?;
390                    let mut args = Vec::new();
391                    if self.peek_token()? != Token::RParen {
392                        loop {
393                            args.push(self.parse_expr()?);
394                            if self.peek_token()? == Token::Comma {
395                                self.next_token()?;
396                            } else {
397                                break;
398                            }
399                        }
400                    }
401                    self.expect(Token::RParen)?;
402                    Ok(Expr::Call { callee: name, args })
403                } else if let Ok(Token::LBrace) = self.peek_token() {
404                    // Struct literal: Name { field: val, ... }
405                    // Disambiguate from: if x { ... } or match x { ... }
406                    // Peek ahead: after '{', is it an 'ident :'?
407                    let mut lookahead = self.lex.clone();
408                    let _ = lookahead.next(); // consume '{'
409                    let maybe_ident = lookahead.next();
410                    let maybe_colon = lookahead.next();
411
412                    let is_struct_literal = matches!(maybe_ident, Some(Ok(Token::Ident(_)))) &&
413                                            matches!(maybe_colon, Some(Ok(Token::Colon)));
414
415                    if is_struct_literal {
416                        self.next_token()?; // consume `{`
417                        let mut fields = Vec::new();
418                        while self.peek_token()? != Token::RBrace {
419                            let f_name = match self.next_token()? {
420                                Token::Ident(n) => n,
421                                t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
422                            };
423                            self.expect(Token::Colon)?;
424                            let f_val = self.parse_expr()?;
425                            fields.push((f_name, f_val));
426                            if let Ok(Token::Comma) = self.peek_token() {
427                                self.next_token()?;
428                            } else {
429                                break;
430                            }
431                        }
432                        self.expect(Token::RBrace)?;
433                        Ok(Expr::StructLiteral { name, fields })
434                    } else {
435                        Ok(Expr::Ident(name))
436                    }
437                } else {
438                    Ok(Expr::Ident(name))
439                }
440            }
441            Token::LParen => {
442                let expr = self.parse_expr()?;
443                self.expect(Token::RParen)?;
444                Ok(expr)
445            }
446            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
447        }
448    }
449
450    pub fn parse_stmt(&mut self) -> Result<Stmt, ParseError> {
451        let token = self.peek_token()?;
452        match token {
453            Token::At => {
454                self.next_token()?;
455                let dir = match self.next_token()? {
456                    Token::SparseSkip  => "sparseskip".to_string(),
457                    Token::Ident(n)    => n,
458                    t => return Err(ParseError::ExpectedToken("directive".into(), format!("{:?}", t))),
459                };
460                let stmt = self.parse_stmt()?;
461                Ok(Stmt::Decorated { directive: dir, stmt: Box::new(stmt) })
462            }
463
464            Token::Use => {
465                self.next_token()?;
466                let mut path = Vec::new();
467                loop {
468                    // Accept both identifiers and reserved type keywords as path segments
469                    let segment = match self.next_token()? {
470                        Token::Ident(n)   => n,
471                        Token::TritType   => "trit".to_string(),
472                        Token::TritTensor => "trittensor".to_string(),
473                        t => return Err(ParseError::ExpectedToken("module path segment".into(), format!("{:?}", t))),
474                    };
475                    path.push(segment);
476                    if let Ok(Token::DoubleColon) = self.peek_token() {
477                        self.next_token()?;
478                    } else {
479                        break;
480                    }
481                }
482                self.expect(Token::Semicolon)?;
483                Ok(Stmt::Use { path })
484            }
485
486            // from <module::path | "file.tern"> import <name, name2 | *>;
487            Token::From => {
488                self.next_token()?;
489                // Determine source: string literal = file path, else module path
490                let source = match self.peek_token()? {
491                    Token::StringLit(_) => {
492                        if let Token::StringLit(s) = self.next_token()? {
493                            ImportSource::File(s)
494                        } else { unreachable!() }
495                    }
496                    _ => {
497                        let mut path = Vec::new();
498                        loop {
499                            let segment = match self.next_token()? {
500                                Token::Ident(n)   => n,
501                                Token::TritType   => "trit".to_string(),
502                                Token::TritTensor => "trittensor".to_string(),
503                                t => return Err(ParseError::ExpectedToken("module path segment".into(), format!("{:?}", t))),
504                            };
505                            path.push(segment);
506                            if let Ok(Token::DoubleColon) = self.peek_token() {
507                                self.next_token()?;
508                            } else {
509                                break;
510                            }
511                        }
512                        ImportSource::Module(path)
513                    }
514                };
515                self.expect(Token::Import)?;
516                // Parse names: `*` or comma-separated identifiers
517                let names = if let Ok(Token::Star) = self.peek_token() {
518                    self.next_token()?;
519                    ImportNames::Wildcard
520                } else {
521                    let mut named = Vec::new();
522                    loop {
523                        match self.next_token()? {
524                            Token::Ident(n) => named.push(n),
525                            t => return Err(ParseError::ExpectedToken("import name".into(), format!("{:?}", t))),
526                        }
527                        if let Ok(Token::Comma) = self.peek_token() {
528                            self.next_token()?;
529                        } else {
530                            break;
531                        }
532                    }
533                    ImportNames::Named(named)
534                };
535                self.expect(Token::Semicolon)?;
536                Ok(Stmt::FromImport { spec: ImportSpec { source, names } })
537            }
538
539            Token::Let => {
540                self.next_token()?;
541                // optional mut
542                let _mutable = if let Ok(Token::Mut) = self.peek_token() {
543                    self.next_token()?; true
544                } else { false };
545
546                let name = match self.next_token()? {
547                    Token::Ident(n) => n,
548                    t => return Err(ParseError::ExpectedToken("identifier".into(), format!("{:?}", t))),
549                };
550                self.expect(Token::Colon)?;
551                let ty = self.parse_type()?;
552                let value = if let Ok(Token::Assign) = self.peek_token() {
553                    self.next_token()?;
554                    self.parse_expr()?
555                } else {
556                    Expr::TritLiteral(0)
557                };
558                self.expect(Token::Semicolon)?;
559                Ok(Stmt::Let { name, ty, value })
560            }
561
562            Token::If => {
563                self.next_token()?;
564                let condition = self.parse_expr()?;
565                if let Ok(Token::UncertainBranch) = self.peek_token() {
566                    self.next_token()?;
567                    let on_pos  = Box::new(self.parse_block()?);
568                    self.expect(Token::Else)?;
569                    let on_zero = Box::new(self.parse_block()?);
570                    self.expect(Token::Else)?;
571                    let on_neg  = Box::new(self.parse_block()?);
572                    Ok(Stmt::IfTernary { condition, on_pos, on_zero, on_neg })
573                } else {
574                    // Binary if: if cond { A } else { B }
575                    // Maps to IfTernary(cond, A, B, B)
576                    let then_branch = Box::new(self.parse_block()?);
577                    let else_branch = if let Ok(Token::Else) = self.peek_token() {
578                        self.next_token()?;
579                        // Support `else if` chains — peek for `if` before expecting a block
580                        if let Ok(Token::If) = self.peek_token() {
581                            Box::new(self.parse_stmt()?)
582                        } else {
583                            Box::new(self.parse_block()?)
584                        }
585                    } else {
586                        Box::new(Stmt::Block(vec![]))
587                    };
588                    Ok(Stmt::IfTernary {
589                        condition,
590                        on_pos: then_branch,
591                        on_zero: else_branch.clone(),
592                        on_neg: else_branch,
593                    })
594                }
595            }
596
597            Token::Match => {
598                self.next_token()?;
599                let condition = self.parse_expr()?;
600                self.expect(Token::LBrace)?;
601                let mut arms = Vec::new();
602                while self.peek_token()? != Token::RBrace {
603                    let pattern = match self.next_token()? {
604                        Token::TritLiteral => {
605                            let slice = self.lex.slice();
606                            Pattern::Trit(slice.parse::<i8>().map_err(|_| ParseError::InvalidTrit(slice.to_string()))?)
607                        }
608                        Token::Int(v) => Pattern::Int(v),
609                        Token::Float(v) => Pattern::Float(v),
610                        Token::Minus => {
611                            match self.next_token()? {
612                                Token::Int(v) => Pattern::Int(-v),
613                                Token::Float(v) => Pattern::Float(-v),
614                                t => return Err(ParseError::ExpectedToken("number literal after '-'".into(), format!("{:?}", t))),
615                            }
616                        }
617                        Token::Affirm => Pattern::Trit(1),
618                        Token::Tend   => Pattern::Trit(0),
619                        Token::Reject => Pattern::Trit(-1),
620                        Token::Ident(ref s) if s == "_" => Pattern::Wildcard,
621                        t => return Err(ParseError::ExpectedToken("pattern (int, float, trit, or _)".into(), format!("{:?}", t))),
622                    };
623                    self.expect(Token::FatArrow)?;
624                    let stmt = self.parse_stmt()?;
625                    arms.push((pattern, stmt));
626                }
627                self.expect(Token::RBrace)?;
628
629                Ok(Stmt::Match { condition, arms })
630            }
631
632            // for <var> in <expr> { body }
633            Token::For => {
634                self.next_token()?;
635                let var = match self.next_token()? {
636                    Token::Ident(n) => n,
637                    t => return Err(ParseError::ExpectedToken("loop variable".into(), format!("{:?}", t))),
638                };
639                self.expect(Token::In)?;
640                let iter = self.parse_expr()?;
641                let body = Box::new(self.parse_block()?);
642                Ok(Stmt::ForIn { var, iter, body })
643            }
644
645            // while <condition> [?] { on_pos } [else { on_zero } else { on_neg }]
646            Token::While => {
647                self.next_token()?;
648                let condition = self.parse_expr()?;
649                if let Ok(Token::UncertainBranch) = self.peek_token() {
650                    self.next_token()?;
651                    let on_pos  = Box::new(self.parse_block()?);
652                    self.expect(Token::Else)?;
653                    let on_zero = Box::new(self.parse_block()?);
654                    self.expect(Token::Else)?;
655                    let on_neg  = Box::new(self.parse_block()?);
656                    Ok(Stmt::WhileTernary { condition, on_pos, on_zero, on_neg })
657                } else {
658                    // Binary while: while cond { body } [else { zero } else { neg }]
659                    // The else arms are optional — ? is not required for ternary while.
660                    let body = Box::new(self.parse_block()?);
661                    let (on_zero, on_neg) = if let Ok(Token::Else) = self.peek_token() {
662                        self.next_token()?;
663                        let zero = Box::new(self.parse_block()?);
664                        self.expect(Token::Else)?;
665                        let neg = Box::new(self.parse_block()?);
666                        (zero, neg)
667                    } else {
668                        (Box::new(Stmt::Break), Box::new(Stmt::Break))
669                    };
670                    Ok(Stmt::WhileTernary {
671                        condition,
672                        on_pos: body,
673                        on_zero,
674                        on_neg,
675                    })
676                }
677            }
678
679            // loop { body }
680            Token::Loop => {
681                self.next_token()?;
682                let body = Box::new(self.parse_block()?);
683                Ok(Stmt::Loop { body })
684            }
685
686            // send <target_expr> <message_expr>;
687            Token::Send => {
688                self.next_token()?;
689                let target = self.parse_expr()?;
690                let message = self.parse_expr()?;
691                self.expect(Token::Semicolon)?;
692                Ok(Stmt::Send { target, message })
693            }
694
695            Token::Break => {
696                self.next_token()?;
697                self.expect(Token::Semicolon)?;
698                Ok(Stmt::Break)
699            }
700
701            Token::Continue => {
702                self.next_token()?;
703                self.expect(Token::Semicolon)?;
704                Ok(Stmt::Continue)
705            }
706
707            Token::Return => {
708                self.next_token()?;
709                let expr = self.parse_expr()?;
710                self.expect(Token::Semicolon)?;
711                Ok(Stmt::Return(expr))
712            }
713
714            Token::LBrace => self.parse_block(),
715
716            // BUG-L02 fix: 'fn' at statement level — do NOT consume the token.
717            // peek_token() was used above so the lexer is still positioned at 'fn'.
718            // Returning this error lets the fallback in main.rs detect it and call
719            // parse_function() directly, which expects 'fn' as its first token.
720            Token::Fn => Err(ParseError::UnexpectedToken("Fn".into())),
721
722            _ => {
723                // Could be: expr; OR assignment: ident.field = value; OR ident[row, col] = value;
724                let expr = self.parse_expr()?;
725
726                // Check for assignment
727                if let Ok(Token::Assign) = self.peek_token() {
728                    match expr {
729                        Expr::FieldAccess { object, field } => {
730                            if let Expr::Ident(obj_name) = *object {
731                                self.next_token()?; // consume `=`
732                                let value = self.parse_expr()?;
733                                self.expect(Token::Semicolon)?;
734                                return Ok(Stmt::FieldSet { object: obj_name, field, value });
735                            }
736                        }
737                        Expr::Index { object, row, col } => {
738                            if let Expr::Ident(obj_name) = *object {
739                                self.next_token()?; // consume `=`
740                                let value = self.parse_expr()?;
741                                self.expect(Token::Semicolon)?;
742                                return Ok(Stmt::IndexSet { object: obj_name, row: *row, col: *col, value });
743                            }
744                        }
745                        Expr::Ident(name) => {
746                            self.next_token()?; // consume `=`
747                            let value = self.parse_expr()?;
748                            self.expect(Token::Semicolon)?;
749                            return Ok(Stmt::Set { name, value });
750                        }
751                        _ => {}
752                    }
753                    return Err(ParseError::UnexpectedToken("invalid assignment target".into()));
754                }
755
756                self.expect(Token::Semicolon)?;
757                Ok(Stmt::Expr(expr))
758            }
759        }
760    }
761
762    fn parse_block(&mut self) -> Result<Stmt, ParseError> {
763        self.expect(Token::LBrace)?;
764        let mut stmts = Vec::new();
765        while self.peek_token()? != Token::RBrace {
766            stmts.push(self.parse_stmt()?);
767        }
768        self.expect(Token::RBrace)?;
769        Ok(Stmt::Block(stmts))
770    }
771
772    fn parse_type(&mut self) -> Result<Type, ParseError> {
773        let token = self.next_token()?;
774        match token {
775            Token::TritType   => {
776                if let Ok(Token::LBracket) = self.peek_token() {
777                    self.next_token()?;
778                    let dim = if let Ok(Token::Int(n)) = self.peek_token() {
779                        self.next_token()?;
780                        n as usize
781                    } else { 0 };
782                    self.expect(Token::RBracket)?;
783                    Ok(Type::TritTensor { dims: vec![dim] })
784                } else {
785                    Ok(Type::Trit)
786                }
787            }
788            Token::AgentRef   => Ok(Type::AgentRef),
789            Token::TritTensor => {
790                self.expect(Token::LAngle)?;
791                let mut dims = Vec::new();
792                loop {
793                    let d = match self.next_token()? {
794                        Token::Int(v) => v as usize,
795                        // TritLiteral matches "0" and "1" — accept them as dims
796                        Token::TritLiteral => {
797                            let s = self.lex.slice();
798                            s.parse::<i8>().unwrap_or(0).max(0) as usize
799                        }
800                        t => return Err(ParseError::ExpectedToken("dimension".into(), format!("{:?}", t))),
801                    };
802                    dims.push(d);
803                    if self.peek_token()? == Token::Ident("x".to_string()) {
804                        self.next_token()?;
805                    } else {
806                        break;
807                    }
808                }
809                self.expect(Token::RAngle)?;
810                Ok(Type::TritTensor { dims })
811            }
812            Token::Ident(ref name) => match name.as_str() {
813                "int"    => {
814                    match self.peek_token() {
815                        Ok(Token::LBracket) => {
816                            self.next_token()?; // consume [
817                            let dim = if let Ok(Token::Int(n)) = self.peek_token() {
818                                self.next_token()?;
819                                n as usize
820                            } else { 0 };
821                            self.expect(Token::RBracket)?;
822                            Ok(Type::IntTensor { dims: vec![dim] })
823                        }
824                        _ => Ok(Type::Int)
825                    }
826                }
827                "float"  => {
828                    match self.peek_token() {
829                        Ok(Token::LBracket) => {
830                            self.next_token()?; // consume [
831                            let dim = if let Ok(Token::Int(n)) = self.peek_token() {
832                                self.next_token()?;
833                                n as usize
834                            } else { 0 };
835                            self.expect(Token::RBracket)?;
836                            Ok(Type::FloatTensor { dims: vec![dim] })
837                        }
838                        _ => Ok(Type::Float)
839                    }
840                }
841                "bool"   => Ok(Type::Bool),
842                "string" => Ok(Type::String),
843                // Named struct type
844                _        => Ok(Type::Named(name.clone())),
845            },
846            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
847        }
848    }
849
850    fn expect(&mut self, expected: Token) -> Result<(), ParseError> {
851        let token = self.next_token()?;
852        if token == expected {
853            Ok(())
854        } else {
855            Err(ParseError::ExpectedToken(format!("{:?}", expected), format!("{:?}", token)))
856        }
857    }
858}
859
860#[cfg(test)]
861mod tests {
862    use super::*;
863
864    #[test]
865    fn test_parse_function() {
866        let input = "fn invert(signal: trit) -> trit { return -signal; }";
867        let mut parser = Parser::new(input);
868        let func = parser.parse_function().unwrap();
869        assert_eq!(func.name, "invert");
870        assert_eq!(func.params[0].1, Type::Trit);
871        assert_eq!(func.return_type, Type::Trit);
872    }
873
874    #[test]
875    fn test_parse_match() {
876        let input = "match x { 1 => return 1; 0 => return 0; -1 => return -1; }";
877        let mut parser = Parser::new(input);
878        let stmt = parser.parse_stmt().unwrap();
879        if let Stmt::Match { arms, .. } = stmt {
880            use crate::ast::Pattern;
881            assert_eq!(arms.len(), 3);
882            assert_eq!(arms[0].0, Pattern::Int(1));
883            assert_eq!(arms[1].0, Pattern::Int(0));
884            assert_eq!(arms[2].0, Pattern::Int(-1));
885        } else {
886            panic!("Expected Match");
887        }
888    }
889
890    #[test]
891    fn test_match_parses_non_exhaustive() {
892        // Missing hold (0) arm — now parses (exhaustiveness moved to semantic)
893        let input = "match x { 1 => return 1; -1 => return -1; }";
894        let mut parser = Parser::new(input);
895        let result = parser.parse_stmt();
896        assert!(result.is_ok(), "should parse successfully even if non-exhaustive");
897    }
898
899    #[test]
900    fn test_parse_for_loop() {
901        let input = "for item in weights { return item; }";
902        let mut parser = Parser::new(input);
903        let stmt = parser.parse_stmt().unwrap();
904        assert!(matches!(stmt, Stmt::ForIn { .. }));
905    }
906
907    #[test]
908    fn test_parse_loop_break() {
909        let input = "loop { break; }";
910        let mut parser = Parser::new(input);
911        let stmt = parser.parse_stmt().unwrap();
912        assert!(matches!(stmt, Stmt::Loop { .. }));
913    }
914
915    #[test]
916    fn test_parse_use() {
917        let input = "use std::trit;";
918        let mut parser = Parser::new(input);
919        let stmt = parser.parse_stmt().unwrap();
920        if let Stmt::Use { path } = stmt {
921            assert_eq!(path, vec!["std", "trit"]);
922        } else {
923            panic!("Expected Use");
924        }
925    }
926
927    #[test]
928    fn test_parse_mut_let() {
929        let input = "let mut signal: trit = 1;";
930        let mut parser = Parser::new(input);
931        let stmt = parser.parse_stmt().unwrap();
932        assert!(matches!(stmt, Stmt::Let { .. }));
933    }
934
935    #[test]
936    fn test_parse_struct_def() {
937        let input = "struct Signal { value: trit, weight: trit }";
938        let mut parser = Parser::new(input);
939        let s = parser.parse_struct_def().unwrap();
940        assert_eq!(s.name, "Signal");
941        assert_eq!(s.fields.len(), 2);
942        assert_eq!(s.fields[0], ("value".to_string(), Type::Trit));
943        assert_eq!(s.fields[1], ("weight".to_string(), Type::Trit));
944    }
945
946    #[test]
947    fn test_parse_field_access() {
948        let input = "let v: trit = sig.value;";
949        let mut parser = Parser::new(input);
950        let stmt = parser.parse_stmt().unwrap();
951        if let Stmt::Let { value: Expr::FieldAccess { field, .. }, .. } = stmt {
952            assert_eq!(field, "value");
953        } else {
954            panic!("Expected FieldAccess in let binding");
955        }
956    }
957
958    #[test]
959    fn test_parse_field_set() {
960        let input = "sig.value = 1;";
961        let mut parser = Parser::new(input);
962        let stmt = parser.parse_stmt().unwrap();
963        assert!(matches!(stmt, Stmt::FieldSet { .. }));
964    }
965
966    #[test]
967    fn test_parse_cast() {
968        let input = "let t: trit = cast(flag);";
969        let mut parser = Parser::new(input);
970        let stmt = parser.parse_stmt().unwrap();
971        if let Stmt::Let { value: Expr::Cast { .. }, .. } = stmt {
972            // ok
973        } else {
974            panic!("Expected Cast in let binding");
975        }
976    }
977
978    #[test]
979    fn test_parse_named_type() {
980        let input = "let s: Signal;";
981        let mut parser = Parser::new(input);
982        let stmt = parser.parse_stmt().unwrap();
983        if let Stmt::Let { ty: Type::Named(name), .. } = stmt {
984            assert_eq!(name, "Signal");
985        } else {
986            panic!("Expected Named type");
987        }
988    }
989
990    #[test]
991    fn test_parse_agent_def() {
992        let input = r#"
993            agent Voter {
994                fn handle(msg: trit) -> trit {
995                    match msg {
996                         1 => { return  1; }
997                         0 => { return  0; }
998                        -1 => { return -1; }
999                    }
1000                }
1001            }
1002        "#;
1003        let mut parser = Parser::new(input);
1004        let agent = parser.parse_agent_def().unwrap();
1005        assert_eq!(agent.name, "Voter");
1006        assert_eq!(agent.methods.len(), 1);
1007        assert_eq!(agent.methods[0].name, "handle");
1008    }
1009
1010    #[test]
1011    fn test_parse_spawn() {
1012        let input = "let v: agentref = spawn Voter;";
1013        let mut parser = Parser::new(input);
1014        let stmt = parser.parse_stmt().unwrap();
1015        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
1016            assert_eq!(agent_name, "Voter");
1017            assert_eq!(node_addr, None);
1018        } else {
1019            panic!("Expected spawn in let binding");
1020        }
1021    }
1022
1023    #[test]
1024    fn test_parse_spawn_remote() {
1025        let input = r#"let v: agentref = spawn remote "10.0.0.1:7373" Voter;"#;
1026        let mut parser = Parser::new(input);
1027        let stmt = parser.parse_stmt().unwrap();
1028        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
1029            assert_eq!(agent_name, "Voter");
1030            assert_eq!(node_addr, Some("10.0.0.1:7373".to_string()));
1031        } else {
1032            panic!("Expected remote spawn in let binding");
1033        }
1034    }
1035
1036    #[test]
1037    fn test_parse_send() {
1038        let input = "send v 1;";
1039        let mut parser = Parser::new(input);
1040        let stmt = parser.parse_stmt().unwrap();
1041        assert!(matches!(stmt, Stmt::Send { .. }));
1042    }
1043
1044    #[test]
1045    fn test_parse_await() {
1046        let input = "let reply: trit = await v;";
1047        let mut parser = Parser::new(input);
1048        let stmt = parser.parse_stmt().unwrap();
1049        if let Stmt::Let { value: Expr::Await { .. }, .. } = stmt {
1050            // ok
1051        } else {
1052            panic!("Expected await in let binding");
1053        }
1054    }
1055}