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