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