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_or_start = self.parse_expr()?;
268                    if let Ok(Token::Range) = self.peek_token() {
269                        self.next_token()?; // consume `..`
270                        let end = self.parse_expr()?;
271                        let stride = if let Ok(Token::Semicolon) = self.peek_token() {
272                            self.next_token()?;
273                            self.parse_expr()?
274                        } else {
275                            Expr::IntLiteral(1)
276                        };
277                        self.expect(Token::RBracket)?;
278                        expr = Expr::Slice {
279                            object: Box::new(expr),
280                            start: Box::new(row_or_start),
281                            end: Box::new(end),
282                            stride: Box::new(stride),
283                        };
284                    } else if let Ok(Token::Comma) = self.peek_token() {
285                        self.next_token()?; // consume `,`
286                        let col = self.parse_expr()?;
287                        self.expect(Token::RBracket)?;
288                        expr = Expr::Index { object: Box::new(expr), row: Box::new(row_or_start), col: Box::new(col) };
289                    } else {
290                        self.expect(Token::RBracket)?;
291                        // Single-index access: sentinel col=-1 signals flat indexing in VM
292                        expr = Expr::Index { object: Box::new(expr), row: Box::new(row_or_start), col: Box::new(Expr::IntLiteral(-1)) };
293                    }
294                }
295                Token::UncertainBranch => {
296                    // Postfix `?` — ternary error propagation.
297                    // Disambiguate from `if cond ? { }`: if the token after `?` is `{`, this
298                    // `?` belongs to the enclosing if/while statement — don't consume it.
299                    let mut lookahead = self.lex.clone();
300                    lookahead.next(); // skip `?`
301                    let after_q = lookahead.next();
302                    let is_uncertain_branch = matches!(after_q, Some(Ok(Token::LBrace)));
303                    if !is_uncertain_branch {
304                        self.next_token()?; // consume `?`
305                        expr = Expr::Propagate { expr: Box::new(expr) };
306                    } else {
307                        break;
308                    }
309                }
310                _ => break,
311            }
312        }
313        Ok(expr)
314    }
315
316    fn parse_primary_expr(&mut self) -> Result<Expr, ParseError> {
317        let token = self.next_token()?;
318        match token {
319            // spawn AgentName           — local agent
320            // spawn remote "addr" Name  — remote agent (Phase 5.1)
321            Token::Spawn => {
322                let node_addr = if let Ok(Token::Remote) = self.peek_token() {
323                    self.next_token()?; // consume `remote`
324                    match self.next_token()? {
325                        Token::StringLit(addr) => Some(addr),
326                        t => return Err(ParseError::ExpectedToken("node address string".into(), format!("{:?}", t))),
327                    }
328                } else {
329                    None
330                };
331                let agent_name = match self.next_token()? {
332                    Token::Ident(n) => n,
333                    t => return Err(ParseError::ExpectedToken("agent name".into(), format!("{:?}", t))),
334                };
335                Ok(Expr::Spawn { agent_name, node_addr })
336            }
337            // await <agentref_expr> — receive from agent mailbox
338            Token::Await => {
339                let target = self.parse_unary_expr()?;
340                Ok(Expr::Await { target: Box::new(target) })
341            }
342            Token::NodeId => Ok(Expr::NodeId),
343            Token::Minus => {
344                let expr = self.parse_unary_expr()?;
345                Ok(Expr::UnaryOp { op: UnOp::Neg, expr: Box::new(expr) })
346            }
347            Token::LBracket => {
348                let mut vals = Vec::new();
349                loop {
350                    match self.next_token()? {
351                        Token::TritLiteral => {
352                            let s = self.lex.slice();
353                            let v = s.parse::<i8>().unwrap_or(0);
354                            vals.push(v);
355                        }
356                        Token::Int(v) => vals.push(v as i8),
357                        Token::Minus => {
358                            match self.next_token()? {
359                                Token::Int(v) => vals.push(-(v as i8)),
360                                t => return Err(ParseError::UnexpectedToken(format!("tensor literal element after '-': {:?}", t))),
361                            }
362                        }
363                        Token::Affirm => vals.push(1),
364                        Token::Tend => vals.push(0),
365                        Token::Reject => vals.push(-1),
366                        t => return Err(ParseError::UnexpectedToken(format!("tensor literal element: {:?}", t))),
367                    }
368                    if self.peek_token()? == Token::Comma {
369                        self.next_token()?;
370                    } else {
371                        break;
372                    }
373                }
374                self.expect(Token::RBracket)?;
375                Ok(Expr::TritTensorLiteral(vals))
376            }
377            Token::TritLiteral => {
378                let slice = self.lex.slice();
379                let val = slice.parse::<i8>()
380                    .map_err(|_| ParseError::InvalidTrit(slice.to_string()))?;
381                Ok(Expr::TritLiteral(val))
382            }
383            // Semantic trit keywords: affirm=+1, tend=0, reject=-1
384            Token::Affirm => Ok(Expr::TritLiteral(1)),
385            Token::Tend   => Ok(Expr::TritLiteral(0)),
386            Token::Reject => Ok(Expr::TritLiteral(-1)),
387            Token::Int(val) => Ok(Expr::IntLiteral(val)),
388            Token::Float(val) => Ok(Expr::FloatLiteral(val)),
389            Token::StringLit(s) => Ok(Expr::StringLiteral(s)),
390            Token::Ident(name) => {
391                // cast(expr) built-in: returns Cast node
392                if name == "cast" {
393                    if let Ok(Token::LParen) = self.peek_token() {
394                        self.next_token()?;
395                        let inner = self.parse_expr()?;
396                        self.expect(Token::RParen)?;
397                        // Type is resolved by context (the let binding ty)
398                        // Emit with Architecture defined Trit — semantic pass refines this
399                        return Ok(Expr::Cast { expr: Box::new(inner), ty: Type::Trit });
400                    }
401                }
402
403                if let Ok(Token::LParen) = self.peek_token() {
404                    // Function call
405                    self.next_token()?;
406                    let mut args = Vec::new();
407                    if self.peek_token()? != Token::RParen {
408                        loop {
409                            args.push(self.parse_expr()?);
410                            if self.peek_token()? == Token::Comma {
411                                self.next_token()?;
412                            } else {
413                                break;
414                            }
415                        }
416                    }
417                    self.expect(Token::RParen)?;
418                    Ok(Expr::Call { callee: name, args })
419                } else if let Ok(Token::LBrace) = self.peek_token() {
420                    // Struct literal: Name { field: val, ... }
421                    // Disambiguate from: if x { ... } or match x { ... }
422                    // Peek ahead: after '{', is it an 'ident :'?
423                    let mut lookahead = self.lex.clone();
424                    let _ = lookahead.next(); // consume '{'
425                    let maybe_ident = lookahead.next();
426                    let maybe_colon = lookahead.next();
427
428                    let is_struct_literal = matches!(maybe_ident, Some(Ok(Token::Ident(_)))) &&
429                                            matches!(maybe_colon, Some(Ok(Token::Colon)));
430
431                    if is_struct_literal {
432                        self.next_token()?; // consume `{`
433                        let mut fields = Vec::new();
434                        while self.peek_token()? != Token::RBrace {
435                            let f_name = match self.next_token()? {
436                                Token::Ident(n) => n,
437                                t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
438                            };
439                            self.expect(Token::Colon)?;
440                            let f_val = self.parse_expr()?;
441                            fields.push((f_name, f_val));
442                            if let Ok(Token::Comma) = self.peek_token() {
443                                self.next_token()?;
444                            } else {
445                                break;
446                            }
447                        }
448                        self.expect(Token::RBrace)?;
449                        Ok(Expr::StructLiteral { name, fields })
450                    } else {
451                        Ok(Expr::Ident(name))
452                    }
453                } else {
454                    Ok(Expr::Ident(name))
455                }
456            }
457            Token::LParen => {
458                let expr = self.parse_expr()?;
459                self.expect(Token::RParen)?;
460                Ok(expr)
461            }
462            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
463        }
464    }
465
466    pub fn parse_stmt(&mut self) -> Result<Stmt, ParseError> {
467        let token = self.peek_token()?;
468        match token {
469            Token::At => {
470                self.next_token()?;
471                let dir = match self.next_token()? {
472                    Token::SparseSkip  => "sparseskip".to_string(),
473                    Token::Ident(n)    => n,
474                    t => return Err(ParseError::ExpectedToken("directive".into(), format!("{:?}", t))),
475                };
476                let stmt = self.parse_stmt()?;
477                Ok(Stmt::Decorated { directive: dir, stmt: Box::new(stmt) })
478            }
479
480            Token::Use => {
481                self.next_token()?;
482                let mut path = Vec::new();
483                loop {
484                    // Accept both identifiers and reserved type keywords as path segments
485                    let segment = match self.next_token()? {
486                        Token::Ident(n)   => n,
487                        Token::TritType   => "trit".to_string(),
488                        Token::TritTensor => "trittensor".to_string(),
489                        t => return Err(ParseError::ExpectedToken("module path segment".into(), format!("{:?}", t))),
490                    };
491                    path.push(segment);
492                    if let Ok(Token::DoubleColon) = self.peek_token() {
493                        self.next_token()?;
494                    } else {
495                        break;
496                    }
497                }
498                self.expect(Token::Semicolon)?;
499                Ok(Stmt::Use { path })
500            }
501
502            // from <module::path | "file.tern"> import <name, name2 | *>;
503            Token::From => {
504                self.next_token()?;
505                // Determine source: string literal = file path, else module path
506                let source = match self.peek_token()? {
507                    Token::StringLit(_) => {
508                        if let Token::StringLit(s) = self.next_token()? {
509                            ImportSource::File(s)
510                        } else { unreachable!() }
511                    }
512                    _ => {
513                        let mut path = Vec::new();
514                        loop {
515                            let segment = match self.next_token()? {
516                                Token::Ident(n)   => n,
517                                Token::TritType   => "trit".to_string(),
518                                Token::TritTensor => "trittensor".to_string(),
519                                t => return Err(ParseError::ExpectedToken("module path segment".into(), format!("{:?}", t))),
520                            };
521                            path.push(segment);
522                            if let Ok(Token::DoubleColon) = self.peek_token() {
523                                self.next_token()?;
524                            } else {
525                                break;
526                            }
527                        }
528                        ImportSource::Module(path)
529                    }
530                };
531                self.expect(Token::Import)?;
532                // Parse names: `*` or comma-separated identifiers
533                let names = if let Ok(Token::Star) = self.peek_token() {
534                    self.next_token()?;
535                    ImportNames::Wildcard
536                } else {
537                    let mut named = Vec::new();
538                    loop {
539                        match self.next_token()? {
540                            Token::Ident(n) => named.push(n),
541                            t => return Err(ParseError::ExpectedToken("import name".into(), format!("{:?}", t))),
542                        }
543                        if let Ok(Token::Comma) = self.peek_token() {
544                            self.next_token()?;
545                        } else {
546                            break;
547                        }
548                    }
549                    ImportNames::Named(named)
550                };
551                self.expect(Token::Semicolon)?;
552                Ok(Stmt::FromImport { spec: ImportSpec { source, names } })
553            }
554
555            Token::Let => {
556                self.next_token()?;
557                // optional mut
558                let _mutable = if let Ok(Token::Mut) = self.peek_token() {
559                    self.next_token()?; true
560                } else { false };
561
562                let name = match self.next_token()? {
563                    Token::Ident(n) => n,
564                    t => return Err(ParseError::ExpectedToken("identifier".into(), format!("{:?}", t))),
565                };
566                self.expect(Token::Colon)?;
567                let ty = self.parse_type()?;
568                let value = if let Ok(Token::Assign) = self.peek_token() {
569                    self.next_token()?;
570                    self.parse_expr()?
571                } else {
572                    Expr::TritLiteral(0)
573                };
574                self.expect(Token::Semicolon)?;
575                Ok(Stmt::Let { name, ty, value })
576            }
577
578            Token::If => {
579                self.next_token()?;
580                let condition = self.parse_expr()?;
581                if let Ok(Token::UncertainBranch) = self.peek_token() {
582                    self.next_token()?;
583                    let on_pos  = Box::new(self.parse_block()?);
584                    self.expect(Token::Else)?;
585                    let on_zero = Box::new(self.parse_block()?);
586                    self.expect(Token::Else)?;
587                    let on_neg  = Box::new(self.parse_block()?);
588                    Ok(Stmt::IfTernary { condition, on_pos, on_zero, on_neg })
589                } else {
590                    // Binary if: if cond { A } else { B }
591                    // Maps to IfTernary(cond, A, B, B)
592                    let then_branch = Box::new(self.parse_block()?);
593                    let else_branch = if let Ok(Token::Else) = self.peek_token() {
594                        self.next_token()?;
595                        // Support `else if` chains — peek for `if` before expecting a block
596                        if let Ok(Token::If) = self.peek_token() {
597                            Box::new(self.parse_stmt()?)
598                        } else {
599                            Box::new(self.parse_block()?)
600                        }
601                    } else {
602                        Box::new(Stmt::Block(vec![]))
603                    };
604                    Ok(Stmt::IfTernary {
605                        condition,
606                        on_pos: then_branch,
607                        on_zero: else_branch.clone(),
608                        on_neg: else_branch,
609                    })
610                }
611            }
612
613            Token::Match => {
614                self.next_token()?;
615                let condition = self.parse_expr()?;
616                self.expect(Token::LBrace)?;
617                let mut arms = Vec::new();
618                while self.peek_token()? != Token::RBrace {
619                    let pattern = match self.next_token()? {
620                        Token::TritLiteral => {
621                            let slice = self.lex.slice();
622                            Pattern::Trit(slice.parse::<i8>().map_err(|_| ParseError::InvalidTrit(slice.to_string()))?)
623                        }
624                        Token::Int(v) => Pattern::Int(v),
625                        Token::Float(v) => Pattern::Float(v),
626                        Token::Minus => {
627                            match self.next_token()? {
628                                Token::Int(v) => Pattern::Int(-v),
629                                Token::Float(v) => Pattern::Float(-v),
630                                t => return Err(ParseError::ExpectedToken("number literal after '-'".into(), format!("{:?}", t))),
631                            }
632                        }
633                        Token::Affirm => Pattern::Trit(1),
634                        Token::Tend   => Pattern::Trit(0),
635                        Token::Reject => Pattern::Trit(-1),
636                        Token::Ident(ref s) if s == "_" => Pattern::Wildcard,
637                        t => return Err(ParseError::ExpectedToken("pattern (int, float, trit, or _)".into(), format!("{:?}", t))),
638                    };
639                    self.expect(Token::FatArrow)?;
640                    let stmt = self.parse_stmt()?;
641                    arms.push((pattern, stmt));
642                }
643                self.expect(Token::RBrace)?;
644
645                Ok(Stmt::Match { condition, arms })
646            }
647
648            // for <var> in <expr> { body }
649            Token::For => {
650                self.next_token()?;
651                let var = match self.next_token()? {
652                    Token::Ident(n) => n,
653                    t => return Err(ParseError::ExpectedToken("loop variable".into(), format!("{:?}", t))),
654                };
655                self.expect(Token::In)?;
656                let iter = self.parse_expr()?;
657                let body = Box::new(self.parse_block()?);
658                Ok(Stmt::ForIn { var, iter, body })
659            }
660
661            // while <condition> [?] { on_pos } [else { on_zero } else { on_neg }]
662            Token::While => {
663                self.next_token()?;
664                let condition = self.parse_expr()?;
665                if let Ok(Token::UncertainBranch) = self.peek_token() {
666                    self.next_token()?;
667                    let on_pos  = Box::new(self.parse_block()?);
668                    self.expect(Token::Else)?;
669                    let on_zero = Box::new(self.parse_block()?);
670                    self.expect(Token::Else)?;
671                    let on_neg  = Box::new(self.parse_block()?);
672                    Ok(Stmt::WhileTernary { condition, on_pos, on_zero, on_neg })
673                } else {
674                    // Binary while: while cond { body } [else { zero } else { neg }]
675                    // The else arms are optional — ? is not required for ternary while.
676                    let body = Box::new(self.parse_block()?);
677                    let (on_zero, on_neg) = if let Ok(Token::Else) = self.peek_token() {
678                        self.next_token()?;
679                        let zero = Box::new(self.parse_block()?);
680                        self.expect(Token::Else)?;
681                        let neg = Box::new(self.parse_block()?);
682                        (zero, neg)
683                    } else {
684                        (Box::new(Stmt::Break), Box::new(Stmt::Break))
685                    };
686                    Ok(Stmt::WhileTernary {
687                        condition,
688                        on_pos: body,
689                        on_zero,
690                        on_neg,
691                    })
692                }
693            }
694
695            // loop { body }
696            Token::Loop => {
697                self.next_token()?;
698                let body = Box::new(self.parse_block()?);
699                Ok(Stmt::Loop { body })
700            }
701
702            // send <target_expr> <message_expr>;
703            Token::Send => {
704                self.next_token()?;
705                let target = self.parse_expr()?;
706                let message = self.parse_expr()?;
707                self.expect(Token::Semicolon)?;
708                Ok(Stmt::Send { target, message })
709            }
710
711            Token::Break => {
712                self.next_token()?;
713                self.expect(Token::Semicolon)?;
714                Ok(Stmt::Break)
715            }
716
717            Token::Continue => {
718                self.next_token()?;
719                self.expect(Token::Semicolon)?;
720                Ok(Stmt::Continue)
721            }
722
723            Token::Return => {
724                self.next_token()?;
725                let expr = self.parse_expr()?;
726                self.expect(Token::Semicolon)?;
727                Ok(Stmt::Return(expr))
728            }
729
730            Token::LBrace => self.parse_block(),
731
732            // BUG-L02 fix: 'fn' at statement level — do NOT consume the token.
733            // peek_token() was used above so the lexer is still positioned at 'fn'.
734            // Returning this error lets the fallback in main.rs detect it and call
735            // parse_function() directly, which expects 'fn' as its first token.
736            Token::Fn => Err(ParseError::UnexpectedToken("Fn".into())),
737
738            _ => {
739                // Could be: expr; OR assignment: ident.field = value; OR ident[row, col] = value;
740                let expr = self.parse_expr()?;
741
742                // Check for assignment
743                if let Ok(Token::Assign) = self.peek_token() {
744                    match expr {
745                        Expr::FieldAccess { object, field } => {
746                            if let Expr::Ident(obj_name) = *object {
747                                self.next_token()?; // consume `=`
748                                let value = self.parse_expr()?;
749                                self.expect(Token::Semicolon)?;
750                                return Ok(Stmt::FieldSet { object: obj_name, field, value });
751                            }
752                        }
753                        Expr::Index { object, row, col } => {
754                            if let Expr::Ident(obj_name) = *object {
755                                self.next_token()?; // consume `=`
756                                let value = self.parse_expr()?;
757                                self.expect(Token::Semicolon)?;
758                                return Ok(Stmt::IndexSet { object: obj_name, row: *row, col: *col, value });
759                            }
760                        }
761                        Expr::Ident(name) => {
762                            self.next_token()?; // consume `=`
763                            let value = self.parse_expr()?;
764                            self.expect(Token::Semicolon)?;
765                            return Ok(Stmt::Set { name, value });
766                        }
767                        _ => {}
768                    }
769                    return Err(ParseError::UnexpectedToken("invalid assignment target".into()));
770                }
771
772                self.expect(Token::Semicolon)?;
773                Ok(Stmt::Expr(expr))
774            }
775        }
776    }
777
778    fn parse_block(&mut self) -> Result<Stmt, ParseError> {
779        self.expect(Token::LBrace)?;
780        let mut stmts = Vec::new();
781        while self.peek_token()? != Token::RBrace {
782            stmts.push(self.parse_stmt()?);
783        }
784        self.expect(Token::RBrace)?;
785        Ok(Stmt::Block(stmts))
786    }
787
788    fn parse_type(&mut self) -> Result<Type, ParseError> {
789        let token = self.next_token()?;
790        match token {
791            Token::SparseSkip => Ok(Type::Trit), // skip as marker
792            Token::Packed     => {
793                self.expect(Token::TritType)?;
794                if let Ok(Token::LBracket) = self.peek_token() {
795                    self.next_token()?;
796                    let dim = if let Ok(Token::Int(n)) = self.peek_token() {
797                        self.next_token()?;
798                        n as usize
799                    } else { 0 };
800                    self.expect(Token::RBracket)?;
801                    Ok(Type::PackedTritTensor { dims: vec![dim] })
802                } else {
803                    Ok(Type::PackedTritTensor { dims: vec![0] })
804                }
805            }
806            Token::TritType   => {
807                if let Ok(Token::LBracket) = self.peek_token() {
808                    self.next_token()?;
809                    let dim = if let Ok(Token::Int(n)) = self.peek_token() {
810                        self.next_token()?;
811                        n as usize
812                    } else { 0 };
813                    self.expect(Token::RBracket)?;
814                    Ok(Type::TritTensor { dims: vec![dim] })
815                } else {
816                    Ok(Type::Trit)
817                }
818            }
819            Token::AgentRef   => Ok(Type::AgentRef),
820            Token::TritTensor => {
821                self.expect(Token::LAngle)?;
822                let mut dims = Vec::new();
823                loop {
824                    let d = match self.next_token()? {
825                        Token::Int(v) => v as usize,
826                        // TritLiteral matches "0" and "1" — accept them as dims
827                        Token::TritLiteral => {
828                            let s = self.lex.slice();
829                            s.parse::<i8>().unwrap_or(0).max(0) as usize
830                        }
831                        t => return Err(ParseError::ExpectedToken("dimension".into(), format!("{:?}", t))),
832                    };
833                    dims.push(d);
834                    if self.peek_token()? == Token::Ident("x".to_string()) {
835                        self.next_token()?;
836                    } else {
837                        break;
838                    }
839                }
840                self.expect(Token::RAngle)?;
841                Ok(Type::TritTensor { dims })
842            }
843            Token::Ident(ref name) => match name.as_str() {
844                "int"    => {
845                    match self.peek_token() {
846                        Ok(Token::LBracket) => {
847                            self.next_token()?; // consume [
848                            let dim = if let Ok(Token::Int(n)) = self.peek_token() {
849                                self.next_token()?;
850                                n as usize
851                            } else { 0 };
852                            self.expect(Token::RBracket)?;
853                            Ok(Type::IntTensor { dims: vec![dim] })
854                        }
855                        _ => Ok(Type::Int)
856                    }
857                }
858                "float"  => {
859                    match self.peek_token() {
860                        Ok(Token::LBracket) => {
861                            self.next_token()?; // consume [
862                            let dim = if let Ok(Token::Int(n)) = self.peek_token() {
863                                self.next_token()?;
864                                n as usize
865                            } else { 0 };
866                            self.expect(Token::RBracket)?;
867                            Ok(Type::FloatTensor { dims: vec![dim] })
868                        }
869                        _ => Ok(Type::Float)
870                    }
871                }
872                "bool"   => Ok(Type::Bool),
873                "string" => Ok(Type::String),
874                // Named struct type
875                _        => Ok(Type::Named(name.clone())),
876            },
877            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
878        }
879    }
880
881    fn expect(&mut self, expected: Token) -> Result<(), ParseError> {
882        let token = self.next_token()?;
883        if token == expected {
884            Ok(())
885        } else {
886            Err(ParseError::ExpectedToken(format!("{:?}", expected), format!("{:?}", token)))
887        }
888    }
889}
890
891#[cfg(test)]
892mod tests {
893    use super::*;
894
895    #[test]
896    fn test_parse_function() {
897        let input = "fn invert(signal: trit) -> trit { return -signal; }";
898        let mut parser = Parser::new(input);
899        let func = parser.parse_function().unwrap();
900        assert_eq!(func.name, "invert");
901        assert_eq!(func.params[0].1, Type::Trit);
902        assert_eq!(func.return_type, Type::Trit);
903    }
904
905    #[test]
906    fn test_parse_match() {
907        let input = "match x { 1 => return 1; 0 => return 0; -1 => return -1; }";
908        let mut parser = Parser::new(input);
909        let stmt = parser.parse_stmt().unwrap();
910        if let Stmt::Match { arms, .. } = stmt {
911            use crate::ast::Pattern;
912            assert_eq!(arms.len(), 3);
913            assert_eq!(arms[0].0, Pattern::Int(1));
914            assert_eq!(arms[1].0, Pattern::Int(0));
915            assert_eq!(arms[2].0, Pattern::Int(-1));
916        } else {
917            panic!("Expected Match");
918        }
919    }
920
921    #[test]
922    fn test_match_parses_non_exhaustive() {
923        // Missing hold (0) arm — now parses (exhaustiveness moved to semantic)
924        let input = "match x { 1 => return 1; -1 => return -1; }";
925        let mut parser = Parser::new(input);
926        let result = parser.parse_stmt();
927        assert!(result.is_ok(), "should parse successfully even if non-exhaustive");
928    }
929
930    #[test]
931    fn test_parse_for_loop() {
932        let input = "for item in weights { return item; }";
933        let mut parser = Parser::new(input);
934        let stmt = parser.parse_stmt().unwrap();
935        assert!(matches!(stmt, Stmt::ForIn { .. }));
936    }
937
938    #[test]
939    fn test_parse_loop_break() {
940        let input = "loop { break; }";
941        let mut parser = Parser::new(input);
942        let stmt = parser.parse_stmt().unwrap();
943        assert!(matches!(stmt, Stmt::Loop { .. }));
944    }
945
946    #[test]
947    fn test_parse_use() {
948        let input = "use std::trit;";
949        let mut parser = Parser::new(input);
950        let stmt = parser.parse_stmt().unwrap();
951        if let Stmt::Use { path } = stmt {
952            assert_eq!(path, vec!["std", "trit"]);
953        } else {
954            panic!("Expected Use");
955        }
956    }
957
958    #[test]
959    fn test_parse_mut_let() {
960        let input = "let mut signal: trit = 1;";
961        let mut parser = Parser::new(input);
962        let stmt = parser.parse_stmt().unwrap();
963        assert!(matches!(stmt, Stmt::Let { .. }));
964    }
965
966    #[test]
967    fn test_parse_struct_def() {
968        let input = "struct Signal { value: trit, weight: trit }";
969        let mut parser = Parser::new(input);
970        let s = parser.parse_struct_def().unwrap();
971        assert_eq!(s.name, "Signal");
972        assert_eq!(s.fields.len(), 2);
973        assert_eq!(s.fields[0], ("value".to_string(), Type::Trit));
974        assert_eq!(s.fields[1], ("weight".to_string(), Type::Trit));
975    }
976
977    #[test]
978    fn test_parse_field_access() {
979        let input = "let v: trit = sig.value;";
980        let mut parser = Parser::new(input);
981        let stmt = parser.parse_stmt().unwrap();
982        if let Stmt::Let { value: Expr::FieldAccess { field, .. }, .. } = stmt {
983            assert_eq!(field, "value");
984        } else {
985            panic!("Expected FieldAccess in let binding");
986        }
987    }
988
989    #[test]
990    fn test_parse_field_set() {
991        let input = "sig.value = 1;";
992        let mut parser = Parser::new(input);
993        let stmt = parser.parse_stmt().unwrap();
994        assert!(matches!(stmt, Stmt::FieldSet { .. }));
995    }
996
997    #[test]
998    fn test_parse_cast() {
999        let input = "let t: trit = cast(flag);";
1000        let mut parser = Parser::new(input);
1001        let stmt = parser.parse_stmt().unwrap();
1002        if let Stmt::Let { value: Expr::Cast { .. }, .. } = stmt {
1003            // ok
1004        } else {
1005            panic!("Expected Cast in let binding");
1006        }
1007    }
1008
1009    #[test]
1010    fn test_parse_named_type() {
1011        let input = "let s: Signal;";
1012        let mut parser = Parser::new(input);
1013        let stmt = parser.parse_stmt().unwrap();
1014        if let Stmt::Let { ty: Type::Named(name), .. } = stmt {
1015            assert_eq!(name, "Signal");
1016        } else {
1017            panic!("Expected Named type");
1018        }
1019    }
1020
1021    #[test]
1022    fn test_parse_agent_def() {
1023        let input = r#"
1024            agent Voter {
1025                fn handle(msg: trit) -> trit {
1026                    match msg {
1027                         1 => { return  1; }
1028                         0 => { return  0; }
1029                        -1 => { return -1; }
1030                    }
1031                }
1032            }
1033        "#;
1034        let mut parser = Parser::new(input);
1035        let agent = parser.parse_agent_def().unwrap();
1036        assert_eq!(agent.name, "Voter");
1037        assert_eq!(agent.methods.len(), 1);
1038        assert_eq!(agent.methods[0].name, "handle");
1039    }
1040
1041    #[test]
1042    fn test_parse_spawn() {
1043        let input = "let v: agentref = spawn Voter;";
1044        let mut parser = Parser::new(input);
1045        let stmt = parser.parse_stmt().unwrap();
1046        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
1047            assert_eq!(agent_name, "Voter");
1048            assert_eq!(node_addr, None);
1049        } else {
1050            panic!("Expected spawn in let binding");
1051        }
1052    }
1053
1054    #[test]
1055    fn test_parse_spawn_remote() {
1056        let input = r#"let v: agentref = spawn remote "10.0.0.1:7373" Voter;"#;
1057        let mut parser = Parser::new(input);
1058        let stmt = parser.parse_stmt().unwrap();
1059        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
1060            assert_eq!(agent_name, "Voter");
1061            assert_eq!(node_addr, Some("10.0.0.1:7373".to_string()));
1062        } else {
1063            panic!("Expected remote spawn in let binding");
1064        }
1065    }
1066
1067    #[test]
1068    fn test_parse_send() {
1069        let input = "send v 1;";
1070        let mut parser = Parser::new(input);
1071        let stmt = parser.parse_stmt().unwrap();
1072        assert!(matches!(stmt, Stmt::Send { .. }));
1073    }
1074
1075    #[test]
1076    fn test_parse_await() {
1077        let input = "let reply: trit = await v;";
1078        let mut parser = Parser::new(input);
1079        let stmt = parser.parse_stmt().unwrap();
1080        if let Stmt::Let { value: Expr::Await { .. }, .. } = stmt {
1081            // ok
1082        } else {
1083            panic!("Expected await in let binding");
1084        }
1085    }
1086}