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