Skip to main content

snc_core/
parser.rs

1use crate::ast::*;
2use crate::error::{CompileError, CompileResult, Span};
3use crate::lexer::{SpannedToken, Token};
4
5pub struct Parser {
6    tokens: Vec<SpannedToken>,
7    pos: usize,
8}
9
10impl Parser {
11    pub fn new(tokens: Vec<SpannedToken>) -> Self {
12        Self { tokens, pos: 0 }
13    }
14
15    fn span(&self) -> Span {
16        self.tokens
17            .get(self.pos)
18            .map(|t| t.span.clone())
19            .unwrap_or(Span {
20                offset: 0,
21                line: 0,
22                column: 0,
23            })
24    }
25
26    fn peek(&self) -> &Token {
27        self.tokens
28            .get(self.pos)
29            .map(|t| &t.token)
30            .unwrap_or(&Token::Eof)
31    }
32
33    fn advance(&mut self) -> &Token {
34        let t = &self.tokens[self.pos].token;
35        if self.pos < self.tokens.len() - 1 {
36            self.pos += 1;
37        }
38        t
39    }
40
41    fn expect(&mut self, expected: &Token) -> CompileResult<()> {
42        if self.peek() == expected {
43            self.advance();
44            Ok(())
45        } else {
46            Err(CompileError::syntax(
47                self.span(),
48                format!("expected {:?}, got {:?}", expected, self.peek()),
49            ))
50        }
51    }
52
53    fn expect_ident(&mut self) -> CompileResult<String> {
54        match self.peek().clone() {
55            Token::Ident(name) => {
56                let name = name.clone();
57                self.advance();
58                Ok(name)
59            }
60            _ => Err(CompileError::syntax(
61                self.span(),
62                format!("expected identifier, got {:?}", self.peek()),
63            )),
64        }
65    }
66
67    fn expect_string(&mut self) -> CompileResult<String> {
68        match self.peek().clone() {
69            Token::StringLit(s) => {
70                let s = s.clone();
71                self.advance();
72                Ok(s)
73            }
74            _ => Err(CompileError::syntax(
75                self.span(),
76                format!("expected string literal, got {:?}", self.peek()),
77            )),
78        }
79    }
80
81    // --- Top-level ---
82
83    pub fn parse_program(&mut self) -> CompileResult<Program> {
84        let span = self.span();
85        self.expect(&Token::Program)?;
86        let name = self.expect_ident()?;
87
88        // Optional semicolon after program name
89        if self.peek() == &Token::Semi {
90            self.advance();
91        }
92
93        let mut options = Vec::new();
94        let mut definitions = Vec::new();
95        let mut entry = None;
96        let mut state_sets = Vec::new();
97        let mut exit = None;
98
99        loop {
100            match self.peek() {
101                Token::Eof => break,
102                Token::Option_ => {
103                    let opt = self.parse_option()?;
104                    options.push(opt.clone());
105                    definitions.push(Definition::Option(opt));
106                }
107                Token::Int | Token::Short | Token::Long | Token::Float | Token::Double
108                | Token::String_ | Token::Char | Token::Unsigned => {
109                    definitions.push(Definition::VarDecl(self.parse_var_decl()?));
110                }
111                Token::Assign => {
112                    definitions.push(Definition::Assign(self.parse_assign()?));
113                }
114                Token::Monitor => {
115                    definitions.push(Definition::Monitor(self.parse_monitor()?));
116                }
117                Token::Sync => {
118                    definitions.push(Definition::Sync(self.parse_sync()?));
119                }
120                Token::EvFlag => {
121                    definitions.push(Definition::EvFlag(self.parse_evflag()?));
122                }
123                Token::Entry => {
124                    self.advance();
125                    entry = Some(self.parse_block()?);
126                }
127                Token::Exit => {
128                    self.advance();
129                    exit = Some(self.parse_block()?);
130                }
131                Token::Ss => {
132                    state_sets.push(self.parse_state_set()?);
133                }
134                Token::EmbeddedLine(_) => {
135                    if let Token::EmbeddedLine(code) = self.peek().clone() {
136                        let code = code.clone();
137                        self.advance();
138                        definitions.push(Definition::EmbeddedCode(code));
139                    }
140                }
141                _ => {
142                    return Err(CompileError::syntax(
143                        self.span(),
144                        format!("unexpected token at top level: {:?}", self.peek()),
145                    ));
146                }
147            }
148        }
149
150        Ok(Program {
151            name,
152            options,
153            definitions,
154            entry,
155            state_sets,
156            exit,
157            span,
158        })
159    }
160
161    fn parse_option(&mut self) -> CompileResult<ProgramOption> {
162        self.expect(&Token::Option_)?;
163        self.expect(&Token::Plus)?;
164
165        let ident = self.expect_ident()?;
166        self.expect(&Token::Semi)?;
167
168        match ident.as_str() {
169            "s" => Ok(ProgramOption::Safe),
170            "r" => Ok(ProgramOption::Reentrant),
171            "m" => Ok(ProgramOption::Main),
172            _ => Err(CompileError::syntax(
173                self.span(),
174                format!("unknown option: +{ident}"),
175            )),
176        }
177    }
178
179    fn parse_type_spec(&mut self) -> CompileResult<TypeSpec> {
180        let ts = match self.peek() {
181            Token::Int => { self.advance(); TypeSpec::Int }
182            Token::Short => { self.advance(); TypeSpec::Short }
183            Token::Long => { self.advance(); TypeSpec::Long }
184            Token::Float => { self.advance(); TypeSpec::Float }
185            Token::Double => { self.advance(); TypeSpec::Double }
186            Token::String_ => { self.advance(); TypeSpec::String }
187            Token::Char => { self.advance(); TypeSpec::Char }
188            Token::Unsigned => {
189                self.advance();
190                let inner = if matches!(
191                    self.peek(),
192                    Token::Int | Token::Short | Token::Long | Token::Char
193                ) {
194                    self.parse_type_spec()?
195                } else {
196                    TypeSpec::Int
197                };
198                TypeSpec::Unsigned(Box::new(inner))
199            }
200            _ => {
201                return Err(CompileError::syntax(
202                    self.span(),
203                    format!("expected type, got {:?}", self.peek()),
204                ));
205            }
206        };
207        Ok(ts)
208    }
209
210    fn parse_var_decl(&mut self) -> CompileResult<VarDecl> {
211        let span = self.span();
212        let type_spec = self.parse_type_spec()?;
213        let name = self.expect_ident()?;
214
215        // Parse array dimensions: name[N][M]...
216        let mut dimensions = Vec::new();
217        while self.peek() == &Token::LBracket {
218            self.advance();
219            let dim = self.parse_expr()?;
220            self.expect(&Token::RBracket)?;
221            dimensions.push(dim);
222        }
223
224        let init = if self.peek() == &Token::Assign_ {
225            self.advance();
226            if self.peek() == &Token::LBrace {
227                // Brace initializer: = {1, 2, 3}
228                Some(self.parse_brace_init()?)
229            } else {
230                Some(self.parse_expr()?)
231            }
232        } else {
233            None
234        };
235
236        self.expect(&Token::Semi)?;
237
238        Ok(VarDecl {
239            type_spec,
240            name,
241            dimensions,
242            init,
243            span,
244        })
245    }
246
247    fn parse_brace_init(&mut self) -> CompileResult<Expr> {
248        let span = self.span();
249        self.expect(&Token::LBrace)?;
250        let mut elements = Vec::new();
251        if self.peek() != &Token::RBrace {
252            elements.push(self.parse_expr()?);
253            while self.peek() == &Token::Comma {
254                self.advance();
255                if self.peek() == &Token::RBrace {
256                    break; // trailing comma
257                }
258                elements.push(self.parse_expr()?);
259            }
260        }
261        self.expect(&Token::RBrace)?;
262        Ok(Expr::ArrayInit(elements, span))
263    }
264
265    fn parse_assign(&mut self) -> CompileResult<Assign> {
266        let span = self.span();
267        self.expect(&Token::Assign)?;
268        let var_name = self.expect_ident()?;
269
270        let pv_name = if self.peek() == &Token::To {
271            self.advance();
272            Some(self.expect_string()?)
273        } else {
274            // assign var; (assigns to var name as PV name)
275            None
276        };
277
278        self.expect(&Token::Semi)?;
279        Ok(Assign {
280            var_name,
281            pv_name,
282            span,
283        })
284    }
285
286    fn parse_monitor(&mut self) -> CompileResult<Monitor> {
287        let span = self.span();
288        self.expect(&Token::Monitor)?;
289        let var_name = self.expect_ident()?;
290        self.expect(&Token::Semi)?;
291        Ok(Monitor { var_name, span })
292    }
293
294    fn parse_sync(&mut self) -> CompileResult<Sync> {
295        let span = self.span();
296        self.expect(&Token::Sync)?;
297        let var_name = self.expect_ident()?;
298
299        // "sync var to ef_name" or "sync var ef_name"
300        if self.peek() == &Token::To {
301            self.advance();
302        }
303
304        let ef_name = self.expect_ident()?;
305        self.expect(&Token::Semi)?;
306        Ok(Sync {
307            var_name,
308            ef_name,
309            span,
310        })
311    }
312
313    fn parse_evflag(&mut self) -> CompileResult<EvFlagDecl> {
314        let span = self.span();
315        self.expect(&Token::EvFlag)?;
316        let name = self.expect_ident()?;
317        self.expect(&Token::Semi)?;
318        Ok(EvFlagDecl { name, span })
319    }
320
321    // --- State sets ---
322
323    fn parse_state_set(&mut self) -> CompileResult<StateSet> {
324        let span = self.span();
325        self.expect(&Token::Ss)?;
326        let name = self.expect_ident()?;
327        self.expect(&Token::LBrace)?;
328
329        let mut local_vars = Vec::new();
330        let mut states = Vec::new();
331
332        loop {
333            match self.peek() {
334                Token::RBrace => {
335                    self.advance();
336                    break;
337                }
338                Token::State => {
339                    states.push(self.parse_state()?);
340                }
341                Token::Int | Token::Short | Token::Long | Token::Float | Token::Double
342                | Token::String_ | Token::Char | Token::Unsigned => {
343                    local_vars.push(self.parse_var_decl()?);
344                }
345                _ => {
346                    return Err(CompileError::syntax(
347                        self.span(),
348                        format!("expected state or variable in ss, got {:?}", self.peek()),
349                    ));
350                }
351            }
352        }
353
354        Ok(StateSet {
355            name,
356            local_vars,
357            states,
358            span,
359        })
360    }
361
362    fn parse_state(&mut self) -> CompileResult<State> {
363        let span = self.span();
364        self.expect(&Token::State)?;
365        let name = self.expect_ident()?;
366        self.expect(&Token::LBrace)?;
367
368        let mut entry_block = None;
369        let mut transitions = Vec::new();
370        let mut exit_block = None;
371
372        loop {
373            match self.peek() {
374                Token::RBrace => {
375                    self.advance();
376                    break;
377                }
378                Token::Entry => {
379                    self.advance();
380                    entry_block = Some(self.parse_block()?);
381                }
382                Token::Exit => {
383                    self.advance();
384                    exit_block = Some(self.parse_block()?);
385                }
386                Token::When => {
387                    transitions.push(self.parse_transition()?);
388                }
389                _ => {
390                    return Err(CompileError::syntax(
391                        self.span(),
392                        format!("expected when/entry/exit in state, got {:?}", self.peek()),
393                    ));
394                }
395            }
396        }
397
398        Ok(State {
399            name,
400            entry: entry_block,
401            transitions,
402            exit: exit_block,
403            span,
404        })
405    }
406
407    fn parse_transition(&mut self) -> CompileResult<Transition> {
408        let span = self.span();
409        self.expect(&Token::When)?;
410        self.expect(&Token::LParen)?;
411
412        let condition = if self.peek() == &Token::RParen {
413            None // empty condition = always true
414        } else {
415            Some(self.parse_expr()?)
416        };
417
418        self.expect(&Token::RParen)?;
419
420        let body = self.parse_block()?;
421
422        // Target: "state <name>" or "exit"
423        let target = match self.peek() {
424            Token::State => {
425                self.advance();
426                let target_name = self.expect_ident()?;
427                TransitionTarget::State(target_name)
428            }
429            Token::Exit => {
430                self.advance();
431                TransitionTarget::Exit
432            }
433            _ => {
434                return Err(CompileError::syntax(
435                    self.span(),
436                    format!("expected 'state' or 'exit' after when block, got {:?}", self.peek()),
437                ));
438            }
439        };
440
441        Ok(Transition {
442            condition,
443            body,
444            target,
445            span,
446        })
447    }
448
449    // --- Blocks and statements ---
450
451    fn parse_block(&mut self) -> CompileResult<Block> {
452        let span = self.span();
453        self.expect(&Token::LBrace)?;
454        let mut stmts = Vec::new();
455
456        loop {
457            if self.peek() == &Token::RBrace {
458                self.advance();
459                break;
460            }
461            stmts.push(self.parse_stmt()?);
462        }
463
464        Ok(Block { stmts, span })
465    }
466
467    fn parse_stmt(&mut self) -> CompileResult<Stmt> {
468        match self.peek() {
469            Token::If => self.parse_if(),
470            Token::While => self.parse_while(),
471            Token::For => self.parse_for(),
472            Token::Break => {
473                self.advance();
474                self.expect(&Token::Semi)?;
475                Ok(Stmt::Break)
476            }
477            Token::Return => {
478                self.advance();
479                let val = if self.peek() != &Token::Semi {
480                    Some(self.parse_expr()?)
481                } else {
482                    None
483                };
484                self.expect(&Token::Semi)?;
485                Ok(Stmt::Return(val))
486            }
487            Token::LBrace => Ok(Stmt::Block(self.parse_block()?)),
488            Token::Int | Token::Short | Token::Long | Token::Float | Token::Double
489            | Token::String_ | Token::Char | Token::Unsigned => {
490                Ok(Stmt::VarDecl(self.parse_var_decl()?))
491            }
492            Token::EmbeddedLine(_) => {
493                if let Token::EmbeddedLine(code) = self.peek().clone() {
494                    let code = code.clone();
495                    self.advance();
496                    Ok(Stmt::EmbeddedCode(code))
497                } else {
498                    unreachable!()
499                }
500            }
501            _ => {
502                let expr = self.parse_expr()?;
503                self.expect(&Token::Semi)?;
504                Ok(Stmt::Expr(expr))
505            }
506        }
507    }
508
509    fn parse_if(&mut self) -> CompileResult<Stmt> {
510        self.expect(&Token::If)?;
511        self.expect(&Token::LParen)?;
512        let cond = self.parse_expr()?;
513        self.expect(&Token::RParen)?;
514
515        let then_block = if self.peek() == &Token::LBrace {
516            self.parse_block()?
517        } else {
518            let span = self.span();
519            let stmt = self.parse_stmt()?;
520            Block {
521                stmts: vec![stmt],
522                span,
523            }
524        };
525
526        let else_block = if self.peek() == &Token::Else {
527            self.advance();
528            if self.peek() == &Token::LBrace {
529                Some(self.parse_block()?)
530            } else {
531                let span = self.span();
532                let stmt = self.parse_stmt()?;
533                Some(Block {
534                    stmts: vec![stmt],
535                    span,
536                })
537            }
538        } else {
539            None
540        };
541
542        Ok(Stmt::If(cond, then_block, else_block))
543    }
544
545    fn parse_while(&mut self) -> CompileResult<Stmt> {
546        self.expect(&Token::While)?;
547        self.expect(&Token::LParen)?;
548        let cond = self.parse_expr()?;
549        self.expect(&Token::RParen)?;
550        let body = if self.peek() == &Token::LBrace {
551            self.parse_block()?
552        } else {
553            let span = self.span();
554            let stmt = self.parse_stmt()?;
555            Block {
556                stmts: vec![stmt],
557                span,
558            }
559        };
560        Ok(Stmt::While(cond, body))
561    }
562
563    fn parse_for(&mut self) -> CompileResult<Stmt> {
564        self.expect(&Token::For)?;
565        self.expect(&Token::LParen)?;
566        let init = if self.peek() == &Token::Semi {
567            None
568        } else {
569            Some(Box::new(self.parse_expr()?))
570        };
571        self.expect(&Token::Semi)?;
572        let cond = if self.peek() == &Token::Semi {
573            None
574        } else {
575            Some(self.parse_expr()?)
576        };
577        self.expect(&Token::Semi)?;
578        let step = if self.peek() == &Token::RParen {
579            None
580        } else {
581            Some(Box::new(self.parse_expr()?))
582        };
583        self.expect(&Token::RParen)?;
584        let body = if self.peek() == &Token::LBrace {
585            self.parse_block()?
586        } else {
587            let span = self.span();
588            let stmt = self.parse_stmt()?;
589            Block {
590                stmts: vec![stmt],
591                span,
592            }
593        };
594        Ok(Stmt::For(init, cond, step, body))
595    }
596
597    // --- Expressions (precedence climbing) ---
598
599    fn parse_expr(&mut self) -> CompileResult<Expr> {
600        self.parse_assignment()
601    }
602
603    fn parse_assignment(&mut self) -> CompileResult<Expr> {
604        let lhs = self.parse_ternary()?;
605
606        match self.peek() {
607            Token::Assign_ => {
608                let span = self.span();
609                self.advance();
610                let rhs = self.parse_assignment()?;
611                Ok(Expr::Assign(Box::new(lhs), Box::new(rhs), span))
612            }
613            Token::PlusEq => {
614                let span = self.span();
615                self.advance();
616                let rhs = self.parse_assignment()?;
617                Ok(Expr::CompoundAssign(
618                    Box::new(lhs),
619                    BinOp::Add,
620                    Box::new(rhs),
621                    span,
622                ))
623            }
624            Token::MinusEq => {
625                let span = self.span();
626                self.advance();
627                let rhs = self.parse_assignment()?;
628                Ok(Expr::CompoundAssign(
629                    Box::new(lhs),
630                    BinOp::Sub,
631                    Box::new(rhs),
632                    span,
633                ))
634            }
635            Token::StarEq => {
636                let span = self.span();
637                self.advance();
638                let rhs = self.parse_assignment()?;
639                Ok(Expr::CompoundAssign(
640                    Box::new(lhs),
641                    BinOp::Mul,
642                    Box::new(rhs),
643                    span,
644                ))
645            }
646            Token::SlashEq => {
647                let span = self.span();
648                self.advance();
649                let rhs = self.parse_assignment()?;
650                Ok(Expr::CompoundAssign(
651                    Box::new(lhs),
652                    BinOp::Div,
653                    Box::new(rhs),
654                    span,
655                ))
656            }
657            _ => Ok(lhs),
658        }
659    }
660
661    fn parse_ternary(&mut self) -> CompileResult<Expr> {
662        let cond = self.parse_or()?;
663        if self.peek() == &Token::Question {
664            let span = self.span();
665            self.advance();
666            let then_expr = self.parse_expr()?;
667            self.expect(&Token::Colon)?;
668            let else_expr = self.parse_ternary()?;
669            Ok(Expr::Ternary(
670                Box::new(cond),
671                Box::new(then_expr),
672                Box::new(else_expr),
673                span,
674            ))
675        } else {
676            Ok(cond)
677        }
678    }
679
680    fn parse_or(&mut self) -> CompileResult<Expr> {
681        let mut lhs = self.parse_and()?;
682        while self.peek() == &Token::Or {
683            let span = self.span();
684            self.advance();
685            let rhs = self.parse_and()?;
686            lhs = Expr::BinaryOp(Box::new(lhs), BinOp::Or, Box::new(rhs), span);
687        }
688        Ok(lhs)
689    }
690
691    fn parse_and(&mut self) -> CompileResult<Expr> {
692        let mut lhs = self.parse_bitor()?;
693        while self.peek() == &Token::And {
694            let span = self.span();
695            self.advance();
696            let rhs = self.parse_bitor()?;
697            lhs = Expr::BinaryOp(Box::new(lhs), BinOp::And, Box::new(rhs), span);
698        }
699        Ok(lhs)
700    }
701
702    fn parse_bitor(&mut self) -> CompileResult<Expr> {
703        let mut lhs = self.parse_bitxor()?;
704        while self.peek() == &Token::BitOr {
705            let span = self.span();
706            self.advance();
707            let rhs = self.parse_bitxor()?;
708            lhs = Expr::BinaryOp(Box::new(lhs), BinOp::BitOr, Box::new(rhs), span);
709        }
710        Ok(lhs)
711    }
712
713    fn parse_bitxor(&mut self) -> CompileResult<Expr> {
714        let mut lhs = self.parse_bitand()?;
715        while self.peek() == &Token::BitXor {
716            let span = self.span();
717            self.advance();
718            let rhs = self.parse_bitand()?;
719            lhs = Expr::BinaryOp(Box::new(lhs), BinOp::BitXor, Box::new(rhs), span);
720        }
721        Ok(lhs)
722    }
723
724    fn parse_bitand(&mut self) -> CompileResult<Expr> {
725        let mut lhs = self.parse_equality()?;
726        while self.peek() == &Token::BitAnd {
727            let span = self.span();
728            self.advance();
729            let rhs = self.parse_equality()?;
730            lhs = Expr::BinaryOp(Box::new(lhs), BinOp::BitAnd, Box::new(rhs), span);
731        }
732        Ok(lhs)
733    }
734
735    fn parse_equality(&mut self) -> CompileResult<Expr> {
736        let mut lhs = self.parse_comparison()?;
737        loop {
738            let op = match self.peek() {
739                Token::Eq => BinOp::Eq,
740                Token::Ne => BinOp::Ne,
741                _ => break,
742            };
743            let span = self.span();
744            self.advance();
745            let rhs = self.parse_comparison()?;
746            lhs = Expr::BinaryOp(Box::new(lhs), op, Box::new(rhs), span);
747        }
748        Ok(lhs)
749    }
750
751    fn parse_comparison(&mut self) -> CompileResult<Expr> {
752        let mut lhs = self.parse_shift()?;
753        loop {
754            let op = match self.peek() {
755                Token::Lt => BinOp::Lt,
756                Token::Le => BinOp::Le,
757                Token::Gt => BinOp::Gt,
758                Token::Ge => BinOp::Ge,
759                _ => break,
760            };
761            let span = self.span();
762            self.advance();
763            let rhs = self.parse_shift()?;
764            lhs = Expr::BinaryOp(Box::new(lhs), op, Box::new(rhs), span);
765        }
766        Ok(lhs)
767    }
768
769    fn parse_shift(&mut self) -> CompileResult<Expr> {
770        let mut lhs = self.parse_additive()?;
771        loop {
772            let op = match self.peek() {
773                Token::Shl => BinOp::Shl,
774                Token::Shr => BinOp::Shr,
775                _ => break,
776            };
777            let span = self.span();
778            self.advance();
779            let rhs = self.parse_additive()?;
780            lhs = Expr::BinaryOp(Box::new(lhs), op, Box::new(rhs), span);
781        }
782        Ok(lhs)
783    }
784
785    fn parse_additive(&mut self) -> CompileResult<Expr> {
786        let mut lhs = self.parse_multiplicative()?;
787        loop {
788            let op = match self.peek() {
789                Token::Plus => BinOp::Add,
790                Token::Minus => BinOp::Sub,
791                _ => break,
792            };
793            let span = self.span();
794            self.advance();
795            let rhs = self.parse_multiplicative()?;
796            lhs = Expr::BinaryOp(Box::new(lhs), op, Box::new(rhs), span);
797        }
798        Ok(lhs)
799    }
800
801    fn parse_multiplicative(&mut self) -> CompileResult<Expr> {
802        let mut lhs = self.parse_unary()?;
803        loop {
804            let op = match self.peek() {
805                Token::Star => BinOp::Mul,
806                Token::Slash => BinOp::Div,
807                Token::Percent => BinOp::Mod,
808                _ => break,
809            };
810            let span = self.span();
811            self.advance();
812            let rhs = self.parse_unary()?;
813            lhs = Expr::BinaryOp(Box::new(lhs), op, Box::new(rhs), span);
814        }
815        Ok(lhs)
816    }
817
818    fn parse_unary(&mut self) -> CompileResult<Expr> {
819        match self.peek() {
820            Token::Minus => {
821                let span = self.span();
822                self.advance();
823                let expr = self.parse_unary()?;
824                Ok(Expr::UnaryOp(UnaryOp::Neg, Box::new(expr), span))
825            }
826            Token::Not => {
827                let span = self.span();
828                self.advance();
829                let expr = self.parse_unary()?;
830                Ok(Expr::UnaryOp(UnaryOp::Not, Box::new(expr), span))
831            }
832            Token::BitNot => {
833                let span = self.span();
834                self.advance();
835                let expr = self.parse_unary()?;
836                Ok(Expr::UnaryOp(UnaryOp::BitNot, Box::new(expr), span))
837            }
838            Token::PlusPlus => {
839                let span = self.span();
840                self.advance();
841                let expr = self.parse_unary()?;
842                Ok(Expr::PreIncr(Box::new(expr), span))
843            }
844            Token::MinusMinus => {
845                let span = self.span();
846                self.advance();
847                let expr = self.parse_unary()?;
848                Ok(Expr::PreDecr(Box::new(expr), span))
849            }
850            _ => self.parse_postfix(),
851        }
852    }
853
854    fn parse_postfix(&mut self) -> CompileResult<Expr> {
855        let mut expr = self.parse_primary()?;
856
857        loop {
858            match self.peek() {
859                Token::PlusPlus => {
860                    let span = self.span();
861                    self.advance();
862                    expr = Expr::PostIncr(Box::new(expr), span);
863                }
864                Token::MinusMinus => {
865                    let span = self.span();
866                    self.advance();
867                    expr = Expr::PostDecr(Box::new(expr), span);
868                }
869                Token::LBracket => {
870                    let span = self.span();
871                    self.advance();
872                    let index = self.parse_expr()?;
873                    self.expect(&Token::RBracket)?;
874                    expr = Expr::Index(Box::new(expr), Box::new(index), span);
875                }
876                Token::Dot => {
877                    let span = self.span();
878                    self.advance();
879                    let field = self.expect_ident()?;
880                    expr = Expr::Field(Box::new(expr), field, span);
881                }
882                Token::Arrow => {
883                    let span = self.span();
884                    self.advance();
885                    let field = self.expect_ident()?;
886                    expr = Expr::Field(Box::new(expr), field, span);
887                }
888                _ => break,
889            }
890        }
891
892        Ok(expr)
893    }
894
895    fn parse_primary(&mut self) -> CompileResult<Expr> {
896        match self.peek().clone() {
897            Token::IntLit(v) => {
898                let span = self.span();
899                let v = v;
900                self.advance();
901                Ok(Expr::IntLit(v, span))
902            }
903            Token::FloatLit(v) => {
904                let span = self.span();
905                let v = v;
906                self.advance();
907                Ok(Expr::FloatLit(v, span))
908            }
909            Token::StringLit(s) => {
910                let span = self.span();
911                let s = s.clone();
912                self.advance();
913                Ok(Expr::StringLit(s, span))
914            }
915            Token::Ident(name) => {
916                let span = self.span();
917                let name = name.clone();
918                self.advance();
919
920                // Function call?
921                if self.peek() == &Token::LParen {
922                    self.advance();
923                    let mut args = Vec::new();
924                    if self.peek() != &Token::RParen {
925                        args.push(self.parse_expr()?);
926                        while self.peek() == &Token::Comma {
927                            self.advance();
928                            args.push(self.parse_expr()?);
929                        }
930                    }
931                    self.expect(&Token::RParen)?;
932                    Ok(Expr::Call(name, args, span))
933                } else {
934                    Ok(Expr::Ident(name, span))
935                }
936            }
937            Token::LParen => {
938                let span = self.span();
939                self.advance();
940                let expr = self.parse_expr()?;
941                self.expect(&Token::RParen)?;
942                Ok(Expr::Paren(Box::new(expr), span))
943            }
944            _ => Err(CompileError::syntax(
945                self.span(),
946                format!("expected expression, got {:?}", self.peek()),
947            )),
948        }
949    }
950}
951
952#[cfg(test)]
953mod tests {
954    use super::*;
955    use crate::lexer::Lexer;
956
957    fn parse(input: &str) -> Program {
958        let tokens = Lexer::new(input).tokenize().unwrap();
959        Parser::new(tokens).parse_program().unwrap()
960    }
961
962    #[test]
963    fn test_minimal_program() {
964        let p = parse("program test ss s1 { state init { when () { } exit } }");
965        assert_eq!(p.name, "test");
966        assert_eq!(p.state_sets.len(), 1);
967        assert_eq!(p.state_sets[0].name, "s1");
968        assert_eq!(p.state_sets[0].states.len(), 1);
969        assert_eq!(p.state_sets[0].states[0].transitions.len(), 1);
970    }
971
972    #[test]
973    fn test_var_assign_monitor() {
974        let p = parse(r#"
975            program test
976            double x;
977            assign x to "PV:x";
978            monitor x;
979            ss s1 { state init { when () { } exit } }
980        "#);
981        let defs = &p.definitions;
982        assert!(matches!(defs[0], Definition::VarDecl(_)));
983        assert!(matches!(defs[1], Definition::Assign(_)));
984        assert!(matches!(defs[2], Definition::Monitor(_)));
985    }
986
987    #[test]
988    fn test_evflag_sync() {
989        let p = parse(r#"
990            program test
991            double x;
992            assign x to "PV:x";
993            monitor x;
994            evflag ef_x;
995            sync x to ef_x;
996            ss s1 { state init { when () { } exit } }
997        "#);
998        let has_evflag = p
999            .definitions
1000            .iter()
1001            .any(|d| matches!(d, Definition::EvFlag(_)));
1002        let has_sync = p
1003            .definitions
1004            .iter()
1005            .any(|d| matches!(d, Definition::Sync(_)));
1006        assert!(has_evflag);
1007        assert!(has_sync);
1008    }
1009
1010    #[test]
1011    fn test_option_safe() {
1012        let p = parse(r#"
1013            program test
1014            option +s;
1015            ss s1 { state init { when () { } exit } }
1016        "#);
1017        assert_eq!(p.options.len(), 1);
1018        assert!(matches!(p.options[0], ProgramOption::Safe));
1019    }
1020
1021    #[test]
1022    fn test_state_transition() {
1023        let p = parse(r#"
1024            program test
1025            ss s1 {
1026                state a {
1027                    when (x > 0) {
1028                        y = 1;
1029                    } state b
1030                }
1031                state b {
1032                    when () { } exit
1033                }
1034            }
1035        "#);
1036        let ss = &p.state_sets[0];
1037        assert_eq!(ss.states.len(), 2);
1038        let t = &ss.states[0].transitions[0];
1039        assert!(matches!(t.target, TransitionTarget::State(ref n) if n == "b"));
1040    }
1041
1042    #[test]
1043    fn test_delay_and_pvput() {
1044        let p = parse(r#"
1045            program test
1046            double counter;
1047            assign counter to "PV:counter";
1048            ss s1 {
1049                state counting {
1050                    when (delay(1.0)) {
1051                        counter += 1.0;
1052                        pvPut(counter);
1053                    } state counting
1054                }
1055            }
1056        "#);
1057        let state = &p.state_sets[0].states[0];
1058        assert_eq!(state.transitions.len(), 1);
1059        let cond = state.transitions[0].condition.as_ref().unwrap();
1060        assert!(matches!(cond, Expr::Call(name, _, _) if name == "delay"));
1061    }
1062
1063    #[test]
1064    fn test_entry_exit_blocks() {
1065        let p = parse(r#"
1066            program test
1067            entry { x = 1; }
1068            ss s1 { state init { when () { } exit } }
1069            exit { x = 0; }
1070        "#);
1071        assert!(p.entry.is_some());
1072        assert!(p.exit.is_some());
1073    }
1074
1075    #[test]
1076    fn test_if_else_in_action() {
1077        let p = parse(r#"
1078            program test
1079            int x;
1080            ss s1 {
1081                state init {
1082                    when (x > 0) {
1083                        if (x > 5) {
1084                            y = 1;
1085                        } else {
1086                            y = 0;
1087                        }
1088                    } state init
1089                }
1090            }
1091        "#);
1092        let body = &p.state_sets[0].states[0].transitions[0].body;
1093        assert!(matches!(body.stmts[0], Stmt::If(_, _, Some(_))));
1094    }
1095
1096    #[test]
1097    fn test_array_declaration() {
1098        let p = parse(r#"
1099            program test
1100            double arr[10];
1101            ss s1 { state init { when () { } exit } }
1102        "#);
1103        let vd = match &p.definitions[0] {
1104            Definition::VarDecl(vd) => vd,
1105            _ => panic!("expected VarDecl"),
1106        };
1107        assert_eq!(vd.name, "arr");
1108        assert_eq!(vd.dimensions.len(), 1);
1109        assert!(matches!(&vd.dimensions[0], Expr::IntLit(10, _)));
1110    }
1111
1112    #[test]
1113    fn test_array_with_init() {
1114        let p = parse(r#"
1115            program test
1116            int arr[3] = {1, 2, 3};
1117            ss s1 { state init { when () { } exit } }
1118        "#);
1119        let vd = match &p.definitions[0] {
1120            Definition::VarDecl(vd) => vd,
1121            _ => panic!("expected VarDecl"),
1122        };
1123        assert_eq!(vd.name, "arr");
1124        assert!(matches!(&vd.init, Some(Expr::ArrayInit(elems, _)) if elems.len() == 3));
1125    }
1126
1127    #[test]
1128    fn test_embedded_code_top_level() {
1129        let p = parse(r#"
1130            program test
1131            %% use std::io;
1132            ss s1 { state init { when () { } exit } }
1133        "#);
1134        let has_embedded = p.definitions.iter().any(|d| matches!(d, Definition::EmbeddedCode(_)));
1135        assert!(has_embedded);
1136    }
1137
1138    #[test]
1139    fn test_safe_monitor_program() {
1140        // This mirrors a simplified safeMonitor.st
1141        let p = parse(r#"
1142            program safeMonitorTest
1143            option +s;
1144            double cnt = 1.0;
1145            assign cnt to "cnt";
1146            monitor cnt;
1147            evflag ef_cnt;
1148            sync cnt to ef_cnt;
1149            ss read {
1150                int n = 1;
1151                state react {
1152                    when (n > 10) {
1153                    } exit
1154                    when (efTestAndClear(ef_cnt)) {
1155                        n++;
1156                    } state react
1157                }
1158            }
1159            ss write {
1160                state send {
1161                    when (delay(0.04)) {
1162                        cnt += 1.0;
1163                        pvPut(cnt);
1164                    } state send
1165                }
1166            }
1167        "#);
1168        assert_eq!(p.name, "safeMonitorTest");
1169        assert_eq!(p.state_sets.len(), 2);
1170        assert_eq!(p.state_sets[0].name, "read");
1171        assert_eq!(p.state_sets[0].local_vars.len(), 1);
1172        assert_eq!(p.state_sets[1].name, "write");
1173    }
1174}