Skip to main content

wirespec_syntax/
parser.rs

1//! Recursive descent parser for wirespec.
2//!
3//! Consumes a token stream from the lexer and produces an `AstModule`.
4//! Grammar follows wirespec_spec_v1.0 §6.1 (core) and §6.2 (state machines).
5
6use crate::ast::*;
7use crate::lexer::{Token, TokenKind};
8use crate::span::Span;
9
10pub struct Parser {
11    tokens: Vec<Token>,
12    pos: usize,
13}
14
15#[derive(Debug, Clone)]
16pub struct ParseError {
17    pub msg: String,
18    pub span: Option<Span>,
19}
20
21impl std::fmt::Display for ParseError {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        if let Some(span) = &self.span {
24            write!(f, "parse error at offset {}: {}", span.offset, self.msg)
25        } else {
26            write!(f, "parse error: {}", self.msg)
27        }
28    }
29}
30
31impl std::error::Error for ParseError {}
32
33type Result<T> = std::result::Result<T, ParseError>;
34
35impl Parser {
36    pub fn new(tokens: Vec<Token>) -> Self {
37        Self { tokens, pos: 0 }
38    }
39
40    // ── Helpers ──
41
42    fn peek(&self) -> &TokenKind {
43        &self.tokens[self.pos].kind
44    }
45
46    fn span(&self) -> Span {
47        self.tokens[self.pos].span
48    }
49
50    fn at(&self, kind: &TokenKind) -> bool {
51        std::mem::discriminant(self.peek()) == std::mem::discriminant(kind)
52    }
53
54    fn at_eof(&self) -> bool {
55        matches!(self.peek(), TokenKind::Eof)
56    }
57
58    fn advance(&mut self) -> &Token {
59        let tok = &self.tokens[self.pos];
60        if !self.at_eof() {
61            self.pos += 1;
62        }
63        tok
64    }
65
66    fn expect(&mut self, kind: &TokenKind) -> Result<&Token> {
67        if self.at(kind) {
68            Ok(self.advance())
69        } else {
70            Err(self.error(format!("expected {kind:?}, found {:?}", self.peek())))
71        }
72    }
73
74    fn expect_name(&mut self) -> Result<(String, Span)> {
75        let span = self.span();
76        if let Some(name) = self.token_as_name() {
77            self.advance();
78            Ok((name, span))
79        } else {
80            Err(self.error(format!("expected identifier, found {:?}", self.peek())))
81        }
82    }
83
84    /// Consume a name token, but also allow certain keywords that can appear
85    /// as identifiers in specific contexts (e.g. field names).
86    fn expect_name_or_keyword(&mut self) -> Result<(String, Span)> {
87        // Same as expect_name — all keywords are accepted as identifiers
88        self.expect_name()
89    }
90
91    /// Try to interpret the current token as a name/identifier.
92    /// Keywords are accepted because wirespec allows keywords as field names,
93    /// module path components, etc. (e.g., `quic.varint`, `flags: u8`).
94    fn token_as_name(&self) -> Option<String> {
95        match self.peek() {
96            TokenKind::Name(n) => Some(n.clone()),
97            // All keywords that can appear as identifiers in various contexts
98            TokenKind::Module => Some("module".into()),
99            TokenKind::Import => Some("import".into()),
100            TokenKind::Const => Some("const".into()),
101            TokenKind::Enum => Some("enum".into()),
102            TokenKind::Flags => Some("flags".into()),
103            TokenKind::Type => Some("type".into()),
104            TokenKind::Packet => Some("packet".into()),
105            TokenKind::Frame => Some("frame".into()),
106            TokenKind::Capsule => Some("capsule".into()),
107            TokenKind::State => Some("state".into()),
108            TokenKind::Machine => Some("machine".into()),
109            TokenKind::Transition => Some("transition".into()),
110            TokenKind::Initial => Some("initial".into()),
111            TokenKind::Terminal => Some("terminal".into()),
112            TokenKind::On => Some("on".into()),
113            TokenKind::Guard => Some("guard".into()),
114            TokenKind::Action => Some("action".into()),
115            TokenKind::Delegate => Some("delegate".into()),
116            TokenKind::Match => Some("match".into()),
117            TokenKind::If => Some("if".into()),
118            TokenKind::Let => Some("let".into()),
119            TokenKind::Require => Some("require".into()),
120            TokenKind::StaticAssert => Some("static_assert".into()),
121            TokenKind::Within => Some("within".into()),
122            TokenKind::Export => Some("export".into()),
123            TokenKind::Varint => Some("varint".into()),
124            TokenKind::Bytes => Some("bytes".into()),
125            TokenKind::Bits => Some("bits".into()),
126            TokenKind::Bit => Some("bit".into()),
127            TokenKind::Fill => Some("fill".into()),
128            TokenKind::Remaining => Some("remaining".into()),
129            TokenKind::And => Some("and".into()),
130            TokenKind::Or => Some("or".into()),
131            TokenKind::Not => Some("not".into()),
132            TokenKind::InState => Some("in_state".into()),
133            TokenKind::All => Some("all".into()),
134            _ => None,
135        }
136    }
137
138    fn error(&self, msg: String) -> ParseError {
139        ParseError {
140            msg,
141            span: Some(self.span()),
142        }
143    }
144
145    fn eat(&mut self, kind: &TokenKind) -> bool {
146        if self.at(kind) {
147            self.advance();
148            true
149        } else {
150            false
151        }
152    }
153
154    // ── Top-level parse ──
155
156    pub fn parse_module(mut self) -> Result<AstModule> {
157        let start = self.span();
158        let mut module_decl = None;
159        let mut imports = Vec::new();
160        let mut annotations = Vec::new();
161        let mut items = Vec::new();
162
163        // Collect annotations that appear before module decl (file-level)
164        let mut pre_module_anns = self.collect_annotations()?;
165
166        // module decl (may appear after file-level annotations like @endian)
167        if self.at(&TokenKind::Module) {
168            module_decl = Some(self.parse_module_decl()?);
169            // Annotations before module decl are file-level
170            annotations.append(&mut pre_module_anns);
171        }
172
173        // Collect annotations between module decl and first item (also file-level)
174        let mut post_module_anns = self.collect_annotations()?;
175        if module_decl.is_some() {
176            annotations.append(&mut post_module_anns);
177        }
178
179        // If no module decl, merge all pre-annotations forward
180        let mut pending = if module_decl.is_none() {
181            pre_module_anns
182        } else {
183            Vec::new()
184        };
185        pending.append(&mut post_module_anns);
186
187        loop {
188            // Collect annotations
189            let mut item_annotations = self.collect_annotations()?;
190
191            // Prepend any leftover pending annotations
192            if !pending.is_empty() {
193                let mut combined = std::mem::take(&mut pending);
194                combined.append(&mut item_annotations);
195                item_annotations = combined;
196            }
197
198            if self.at_eof() {
199                // Trailing annotations with no item — attach to module
200                annotations.append(&mut item_annotations);
201                break;
202            }
203
204            if self.at(&TokenKind::Import) {
205                if !item_annotations.is_empty() {
206                    // Annotations before import go to module level
207                    annotations.append(&mut item_annotations);
208                }
209                imports.push(self.parse_import()?);
210                continue;
211            }
212
213            if let Some(item) = self.try_parse_top_item(item_annotations)? {
214                items.push(item);
215            } else if self.at_eof() {
216                break;
217            } else {
218                return Err(self.error(format!("unexpected token: {:?}", self.peek())));
219            }
220        }
221
222        Ok(AstModule {
223            module_decl,
224            imports,
225            annotations,
226            items,
227            span: Some(start),
228        })
229    }
230
231    // ── Module / Import ──
232
233    fn parse_module_decl(&mut self) -> Result<AstModuleDecl> {
234        let start = self.span();
235        self.expect(&TokenKind::Module)?;
236        let name = self.parse_dotted_name()?;
237        Ok(AstModuleDecl {
238            name,
239            span: Some(start),
240        })
241    }
242
243    fn parse_import(&mut self) -> Result<AstImport> {
244        let start = self.span();
245        self.expect(&TokenKind::Import)?;
246        let mut parts = vec![];
247        let (first, _) = self.expect_name()?;
248        parts.push(first);
249        while self.eat(&TokenKind::Dot) {
250            let (part, _) = self.expect_name()?;
251            parts.push(part);
252        }
253        // If the last part starts with uppercase, it's a specific item import
254        let name = if parts.len() >= 2
255            && parts
256                .last()
257                .expect("parts has at least 2 elements")
258                .chars()
259                .next()
260                .is_some_and(|c| c.is_uppercase())
261        {
262            let item = parts.pop().expect("parts has at least 2 elements");
263            Some(item)
264        } else {
265            None
266        };
267        let module = parts.join(".");
268        Ok(AstImport {
269            module,
270            name,
271            span: Some(start),
272        })
273    }
274
275    fn parse_dotted_name(&mut self) -> Result<String> {
276        let (first, _) = self.expect_name()?;
277        let mut name = first;
278        while self.eat(&TokenKind::Dot) {
279            let (part, _) = self.expect_name()?;
280            name.push('.');
281            name.push_str(&part);
282        }
283        Ok(name)
284    }
285
286    // ── Annotations ──
287
288    fn collect_annotations(&mut self) -> Result<Vec<AstAnnotation>> {
289        let mut anns = Vec::new();
290        while self.at(&TokenKind::At) {
291            anns.push(self.parse_annotation()?);
292        }
293        Ok(anns)
294    }
295
296    fn parse_annotation(&mut self) -> Result<AstAnnotation> {
297        let start = self.span();
298        self.expect(&TokenKind::At)?;
299        let (name, _) = self.expect_name()?;
300        let mut args = Vec::new();
301
302        if self.eat(&TokenKind::LParen) {
303            // @name(arg, arg, ...)
304            if !self.at(&TokenKind::RParen) {
305                args.push(self.parse_annotation_arg()?);
306                while self.eat(&TokenKind::Comma) {
307                    if self.at(&TokenKind::RParen) {
308                        break;
309                    }
310                    args.push(self.parse_annotation_arg()?);
311                }
312            }
313            self.expect(&TokenKind::RParen)?;
314        } else {
315            // @name value  (e.g. @endian big, @doc "text")
316            match self.peek().clone() {
317                TokenKind::Name(val) => {
318                    self.advance();
319                    args.push(AstAnnotationArg::Identifier(val));
320                }
321                TokenKind::StringLit(val) => {
322                    self.advance();
323                    args.push(AstAnnotationArg::String(val));
324                }
325                TokenKind::Integer(val) => {
326                    self.advance();
327                    args.push(AstAnnotationArg::Int(val));
328                }
329                TokenKind::True => {
330                    self.advance();
331                    args.push(AstAnnotationArg::Bool(true));
332                }
333                TokenKind::False => {
334                    self.advance();
335                    args.push(AstAnnotationArg::Bool(false));
336                }
337                // Some keywords can appear as annotation values (e.g. @endian big)
338                // big/little aren't keywords, they're names. So this is fine.
339                _ => {
340                    // No arg — bare annotation like @strict
341                }
342            }
343        }
344
345        Ok(AstAnnotation {
346            name,
347            args,
348            span: Some(start),
349        })
350    }
351
352    fn parse_annotation_arg(&mut self) -> Result<AstAnnotationArg> {
353        match self.peek().clone() {
354            TokenKind::Integer(v) => {
355                self.advance();
356                Ok(AstAnnotationArg::Int(v))
357            }
358            TokenKind::True => {
359                self.advance();
360                Ok(AstAnnotationArg::Bool(true))
361            }
362            TokenKind::False => {
363                self.advance();
364                Ok(AstAnnotationArg::Bool(false))
365            }
366            TokenKind::StringLit(v) => {
367                self.advance();
368                Ok(AstAnnotationArg::String(v))
369            }
370            TokenKind::Name(n) => {
371                // Lookahead for NAME "=" literal
372                if matches!(self.tokens[self.pos + 1].kind, TokenKind::Assign) {
373                    let name = n;
374                    self.advance(); // skip name
375                    self.advance(); // skip =
376                    let value = self.parse_literal_value()?;
377                    return Ok(AstAnnotationArg::NamedValue { name, value });
378                }
379                self.advance();
380                Ok(AstAnnotationArg::Identifier(n))
381            }
382            _ => Err(self.error(format!(
383                "expected annotation argument, found {:?}",
384                self.peek()
385            ))),
386        }
387    }
388
389    // ── Top Items ──
390
391    fn try_parse_top_item(
392        &mut self,
393        annotations: Vec<AstAnnotation>,
394    ) -> Result<Option<AstTopItem>> {
395        let exported = self.eat(&TokenKind::Export);
396        match self.peek() {
397            TokenKind::Const => Ok(Some(AstTopItem::Const(
398                self.parse_const(annotations, exported)?,
399            ))),
400            TokenKind::Enum => Ok(Some(AstTopItem::Enum(
401                self.parse_enum(annotations, exported)?,
402            ))),
403            TokenKind::Flags => Ok(Some(AstTopItem::Flags(
404                self.parse_flags(annotations, exported)?,
405            ))),
406            TokenKind::StaticAssert => {
407                if exported {
408                    return Err(self.error("'export' is not allowed on static_assert".into()));
409                }
410                if !annotations.is_empty() {
411                    return Err(self.error("annotations are not allowed on static_assert".into()));
412                }
413                Ok(Some(AstTopItem::StaticAssert(self.parse_static_assert()?)))
414            }
415            TokenKind::Type => {
416                let item = self.parse_type_def(annotations, exported)?;
417                Ok(Some(item))
418            }
419            TokenKind::Packet => Ok(Some(AstTopItem::Packet(
420                self.parse_packet(annotations, exported)?,
421            ))),
422            TokenKind::Frame => Ok(Some(AstTopItem::Frame(
423                self.parse_frame(annotations, exported)?,
424            ))),
425            TokenKind::Capsule => Ok(Some(AstTopItem::Capsule(
426                self.parse_capsule(annotations, exported)?,
427            ))),
428            TokenKind::State => Ok(Some(AstTopItem::StateMachine(
429                self.parse_state_machine(annotations, exported)?,
430            ))),
431            _ => {
432                // Check for "extern asn1"
433                if let TokenKind::Name(ref n) = self.peek().clone()
434                    && n == "extern"
435                {
436                    let item = self.parse_extern_asn1(annotations)?;
437                    return Ok(Some(item));
438                }
439
440                if exported {
441                    Err(self.error("expected definition after 'export'".into()))
442                } else if !annotations.is_empty() {
443                    Err(self.error("dangling annotations".into()))
444                } else {
445                    Ok(None)
446                }
447            }
448        }
449    }
450
451    // ── Const ──
452
453    fn parse_const(
454        &mut self,
455        annotations: Vec<AstAnnotation>,
456        exported: bool,
457    ) -> Result<AstConstDecl> {
458        let start = self.span();
459        self.expect(&TokenKind::Const)?;
460        let (name, _) = self.expect_name()?;
461        self.expect(&TokenKind::Colon)?;
462        let type_name = self.parse_type_ref_name()?;
463        self.expect(&TokenKind::Assign)?;
464        let value = self.parse_literal_value()?;
465        Ok(AstConstDecl {
466            name,
467            type_name,
468            value,
469            annotations,
470            exported,
471            span: Some(start),
472        })
473    }
474
475    // ── Enum / Flags ──
476
477    fn parse_enum(
478        &mut self,
479        annotations: Vec<AstAnnotation>,
480        exported: bool,
481    ) -> Result<AstEnumDecl> {
482        let start = self.span();
483        self.expect(&TokenKind::Enum)?;
484        let (name, _) = self.expect_name()?;
485        self.expect(&TokenKind::Colon)?;
486        let underlying_type = self.parse_type_ref_name()?;
487        self.expect(&TokenKind::LBrace)?;
488        let mut members = Vec::new();
489        while !self.at(&TokenKind::RBrace) {
490            let mstart = self.span();
491            let (mname, _) = self.expect_name()?;
492            self.expect(&TokenKind::Assign)?;
493            let mval = self.parse_integer()?;
494            members.push(AstEnumMember {
495                name: mname,
496                value: mval,
497                span: Some(mstart),
498            });
499            self.eat(&TokenKind::Comma);
500        }
501        self.expect(&TokenKind::RBrace)?;
502        Ok(AstEnumDecl {
503            name,
504            underlying_type,
505            members,
506            annotations,
507            exported,
508            span: Some(start),
509        })
510    }
511
512    fn parse_flags(
513        &mut self,
514        annotations: Vec<AstAnnotation>,
515        exported: bool,
516    ) -> Result<AstFlagsDecl> {
517        let start = self.span();
518        self.expect(&TokenKind::Flags)?;
519        let (name, _) = self.expect_name()?;
520        self.expect(&TokenKind::Colon)?;
521        let underlying_type = self.parse_type_ref_name()?;
522        self.expect(&TokenKind::LBrace)?;
523        let mut members = Vec::new();
524        while !self.at(&TokenKind::RBrace) {
525            let mstart = self.span();
526            let (mname, _) = self.expect_name()?;
527            self.expect(&TokenKind::Assign)?;
528            let mval = self.parse_integer()?;
529            members.push(AstEnumMember {
530                name: mname,
531                value: mval,
532                span: Some(mstart),
533            });
534            self.eat(&TokenKind::Comma);
535        }
536        self.expect(&TokenKind::RBrace)?;
537        Ok(AstFlagsDecl {
538            name,
539            underlying_type,
540            members,
541            annotations,
542            exported,
543            span: Some(start),
544        })
545    }
546
547    // ── StaticAssert ──
548
549    fn parse_static_assert(&mut self) -> Result<AstStaticAssertDecl> {
550        let start = self.span();
551        self.expect(&TokenKind::StaticAssert)?;
552        let expr = self.parse_expr()?;
553        Ok(AstStaticAssertDecl {
554            expr,
555            span: Some(start),
556        })
557    }
558
559    // ── Type ──
560
561    fn parse_type_def(
562        &mut self,
563        annotations: Vec<AstAnnotation>,
564        exported: bool,
565    ) -> Result<AstTopItem> {
566        let start = self.span();
567        self.expect(&TokenKind::Type)?;
568        let (name, _) = self.expect_name()?;
569        self.expect(&TokenKind::Assign)?;
570
571        // Check for varint block
572        if self.at(&TokenKind::Varint) {
573            return self.parse_continuation_varint(name, annotations, exported, start);
574        }
575
576        // Check for struct body (type Name = { fields })
577        if self.at(&TokenKind::LBrace) {
578            self.expect(&TokenKind::LBrace)?;
579            let fields = self.parse_struct_field_list()?;
580            self.expect(&TokenKind::RBrace)?;
581            return Ok(AstTopItem::Type(AstTypeDecl {
582                name,
583                annotations,
584                body: AstTypeDeclBody::Fields { fields },
585                exported,
586                span: Some(start),
587            }));
588        }
589
590        // Type alias
591        let target = self.parse_type_expr()?;
592        Ok(AstTopItem::Type(AstTypeDecl {
593            name,
594            annotations,
595            body: AstTypeDeclBody::Alias { target },
596            exported,
597            span: Some(start),
598        }))
599    }
600
601    fn parse_continuation_varint(
602        &mut self,
603        name: String,
604        annotations: Vec<AstAnnotation>,
605        exported: bool,
606        start: Span,
607    ) -> Result<AstTopItem> {
608        self.expect(&TokenKind::Varint)?;
609        self.expect(&TokenKind::LBrace)?;
610
611        let mut continuation_bit = "msb".to_string();
612        let mut value_bits: u8 = 7;
613        let mut max_bytes: u8 = 4;
614        let mut byte_order = "little".to_string();
615
616        while !self.at(&TokenKind::RBrace) {
617            let (pname, _) = self.expect_name()?;
618            self.expect(&TokenKind::Colon)?;
619            match pname.as_str() {
620                "continuation_bit" => {
621                    let (val, _) = self.expect_name()?;
622                    continuation_bit = val;
623                }
624                "value_bits" => {
625                    let raw = self.parse_integer()?;
626                    if raw < 0 || raw > u8::MAX as i64 {
627                        return Err(self.error(format!(
628                            "value_bits {raw} out of range (must be 0..{})",
629                            u8::MAX
630                        )));
631                    }
632                    value_bits = raw as u8;
633                }
634                "max_bytes" => {
635                    let raw = self.parse_integer()?;
636                    if raw < 0 || raw > u8::MAX as i64 {
637                        return Err(self.error(format!(
638                            "max_bytes {raw} out of range (must be 0..{})",
639                            u8::MAX
640                        )));
641                    }
642                    max_bytes = raw as u8;
643                }
644                "byte_order" => {
645                    let (val, _) = self.expect_name()?;
646                    byte_order = val;
647                }
648                _ => return Err(self.error(format!("unknown varint parameter: {pname}"))),
649            }
650            self.eat(&TokenKind::Comma);
651        }
652        self.expect(&TokenKind::RBrace)?;
653
654        Ok(AstTopItem::ContinuationVarInt(AstContinuationVarIntDecl {
655            name,
656            annotations,
657            continuation_bit,
658            value_bits,
659            max_bytes,
660            byte_order,
661            exported,
662            span: Some(start),
663        }))
664    }
665
666    // ── Packet ──
667
668    fn parse_packet(
669        &mut self,
670        annotations: Vec<AstAnnotation>,
671        exported: bool,
672    ) -> Result<AstPacketDecl> {
673        let start = self.span();
674        self.expect(&TokenKind::Packet)?;
675        let (name, _) = self.expect_name()?;
676        self.expect(&TokenKind::LBrace)?;
677        let fields = self.parse_field_list()?;
678        self.expect(&TokenKind::RBrace)?;
679        Ok(AstPacketDecl {
680            name,
681            fields,
682            annotations,
683            exported,
684            span: Some(start),
685        })
686    }
687
688    // ── Frame ──
689
690    fn parse_frame(
691        &mut self,
692        annotations: Vec<AstAnnotation>,
693        exported: bool,
694    ) -> Result<AstFrameDecl> {
695        let start = self.span();
696        self.expect(&TokenKind::Frame)?;
697        let (name, _) = self.expect_name()?;
698        self.expect(&TokenKind::Assign)?;
699        self.expect(&TokenKind::Match)?;
700        let (tag_field, _) = self.expect_name_or_keyword()?;
701        self.expect(&TokenKind::Colon)?;
702        let tag_type = self.parse_type_ref_name()?;
703        self.expect(&TokenKind::LBrace)?;
704        let branches = self.parse_frame_branches()?;
705        self.expect(&TokenKind::RBrace)?;
706        Ok(AstFrameDecl {
707            name,
708            tag_field,
709            tag_type,
710            branches,
711            annotations,
712            exported,
713            span: Some(start),
714        })
715    }
716
717    fn parse_frame_branches(&mut self) -> Result<Vec<AstFrameBranch>> {
718        let mut branches = Vec::new();
719        while !self.at(&TokenKind::RBrace) {
720            branches.push(self.parse_frame_branch()?);
721            self.eat(&TokenKind::Comma);
722        }
723        Ok(branches)
724    }
725
726    fn parse_frame_branch(&mut self) -> Result<AstFrameBranch> {
727        let start = self.span();
728        let pattern = self.parse_pattern()?;
729        self.expect(&TokenKind::FatArrow)?;
730        let (variant_name, _) = self.expect_name()?;
731        self.expect(&TokenKind::LBrace)?;
732        let fields = if self.at(&TokenKind::RBrace) {
733            Vec::new()
734        } else {
735            self.parse_field_list()?
736        };
737        self.expect(&TokenKind::RBrace)?;
738        Ok(AstFrameBranch {
739            pattern,
740            variant_name,
741            fields,
742            span: Some(start),
743        })
744    }
745
746    // ── Capsule ──
747
748    fn parse_capsule(
749        &mut self,
750        annotations: Vec<AstAnnotation>,
751        exported: bool,
752    ) -> Result<AstCapsuleDecl> {
753        let start = self.span();
754        self.expect(&TokenKind::Capsule)?;
755        let (name, _) = self.expect_name()?;
756        self.expect(&TokenKind::LBrace)?;
757
758        // Parse header fields until we hit "payload:"
759        let mut fields = Vec::new();
760        loop {
761            // Check for the payload field pattern: NAME ":" "match" ...
762            if let TokenKind::Name(fname) = self.peek().clone()
763                && fname == "payload"
764            {
765                // Peek ahead: payload : match
766                let saved = self.pos;
767                self.advance(); // skip "payload"
768                if self.at(&TokenKind::Colon) {
769                    self.advance(); // skip ":"
770                    if self.at(&TokenKind::Match) {
771                        // This is the payload match — parse it
772                        break;
773                    }
774                }
775                // Not a payload match, restore
776                self.pos = saved;
777            }
778            fields.push(self.parse_field_item()?);
779            self.eat(&TokenKind::Comma);
780        }
781
782        // Already consumed "payload" ":" and positioned at "match"
783        self.expect(&TokenKind::Match)?;
784
785        // capsule_tag = NAME | "(" expr ")"
786        let payload_tag = if self.eat(&TokenKind::LParen) {
787            let expr = self.parse_expr()?;
788            self.expect(&TokenKind::RParen)?;
789            AstPayloadTagSelector::Expr { expr }
790        } else {
791            let (tag_name, _) = self.expect_name_or_keyword()?;
792            AstPayloadTagSelector::Field {
793                field_name: tag_name,
794            }
795        };
796
797        self.expect(&TokenKind::Within)?;
798        let (payload_within, _) = self.expect_name_or_keyword()?;
799
800        self.expect(&TokenKind::LBrace)?;
801        let branches = self.parse_frame_branches()?;
802        self.expect(&TokenKind::RBrace)?;
803
804        // Close the capsule body
805        self.eat(&TokenKind::Comma);
806        self.expect(&TokenKind::RBrace)?;
807
808        Ok(AstCapsuleDecl {
809            name,
810            fields,
811            payload_tag,
812            payload_within,
813            branches,
814            annotations,
815            exported,
816            span: Some(start),
817        })
818    }
819
820    // ── State Machine ──
821
822    fn parse_state_machine(
823        &mut self,
824        annotations: Vec<AstAnnotation>,
825        exported: bool,
826    ) -> Result<AstStateMachineDecl> {
827        let start = self.span();
828        self.expect(&TokenKind::State)?;
829        self.expect(&TokenKind::Machine)?;
830        let (name, _) = self.expect_name()?;
831        self.expect(&TokenKind::LBrace)?;
832
833        let mut states = Vec::new();
834        let mut initial_state = String::new();
835        let mut transitions = Vec::new();
836        let mut verify_declarations = Vec::new();
837
838        while !self.at(&TokenKind::RBrace) {
839            match self.peek() {
840                TokenKind::State => {
841                    states.push(self.parse_state_decl()?);
842                }
843                TokenKind::Initial => {
844                    self.advance();
845                    let (iname, _) = self.expect_name()?;
846                    initial_state = iname;
847                }
848                TokenKind::Transition => {
849                    transitions.push(self.parse_transition()?);
850                }
851                TokenKind::Name(n) if n == "verify" => {
852                    verify_declarations.push(self.parse_verify_decl()?);
853                }
854                _ => {
855                    return Err(
856                        self.error(format!("unexpected in state machine: {:?}", self.peek()))
857                    );
858                }
859            }
860        }
861        self.expect(&TokenKind::RBrace)?;
862
863        Ok(AstStateMachineDecl {
864            name,
865            states,
866            initial_state,
867            transitions,
868            verify_declarations,
869            annotations,
870            exported,
871            span: Some(start),
872        })
873    }
874
875    fn parse_state_decl(&mut self) -> Result<AstStateDecl> {
876        let start = self.span();
877        self.expect(&TokenKind::State)?;
878        let (name, _) = self.expect_name()?;
879
880        let mut fields = Vec::new();
881        let mut is_terminal = false;
882
883        // Optional fields block
884        if self.eat(&TokenKind::LBrace) {
885            while !self.at(&TokenKind::RBrace) {
886                let fstart = self.span();
887                let (fname, _) = self.expect_name()?;
888                self.expect(&TokenKind::Colon)?;
889                let type_expr = self.parse_type_expr()?;
890                let default_value = if self.eat(&TokenKind::Assign) {
891                    Some(self.parse_literal_value()?)
892                } else {
893                    None
894                };
895                fields.push(AstStateFieldDef {
896                    name: fname,
897                    type_expr,
898                    default_value,
899                    span: Some(fstart),
900                });
901                self.eat(&TokenKind::Comma);
902            }
903            self.expect(&TokenKind::RBrace)?;
904        }
905
906        // [terminal]
907        if self.eat(&TokenKind::LBracket) {
908            self.expect(&TokenKind::Terminal)?;
909            self.expect(&TokenKind::RBracket)?;
910            is_terminal = true;
911        }
912
913        Ok(AstStateDecl {
914            name,
915            fields,
916            is_terminal,
917            span: Some(start),
918        })
919    }
920
921    fn parse_transition(&mut self) -> Result<AstTransitionDecl> {
922        let start = self.span();
923        self.expect(&TokenKind::Transition)?;
924
925        // src state: NAME | "*"
926        let src_state = if self.eat(&TokenKind::Star) {
927            "*".to_string()
928        } else {
929            let (s, _) = self.expect_name()?;
930            s
931        };
932
933        self.expect(&TokenKind::Arrow)?;
934        let (dst_state, _) = self.expect_name()?;
935
936        self.expect(&TokenKind::LBrace)?;
937
938        let mut events = Vec::new();
939        let mut guard = None;
940        let mut actions = Vec::new();
941        let mut delegate = None;
942        let mut has_guard = false;
943        let mut has_action = false;
944        let mut has_delegate = false;
945
946        while !self.at(&TokenKind::RBrace) {
947            match self.peek() {
948                TokenKind::On => {
949                    events.push(self.parse_event_decl()?);
950                }
951                TokenKind::Guard => {
952                    if has_guard {
953                        return Err(self.error("duplicate 'guard' clause in transition".into()));
954                    }
955                    has_guard = true;
956                    self.advance();
957                    guard = Some(self.parse_expr()?);
958                }
959                TokenKind::Action => {
960                    if has_action {
961                        return Err(self.error("duplicate 'action' clause in transition".into()));
962                    }
963                    has_action = true;
964                    self.advance();
965                    self.expect(&TokenKind::LBrace)?;
966                    while !self.at(&TokenKind::RBrace) {
967                        actions.push(self.parse_assignment()?);
968                        self.eat(&TokenKind::Semicolon);
969                    }
970                    self.expect(&TokenKind::RBrace)?;
971                }
972                TokenKind::Delegate => {
973                    if has_delegate {
974                        return Err(self.error("duplicate 'delegate' clause in transition".into()));
975                    }
976                    has_delegate = true;
977                    delegate = Some(self.parse_delegate_clause()?);
978                }
979                _ => {
980                    return Err(self.error(format!("unexpected in transition: {:?}", self.peek())));
981                }
982            }
983        }
984        self.expect(&TokenKind::RBrace)?;
985
986        Ok(AstTransitionDecl {
987            src_state,
988            dst_state,
989            events,
990            guard,
991            actions,
992            delegate,
993            span: Some(start),
994        })
995    }
996
997    fn parse_event_decl(&mut self) -> Result<AstEventDecl> {
998        let start = self.span();
999        self.expect(&TokenKind::On)?;
1000        let (name, _) = self.expect_name_or_keyword()?;
1001        let mut params = Vec::new();
1002        if self.eat(&TokenKind::LParen) {
1003            if !self.at(&TokenKind::RParen) {
1004                loop {
1005                    let pstart = self.span();
1006                    let (pname, _) = self.expect_name()?;
1007                    self.expect(&TokenKind::Colon)?;
1008                    let type_expr = self.parse_type_expr()?;
1009                    params.push(AstEventParam {
1010                        name: pname,
1011                        type_expr,
1012                        span: Some(pstart),
1013                    });
1014                    if !self.eat(&TokenKind::Comma) {
1015                        break;
1016                    }
1017                }
1018            }
1019            self.expect(&TokenKind::RParen)?;
1020        }
1021        Ok(AstEventDecl {
1022            name,
1023            params,
1024            span: Some(start),
1025        })
1026    }
1027
1028    fn parse_assignment(&mut self) -> Result<AstAssignment> {
1029        let start = self.span();
1030        let target = self.parse_postfix_expr()?;
1031        let op = if self.eat(&TokenKind::PlusAssign) {
1032            "+=".to_string()
1033        } else {
1034            self.expect(&TokenKind::Assign)?;
1035            "=".to_string()
1036        };
1037        let value = self.parse_expr()?;
1038        Ok(AstAssignment {
1039            target,
1040            op,
1041            value,
1042            span: Some(start),
1043        })
1044    }
1045
1046    fn parse_delegate_clause(&mut self) -> Result<AstDelegateClause> {
1047        let start = self.span();
1048        self.expect(&TokenKind::Delegate)?;
1049        let target = self.parse_postfix_expr()?;
1050        self.expect(&TokenKind::LArrow)?;
1051        let (event_name, _) = self.expect_name()?;
1052        Ok(AstDelegateClause {
1053            target,
1054            event_name,
1055            span: Some(start),
1056        })
1057    }
1058
1059    fn parse_verify_decl(&mut self) -> Result<AstVerifyDecl> {
1060        let start = self.span();
1061        self.advance(); // skip "verify"
1062
1063        // Check if it's `verify property Name: formula`
1064        if let TokenKind::Name(ref n) = self.peek().clone()
1065            && n == "property"
1066        {
1067            self.advance(); // skip "property"
1068            let (prop_name, _) = self.expect_name()?;
1069            self.expect(&TokenKind::Colon)?;
1070            let formula = self.parse_verify_formula()?;
1071            return Ok(AstVerifyDecl::Property {
1072                name: prop_name,
1073                formula,
1074                span: Some(start),
1075            });
1076        }
1077
1078        // Otherwise it's a built-in: `verify Name`
1079        let (builtin_name, _) = self.expect_name()?;
1080        Ok(AstVerifyDecl::BuiltIn {
1081            name: builtin_name,
1082            span: Some(start),
1083        })
1084    }
1085
1086    /// Parse a verify formula expression. Uses recursive descent with explicit
1087    /// precedence levels:
1088    ///   formula     → implies_expr
1089    ///   implies_expr → or_expr ( ( '->' | '~>' ) or_expr )*
1090    ///   or_expr     → and_expr ( 'or' and_expr )*
1091    ///   and_expr    → compare_expr ( 'and' compare_expr )*
1092    ///   compare_expr → unary_expr ( ( '<' | '<=' | '>' | '>=' | '==' | '!=' ) unary_expr )?
1093    ///   unary_expr  → '[]' unary_expr | '<>' unary_expr | 'not' unary_expr | primary
1094    ///   primary     → 'in_state' '(' Name ')' | 'true' | 'false' | Integer | Name ( '.' Name )* | '(' formula ')'
1095    fn parse_verify_formula(&mut self) -> Result<AstVerifyFormula> {
1096        self.parse_verify_implies()
1097    }
1098
1099    fn parse_verify_implies(&mut self) -> Result<AstVerifyFormula> {
1100        let mut left = self.parse_verify_or()?;
1101        loop {
1102            if self.at(&TokenKind::Arrow) {
1103                self.advance();
1104                let right = self.parse_verify_or()?;
1105                left = AstVerifyFormula::Implies {
1106                    left: Box::new(left),
1107                    right: Box::new(right),
1108                };
1109            } else if self.at(&TokenKind::TildeGt) {
1110                self.advance();
1111                let right = self.parse_verify_or()?;
1112                left = AstVerifyFormula::LeadsTo {
1113                    left: Box::new(left),
1114                    right: Box::new(right),
1115                };
1116            } else {
1117                break;
1118            }
1119        }
1120        Ok(left)
1121    }
1122
1123    fn parse_verify_or(&mut self) -> Result<AstVerifyFormula> {
1124        let mut left = self.parse_verify_and()?;
1125        while self.at(&TokenKind::Or) {
1126            self.advance();
1127            let right = self.parse_verify_and()?;
1128            left = AstVerifyFormula::Or {
1129                left: Box::new(left),
1130                right: Box::new(right),
1131            };
1132        }
1133        Ok(left)
1134    }
1135
1136    fn parse_verify_and(&mut self) -> Result<AstVerifyFormula> {
1137        let mut left = self.parse_verify_compare()?;
1138        while self.at(&TokenKind::And) {
1139            self.advance();
1140            let right = self.parse_verify_compare()?;
1141            left = AstVerifyFormula::And {
1142                left: Box::new(left),
1143                right: Box::new(right),
1144            };
1145        }
1146        Ok(left)
1147    }
1148
1149    fn parse_verify_compare(&mut self) -> Result<AstVerifyFormula> {
1150        let left = self.parse_verify_unary()?;
1151        let op = match self.peek() {
1152            TokenKind::Lt => Some("<"),
1153            TokenKind::Le => Some("<="),
1154            TokenKind::Gt => Some(">"),
1155            TokenKind::Ge => Some(">="),
1156            TokenKind::EqEq => Some("=="),
1157            TokenKind::BangEq => Some("!="),
1158            _ => None,
1159        };
1160        if let Some(op_str) = op {
1161            let op_string = op_str.to_string();
1162            self.advance();
1163            let right = self.parse_verify_unary()?;
1164            Ok(AstVerifyFormula::Compare {
1165                left: Box::new(left),
1166                op: op_string,
1167                right: Box::new(right),
1168            })
1169        } else {
1170            Ok(left)
1171        }
1172    }
1173
1174    fn parse_verify_unary(&mut self) -> Result<AstVerifyFormula> {
1175        // [] formula (Always)
1176        if self.at(&TokenKind::LBracket) {
1177            // Look ahead: [] means LBracket followed immediately by RBracket
1178            let saved = self.pos;
1179            self.advance(); // skip '['
1180            if self.at(&TokenKind::RBracket) {
1181                self.advance(); // skip ']'
1182                let inner = self.parse_verify_unary()?;
1183                return Ok(AstVerifyFormula::Always {
1184                    inner: Box::new(inner),
1185                });
1186            }
1187            // Not [], restore position
1188            self.pos = saved;
1189        }
1190
1191        // <> formula (Eventually) — Lt followed by Gt
1192        if self.at(&TokenKind::Lt) {
1193            let saved = self.pos;
1194            self.advance(); // skip '<'
1195            if self.at(&TokenKind::Gt) {
1196                self.advance(); // skip '>'
1197                let inner = self.parse_verify_unary()?;
1198                return Ok(AstVerifyFormula::Eventually {
1199                    inner: Box::new(inner),
1200                });
1201            }
1202            // Not <>, restore position
1203            self.pos = saved;
1204        }
1205
1206        // not formula
1207        if self.at(&TokenKind::Not) {
1208            self.advance();
1209            let inner = self.parse_verify_unary()?;
1210            return Ok(AstVerifyFormula::Not {
1211                inner: Box::new(inner),
1212            });
1213        }
1214
1215        self.parse_verify_primary()
1216    }
1217
1218    fn parse_verify_primary(&mut self) -> Result<AstVerifyFormula> {
1219        // in_state(Name)
1220        if self.at(&TokenKind::InState) {
1221            self.advance();
1222            self.expect(&TokenKind::LParen)?;
1223            let (state_name, _) = self.expect_name()?;
1224            self.expect(&TokenKind::RParen)?;
1225            return Ok(AstVerifyFormula::InState { state_name });
1226        }
1227
1228        // true / false
1229        if self.at(&TokenKind::True) {
1230            self.advance();
1231            return Ok(AstVerifyFormula::Literal {
1232                value: AstLiteralValue::Bool(true),
1233            });
1234        }
1235        if self.at(&TokenKind::False) {
1236            self.advance();
1237            return Ok(AstVerifyFormula::Literal {
1238                value: AstLiteralValue::Bool(false),
1239            });
1240        }
1241
1242        // Integer literal
1243        if let TokenKind::Integer(n) = self.peek().clone() {
1244            self.advance();
1245            return Ok(AstVerifyFormula::Literal {
1246                value: AstLiteralValue::Int(n),
1247            });
1248        }
1249
1250        // Parenthesized formula
1251        if self.at(&TokenKind::LParen) {
1252            self.advance();
1253            let inner = self.parse_verify_formula()?;
1254            self.expect(&TokenKind::RParen)?;
1255            return Ok(inner);
1256        }
1257
1258        // Name — possibly dotted path like src.field
1259        if let Some(name) = self.token_as_name() {
1260            self.advance();
1261            let mut path = vec![name];
1262            while self.eat(&TokenKind::Dot) {
1263                let (next, _) = self.expect_name()?;
1264                path.push(next);
1265            }
1266            return Ok(AstVerifyFormula::FieldRef { path });
1267        }
1268
1269        Err(self.error(format!("expected verify formula, found {:?}", self.peek())))
1270    }
1271
1272    // ── Fields ──
1273
1274    fn parse_field_list(&mut self) -> Result<Vec<AstFieldItem>> {
1275        let mut items = Vec::new();
1276        while !self.at(&TokenKind::RBrace) {
1277            items.push(self.parse_field_item()?);
1278            self.eat(&TokenKind::Comma);
1279        }
1280        Ok(items)
1281    }
1282
1283    fn parse_struct_field_list(&mut self) -> Result<Vec<AstFieldDef>> {
1284        let mut fields = Vec::new();
1285        while !self.at(&TokenKind::RBrace) {
1286            let anns = self.collect_annotations()?;
1287            let start = self.span();
1288            let (name, _) = self.expect_name()?;
1289            self.expect(&TokenKind::Colon)?;
1290            let type_expr = self.parse_type_expr()?;
1291            fields.push(AstFieldDef {
1292                name,
1293                type_expr,
1294                annotations: anns,
1295                span: Some(start),
1296            });
1297            self.eat(&TokenKind::Comma);
1298        }
1299        Ok(fields)
1300    }
1301
1302    fn parse_field_item(&mut self) -> Result<AstFieldItem> {
1303        match self.peek() {
1304            TokenKind::Let => {
1305                let start = self.span();
1306                self.advance();
1307                let (name, _) = self.expect_name()?;
1308                self.expect(&TokenKind::Colon)?;
1309                let type_name = self.parse_type_ref_name()?;
1310                self.expect(&TokenKind::Assign)?;
1311                let expr = self.parse_expr()?;
1312                Ok(AstFieldItem::Derived(AstDerivedField {
1313                    name,
1314                    type_name,
1315                    expr,
1316                    span: Some(start),
1317                }))
1318            }
1319            TokenKind::Require => {
1320                let start = self.span();
1321                self.advance();
1322                let expr = self.parse_expr()?;
1323                Ok(AstFieldItem::Require(AstRequireClause {
1324                    expr,
1325                    span: Some(start),
1326                }))
1327            }
1328            _ => {
1329                let anns = self.collect_annotations()?;
1330                let start = self.span();
1331                let (name, _) = self.expect_name_or_keyword()?;
1332                self.expect(&TokenKind::Colon)?;
1333                let type_expr = self.parse_type_expr()?;
1334                Ok(AstFieldItem::Field(AstFieldDef {
1335                    name,
1336                    type_expr,
1337                    annotations: anns,
1338                    span: Some(start),
1339                }))
1340            }
1341        }
1342    }
1343
1344    // ── Type Expressions ──
1345
1346    fn parse_type_expr(&mut self) -> Result<AstTypeExpr> {
1347        match self.peek() {
1348            TokenKind::Match => self.parse_match_type_expr(),
1349            TokenKind::If => self.parse_optional_type_expr(),
1350            TokenKind::LBracket => self.parse_array_type_expr(),
1351            TokenKind::Bytes => self.parse_bytes_type_expr(),
1352            TokenKind::Bits => self.parse_bits_type_expr(),
1353            TokenKind::Bit => {
1354                let span = self.span();
1355                self.advance();
1356                Ok(AstTypeExpr::Bits {
1357                    width: 1,
1358                    span: Some(span),
1359                })
1360            }
1361            _ => {
1362                let span = self.span();
1363                let name = self.parse_type_ref_name()?;
1364                // Check for asn1(...) function-call syntax
1365                if name == "asn1" && self.at(&TokenKind::LParen) {
1366                    return self.parse_asn1_type_expr(span);
1367                }
1368                Ok(AstTypeExpr::Named {
1369                    name,
1370                    span: Some(span),
1371                })
1372            }
1373        }
1374    }
1375
1376    fn parse_asn1_type_expr(&mut self, start: Span) -> Result<AstTypeExpr> {
1377        self.expect(&TokenKind::LParen)?;
1378
1379        // Type name
1380        let (type_name, _) = self.expect_name()?;
1381        self.expect(&TokenKind::Comma)?;
1382
1383        // encoding: <name>
1384        let (enc_kw, _) = self.expect_name()?;
1385        if enc_kw != "encoding" {
1386            return Err(self.error(format!("expected 'encoding', found '{enc_kw}'")));
1387        }
1388        self.expect(&TokenKind::Colon)?;
1389        let (encoding, _) = self.expect_name()?;
1390        self.expect(&TokenKind::Comma)?;
1391
1392        // length: <expr> OR remaining
1393        let length = if self.eat(&TokenKind::Remaining) {
1394            Asn1Length::Remaining
1395        } else {
1396            let (len_kw, _) = self.expect_name()?;
1397            if len_kw != "length" {
1398                return Err(self.error(format!(
1399                    "expected 'length' or 'remaining', found '{len_kw}'"
1400                )));
1401            }
1402            self.expect(&TokenKind::Colon)?;
1403            let expr = self.parse_expr()?;
1404            Asn1Length::Expr(Box::new(expr))
1405        };
1406
1407        self.expect(&TokenKind::RParen)?;
1408
1409        Ok(AstTypeExpr::Asn1 {
1410            type_name,
1411            encoding,
1412            length,
1413            span: Some(start),
1414        })
1415    }
1416
1417    fn parse_match_type_expr(&mut self) -> Result<AstTypeExpr> {
1418        let start = self.span();
1419        self.expect(&TokenKind::Match)?;
1420        let (field_name, _) = self.expect_name()?;
1421        self.expect(&TokenKind::LBrace)?;
1422        let mut branches = Vec::new();
1423        while !self.at(&TokenKind::RBrace) {
1424            let bstart = self.span();
1425            let pattern = self.parse_pattern()?;
1426            self.expect(&TokenKind::FatArrow)?;
1427            let result_type = self.parse_type_expr()?;
1428            branches.push(AstMatchBranch {
1429                pattern,
1430                result_type,
1431                span: Some(bstart),
1432            });
1433            self.eat(&TokenKind::Comma);
1434        }
1435        self.expect(&TokenKind::RBrace)?;
1436        Ok(AstTypeExpr::Match {
1437            field_name,
1438            branches,
1439            span: Some(start),
1440        })
1441    }
1442
1443    fn parse_optional_type_expr(&mut self) -> Result<AstTypeExpr> {
1444        let start = self.span();
1445        self.expect(&TokenKind::If)?;
1446        let condition = self.parse_expr()?;
1447        self.expect(&TokenKind::LBrace)?;
1448        let inner_type = self.parse_type_expr()?;
1449        self.expect(&TokenKind::RBrace)?;
1450        Ok(AstTypeExpr::Optional {
1451            condition,
1452            inner_type: Box::new(inner_type),
1453            span: Some(start),
1454        })
1455    }
1456
1457    fn parse_array_type_expr(&mut self) -> Result<AstTypeExpr> {
1458        let start = self.span();
1459        self.expect(&TokenKind::LBracket)?;
1460        let element_type = self.parse_type_expr()?;
1461        self.expect(&TokenKind::Semicolon)?;
1462
1463        let count = if self.eat(&TokenKind::Fill) {
1464            AstArrayCount::Fill
1465        } else {
1466            AstArrayCount::Expr(self.parse_expr()?)
1467        };
1468
1469        // Optional: "] within EXPR" for fill-within arrays (M15)
1470        self.expect(&TokenKind::RBracket)?;
1471
1472        let within_expr = if self.at(&TokenKind::Within) {
1473            // Only valid with fill arrays: [T; fill] within expr
1474            self.advance();
1475            Some(Box::new(self.parse_expr()?))
1476        } else {
1477            None
1478        };
1479
1480        Ok(AstTypeExpr::Array {
1481            element_type: Box::new(element_type),
1482            count,
1483            within_expr,
1484            span: Some(start),
1485        })
1486    }
1487
1488    fn parse_bytes_type_expr(&mut self) -> Result<AstTypeExpr> {
1489        let start = self.span();
1490        self.expect(&TokenKind::Bytes)?;
1491        self.expect(&TokenKind::LBracket)?;
1492
1493        // bytes[remaining]
1494        if self.eat(&TokenKind::Remaining) {
1495            self.expect(&TokenKind::RBracket)?;
1496            return Ok(AstTypeExpr::Bytes {
1497                kind: AstBytesKind::Remaining,
1498                fixed_size: None,
1499                size_expr: None,
1500                span: Some(start),
1501            });
1502        }
1503
1504        // Check for "length:" or "length_or_remaining:" with lookahead
1505        if let TokenKind::Name(n) = self.peek().clone()
1506            && (n == "length" || n == "length_or_remaining")
1507            && matches!(self.tokens[self.pos + 1].kind, TokenKind::Colon)
1508        {
1509            self.advance(); // skip "length" / "length_or_remaining"
1510            self.advance(); // skip ":"
1511            let expr = self.parse_expr()?;
1512            let kind = if n == "length" {
1513                AstBytesKind::Length
1514            } else {
1515                AstBytesKind::LengthOrRemaining
1516            };
1517            self.expect(&TokenKind::RBracket)?;
1518            return Ok(AstTypeExpr::Bytes {
1519                kind,
1520                fixed_size: None,
1521                size_expr: Some(Box::new(expr)),
1522                span: Some(start),
1523            });
1524        }
1525
1526        // bytes[N] — fixed size integer
1527        if let TokenKind::Integer(n) = *self.peek() {
1528            // Only treat as fixed if the next token after the integer is ']'
1529            if matches!(self.tokens[self.pos + 1].kind, TokenKind::RBracket) {
1530                self.advance();
1531                self.expect(&TokenKind::RBracket)?;
1532                return Ok(AstTypeExpr::Bytes {
1533                    kind: AstBytesKind::Fixed,
1534                    fixed_size: Some(n as u64),
1535                    size_expr: None,
1536                    span: Some(start),
1537                });
1538            }
1539        }
1540
1541        // bytes[EXPR] — expression for length (shorthand for bytes[length: EXPR])
1542        let expr = self.parse_expr()?;
1543        self.expect(&TokenKind::RBracket)?;
1544        Ok(AstTypeExpr::Bytes {
1545            kind: AstBytesKind::Length,
1546            fixed_size: None,
1547            size_expr: Some(Box::new(expr)),
1548            span: Some(start),
1549        })
1550    }
1551
1552    fn parse_bits_type_expr(&mut self) -> Result<AstTypeExpr> {
1553        let start = self.span();
1554        self.expect(&TokenKind::Bits)?;
1555        self.expect(&TokenKind::LBracket)?;
1556        let raw = self.parse_integer()?;
1557        if raw < 1 || raw > u16::MAX as i64 {
1558            return Err(self.error(format!(
1559                "bits width {raw} out of range (must be 1..{})",
1560                u16::MAX
1561            )));
1562        }
1563        let width = raw as u16;
1564        self.expect(&TokenKind::RBracket)?;
1565        Ok(AstTypeExpr::Bits {
1566            width,
1567            span: Some(start),
1568        })
1569    }
1570
1571    // ── Patterns ──
1572
1573    fn parse_pattern(&mut self) -> Result<AstPattern> {
1574        let start = self.span();
1575        // Check for wildcard "_"
1576        if let TokenKind::Name(n) = self.peek().clone()
1577            && n == "_"
1578        {
1579            self.advance();
1580            return Ok(AstPattern::Wildcard { span: Some(start) });
1581        }
1582
1583        let value = self.parse_integer()?;
1584
1585        if self.eat(&TokenKind::DotDotEq) {
1586            let end = self.parse_integer()?;
1587            Ok(AstPattern::RangeInclusive {
1588                start: value,
1589                end,
1590                span: Some(start),
1591            })
1592        } else {
1593            Ok(AstPattern::Value {
1594                value,
1595                span: Some(start),
1596            })
1597        }
1598    }
1599
1600    // ── Expressions (precedence climbing) ──
1601    // Precedence (low to high):
1602    //   coalesce (??)
1603    //   or
1604    //   and
1605    //   comparison (==, !=, <, <=, >, >=)
1606    //   bitor (|)
1607    //   bitxor (^)
1608    //   bitand (&)
1609    //   shift (<<, >>)
1610    //   add (+, -)
1611    //   mul (*, /, %)
1612    //   unary (!, -)
1613    //   postfix (., [], [..])
1614
1615    fn parse_expr(&mut self) -> Result<AstExpr> {
1616        self.parse_coalesce_expr()
1617    }
1618
1619    fn parse_coalesce_expr(&mut self) -> Result<AstExpr> {
1620        let start = self.span();
1621        let mut expr = self.parse_or_expr()?;
1622        if self.eat(&TokenKind::QuestionQuestion) {
1623            let default = self.parse_or_expr()?;
1624            expr = AstExpr::Coalesce {
1625                expr: Box::new(expr),
1626                default: Box::new(default),
1627                span: Some(start),
1628            };
1629        }
1630        Ok(expr)
1631    }
1632
1633    fn parse_or_expr(&mut self) -> Result<AstExpr> {
1634        let start = self.span();
1635        let mut left = self.parse_and_expr()?;
1636        while self.eat(&TokenKind::Or) {
1637            let right = self.parse_and_expr()?;
1638            left = AstExpr::Binary {
1639                op: BinOp::Or,
1640                left: Box::new(left),
1641                right: Box::new(right),
1642                span: Some(start),
1643            };
1644        }
1645        Ok(left)
1646    }
1647
1648    fn parse_and_expr(&mut self) -> Result<AstExpr> {
1649        let start = self.span();
1650        let mut left = self.parse_compare_expr()?;
1651        while self.eat(&TokenKind::And) {
1652            let right = self.parse_compare_expr()?;
1653            left = AstExpr::Binary {
1654                op: BinOp::And,
1655                left: Box::new(left),
1656                right: Box::new(right),
1657                span: Some(start),
1658            };
1659        }
1660        Ok(left)
1661    }
1662
1663    fn parse_compare_expr(&mut self) -> Result<AstExpr> {
1664        let start = self.span();
1665        let left = self.parse_bitor_expr()?;
1666        let op = match self.peek() {
1667            TokenKind::EqEq => Some(BinOp::Eq),
1668            TokenKind::BangEq => Some(BinOp::Ne),
1669            TokenKind::Lt => Some(BinOp::Lt),
1670            TokenKind::Le => Some(BinOp::Le),
1671            TokenKind::Gt => Some(BinOp::Gt),
1672            TokenKind::Ge => Some(BinOp::Ge),
1673            _ => None,
1674        };
1675        if let Some(op) = op {
1676            self.advance();
1677            let right = self.parse_bitor_expr()?;
1678            Ok(AstExpr::Binary {
1679                op,
1680                left: Box::new(left),
1681                right: Box::new(right),
1682                span: Some(start),
1683            })
1684        } else {
1685            Ok(left)
1686        }
1687    }
1688
1689    fn parse_bitor_expr(&mut self) -> Result<AstExpr> {
1690        let start = self.span();
1691        let mut left = self.parse_bitxor_expr()?;
1692        while self.eat(&TokenKind::Pipe) {
1693            let right = self.parse_bitxor_expr()?;
1694            left = AstExpr::Binary {
1695                op: BinOp::BitOr,
1696                left: Box::new(left),
1697                right: Box::new(right),
1698                span: Some(start),
1699            };
1700        }
1701        Ok(left)
1702    }
1703
1704    fn parse_bitxor_expr(&mut self) -> Result<AstExpr> {
1705        let start = self.span();
1706        let mut left = self.parse_bitand_expr()?;
1707        while self.eat(&TokenKind::Caret) {
1708            let right = self.parse_bitand_expr()?;
1709            left = AstExpr::Binary {
1710                op: BinOp::BitXor,
1711                left: Box::new(left),
1712                right: Box::new(right),
1713                span: Some(start),
1714            };
1715        }
1716        Ok(left)
1717    }
1718
1719    fn parse_bitand_expr(&mut self) -> Result<AstExpr> {
1720        let start = self.span();
1721        let mut left = self.parse_shift_expr()?;
1722        while self.eat(&TokenKind::Amp) {
1723            let right = self.parse_shift_expr()?;
1724            left = AstExpr::Binary {
1725                op: BinOp::BitAnd,
1726                left: Box::new(left),
1727                right: Box::new(right),
1728                span: Some(start),
1729            };
1730        }
1731        Ok(left)
1732    }
1733
1734    fn parse_shift_expr(&mut self) -> Result<AstExpr> {
1735        let start = self.span();
1736        let mut left = self.parse_add_expr()?;
1737        loop {
1738            let op = match self.peek() {
1739                TokenKind::Shl => Some(BinOp::Shl),
1740                TokenKind::Shr => Some(BinOp::Shr),
1741                _ => None,
1742            };
1743            if let Some(op) = op {
1744                self.advance();
1745                let right = self.parse_add_expr()?;
1746                left = AstExpr::Binary {
1747                    op,
1748                    left: Box::new(left),
1749                    right: Box::new(right),
1750                    span: Some(start),
1751                };
1752            } else {
1753                break;
1754            }
1755        }
1756        Ok(left)
1757    }
1758
1759    fn parse_add_expr(&mut self) -> Result<AstExpr> {
1760        let start = self.span();
1761        let mut left = self.parse_mul_expr()?;
1762        loop {
1763            let op = match self.peek() {
1764                TokenKind::Plus => Some(BinOp::Add),
1765                TokenKind::Minus => Some(BinOp::Sub),
1766                _ => None,
1767            };
1768            if let Some(op) = op {
1769                self.advance();
1770                let right = self.parse_mul_expr()?;
1771                left = AstExpr::Binary {
1772                    op,
1773                    left: Box::new(left),
1774                    right: Box::new(right),
1775                    span: Some(start),
1776                };
1777            } else {
1778                break;
1779            }
1780        }
1781        Ok(left)
1782    }
1783
1784    fn parse_mul_expr(&mut self) -> Result<AstExpr> {
1785        let start = self.span();
1786        let mut left = self.parse_unary_expr()?;
1787        loop {
1788            let op = match self.peek() {
1789                TokenKind::Star => Some(BinOp::Mul),
1790                TokenKind::Slash => Some(BinOp::Div),
1791                TokenKind::Percent => Some(BinOp::Mod),
1792                _ => None,
1793            };
1794            if let Some(op) = op {
1795                self.advance();
1796                let right = self.parse_unary_expr()?;
1797                left = AstExpr::Binary {
1798                    op,
1799                    left: Box::new(left),
1800                    right: Box::new(right),
1801                    span: Some(start),
1802                };
1803            } else {
1804                break;
1805            }
1806        }
1807        Ok(left)
1808    }
1809
1810    fn parse_unary_expr(&mut self) -> Result<AstExpr> {
1811        let start = self.span();
1812        match self.peek() {
1813            TokenKind::Bang => {
1814                self.advance();
1815                let operand = self.parse_unary_expr()?;
1816                Ok(AstExpr::Unary {
1817                    op: UnaryOp::Not,
1818                    operand: Box::new(operand),
1819                    span: Some(start),
1820                })
1821            }
1822            TokenKind::Minus => {
1823                self.advance();
1824                let operand = self.parse_unary_expr()?;
1825                Ok(AstExpr::Unary {
1826                    op: UnaryOp::Neg,
1827                    operand: Box::new(operand),
1828                    span: Some(start),
1829                })
1830            }
1831            TokenKind::Not => {
1832                self.advance();
1833                let operand = self.parse_unary_expr()?;
1834                Ok(AstExpr::Unary {
1835                    op: UnaryOp::Not,
1836                    operand: Box::new(operand),
1837                    span: Some(start),
1838                })
1839            }
1840            _ => self.parse_postfix_expr(),
1841        }
1842    }
1843
1844    fn parse_postfix_expr(&mut self) -> Result<AstExpr> {
1845        let start = self.span();
1846        let mut expr = self.parse_primary_expr()?;
1847
1848        loop {
1849            match self.peek() {
1850                TokenKind::Dot => {
1851                    self.advance();
1852                    let (field, _) = self.expect_name_or_keyword()?;
1853                    expr = AstExpr::MemberAccess {
1854                        base: Box::new(expr),
1855                        field,
1856                        span: Some(start),
1857                    };
1858                }
1859                TokenKind::LBracket => {
1860                    self.advance();
1861                    let index = self.parse_expr()?;
1862                    // Check for slice: expr[start..end]
1863                    if self.eat(&TokenKind::DotDot) {
1864                        let end = self.parse_expr()?;
1865                        self.expect(&TokenKind::RBracket)?;
1866                        expr = AstExpr::Slice {
1867                            base: Box::new(expr),
1868                            start: Box::new(index),
1869                            end: Box::new(end),
1870                            span: Some(start),
1871                        };
1872                    } else {
1873                        self.expect(&TokenKind::RBracket)?;
1874                        expr = AstExpr::Subscript {
1875                            base: Box::new(expr),
1876                            index: Box::new(index),
1877                            span: Some(start),
1878                        };
1879                    }
1880                }
1881                TokenKind::InState => {
1882                    self.advance();
1883                    self.expect(&TokenKind::LParen)?;
1884                    let (state_name, _) = self.expect_name()?;
1885                    self.expect(&TokenKind::RParen)?;
1886                    expr = AstExpr::InState {
1887                        expr: Box::new(expr),
1888                        state_name,
1889                        span: Some(start),
1890                    };
1891                }
1892                _ => break,
1893            }
1894        }
1895        Ok(expr)
1896    }
1897
1898    fn parse_primary_expr(&mut self) -> Result<AstExpr> {
1899        let start = self.span();
1900
1901        match self.peek().clone() {
1902            TokenKind::Integer(value) => {
1903                self.advance();
1904                Ok(AstExpr::Int {
1905                    value,
1906                    span: Some(start),
1907                })
1908            }
1909            TokenKind::True => {
1910                self.advance();
1911                Ok(AstExpr::Bool {
1912                    value: true,
1913                    span: Some(start),
1914                })
1915            }
1916            TokenKind::False => {
1917                self.advance();
1918                Ok(AstExpr::Bool {
1919                    value: false,
1920                    span: Some(start),
1921                })
1922            }
1923            TokenKind::Null => {
1924                self.advance();
1925                Ok(AstExpr::Null { span: Some(start) })
1926            }
1927            TokenKind::LParen => {
1928                self.advance();
1929                let expr = self.parse_expr()?;
1930                self.expect(&TokenKind::RParen)?;
1931                Ok(expr)
1932            }
1933            TokenKind::Fill => {
1934                self.advance();
1935                self.expect(&TokenKind::LParen)?;
1936                let value = self.parse_expr()?;
1937                self.expect(&TokenKind::Comma)?;
1938                let count = self.parse_expr()?;
1939                self.expect(&TokenKind::RParen)?;
1940                Ok(AstExpr::Fill {
1941                    value: Box::new(value),
1942                    count: Box::new(count),
1943                    span: Some(start),
1944                })
1945            }
1946            TokenKind::All => {
1947                self.advance();
1948                self.expect(&TokenKind::LParen)?;
1949                let collection = self.parse_expr()?;
1950                self.expect(&TokenKind::Comma)?;
1951                // Expect in_state(StateName)
1952                self.expect(&TokenKind::InState)?;
1953                self.expect(&TokenKind::LParen)?;
1954                let (state_name, _) = self.expect_name()?;
1955                self.expect(&TokenKind::RParen)?;
1956                self.expect(&TokenKind::RParen)?;
1957                Ok(AstExpr::All {
1958                    collection: Box::new(collection),
1959                    state_name,
1960                    span: Some(start),
1961                })
1962            }
1963            _ => {
1964                // Try to parse as a name (including keywords used as identifiers)
1965                if let Some(name) = self.token_as_name() {
1966                    self.advance();
1967                    // Check for state constructor: Name::StateName(args)
1968                    if self.at(&TokenKind::ColonColon) {
1969                        self.advance();
1970                        let (state_name, _) = self.expect_name()?;
1971                        let mut args = Vec::new();
1972                        if self.eat(&TokenKind::LParen) {
1973                            if !self.at(&TokenKind::RParen) {
1974                                args.push(self.parse_expr()?);
1975                                while self.eat(&TokenKind::Comma) {
1976                                    args.push(self.parse_expr()?);
1977                                }
1978                            }
1979                            self.expect(&TokenKind::RParen)?;
1980                        }
1981                        Ok(AstExpr::StateConstructor {
1982                            sm_name: name,
1983                            state_name,
1984                            args,
1985                            span: Some(start),
1986                        })
1987                    } else {
1988                        Ok(AstExpr::NameRef {
1989                            name,
1990                            span: Some(start),
1991                        })
1992                    }
1993                } else {
1994                    Err(self.error(format!("expected expression, found {:?}", self.peek())))
1995                }
1996            }
1997        }
1998    }
1999
2000    // ── Helpers ──
2001
2002    fn parse_type_ref_name(&mut self) -> Result<String> {
2003        // Primitives, user-defined names, and keywords that can be type names
2004        if let Some(name) = self.token_as_name() {
2005            self.advance();
2006            Ok(name)
2007        } else {
2008            Err(self.error(format!("expected type name, found {:?}", self.peek())))
2009        }
2010    }
2011
2012    fn parse_integer(&mut self) -> Result<i64> {
2013        match self.peek().clone() {
2014            TokenKind::Integer(v) => {
2015                self.advance();
2016                Ok(v)
2017            }
2018            _ => Err(self.error(format!("expected integer, found {:?}", self.peek()))),
2019        }
2020    }
2021
2022    fn parse_literal_value(&mut self) -> Result<AstLiteralValue> {
2023        match self.peek().clone() {
2024            TokenKind::Integer(v) => {
2025                self.advance();
2026                Ok(AstLiteralValue::Int(v))
2027            }
2028            TokenKind::True => {
2029                self.advance();
2030                Ok(AstLiteralValue::Bool(true))
2031            }
2032            TokenKind::False => {
2033                self.advance();
2034                Ok(AstLiteralValue::Bool(false))
2035            }
2036            TokenKind::StringLit(v) => {
2037                self.advance();
2038                Ok(AstLiteralValue::String(v))
2039            }
2040            TokenKind::Null => {
2041                self.advance();
2042                Ok(AstLiteralValue::Null)
2043            }
2044            _ => Err(self.error(format!("expected literal, found {:?}", self.peek()))),
2045        }
2046    }
2047
2048    // ── Extern ASN.1 ──
2049
2050    fn parse_extern_asn1(&mut self, _annotations: Vec<AstAnnotation>) -> Result<AstTopItem> {
2051        let start = self.span();
2052        self.advance(); // skip "extern"
2053
2054        // Expect "asn1" as a name token
2055        let (kw, _) = self.expect_name()?;
2056        if kw != "asn1" {
2057            return Err(self.error(format!("expected 'asn1' after 'extern', found '{kw}'")));
2058        }
2059
2060        // Expect string literal for path
2061        let path = match self.peek().clone() {
2062            TokenKind::StringLit(s) => {
2063                self.advance();
2064                s
2065            }
2066            _ => return Err(self.error("expected string literal for ASN.1 file path".into())),
2067        };
2068
2069        // Optional: use <module_path>
2070        let rust_module = if let Some(name) = self.token_as_name() {
2071            if name == "use" {
2072                self.advance(); // skip "use"
2073                let (first, _) = self.expect_name()?;
2074                let mut mod_path = first;
2075                while self.eat(&TokenKind::ColonColon) {
2076                    let (part, _) = self.expect_name()?;
2077                    mod_path = format!("{mod_path}::{part}");
2078                }
2079                Some(mod_path)
2080            } else {
2081                None
2082            }
2083        } else {
2084            None
2085        };
2086
2087        // Expect { TypeA, TypeB, ... }
2088        self.expect(&TokenKind::LBrace)?;
2089        let mut type_names = Vec::new();
2090        while !self.at(&TokenKind::RBrace) {
2091            let (name, _) = self.expect_name()?;
2092            type_names.push(name);
2093            if !self.eat(&TokenKind::Comma) {
2094                break;
2095            }
2096        }
2097        self.expect(&TokenKind::RBrace)?;
2098
2099        Ok(AstTopItem::ExternAsn1(AstExternAsn1 {
2100            path,
2101            rust_module,
2102            type_names,
2103            span: Some(start),
2104        }))
2105    }
2106}
2107
2108// ── Public parse function ──
2109
2110pub fn parse(source: &str) -> std::result::Result<AstModule, ParseError> {
2111    let tokens = crate::lexer::Lexer::new(source)
2112        .tokenize()
2113        .map_err(|e| ParseError {
2114            msg: e.msg,
2115            span: Some(Span::new(e.offset as u32, 0)),
2116        })?;
2117    Parser::new(tokens).parse_module()
2118}