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                    value_bits = self.parse_integer()? as u8;
626                }
627                "max_bytes" => {
628                    max_bytes = self.parse_integer()? as u8;
629                }
630                "byte_order" => {
631                    let (val, _) = self.expect_name()?;
632                    byte_order = val;
633                }
634                _ => return Err(self.error(format!("unknown varint parameter: {pname}"))),
635            }
636            self.eat(&TokenKind::Comma);
637        }
638        self.expect(&TokenKind::RBrace)?;
639
640        Ok(AstTopItem::ContinuationVarInt(AstContinuationVarIntDecl {
641            name,
642            annotations,
643            continuation_bit,
644            value_bits,
645            max_bytes,
646            byte_order,
647            exported,
648            span: Some(start),
649        }))
650    }
651
652    // ── Packet ──
653
654    fn parse_packet(
655        &mut self,
656        annotations: Vec<AstAnnotation>,
657        exported: bool,
658    ) -> Result<AstPacketDecl> {
659        let start = self.span();
660        self.expect(&TokenKind::Packet)?;
661        let (name, _) = self.expect_name()?;
662        self.expect(&TokenKind::LBrace)?;
663        let fields = self.parse_field_list()?;
664        self.expect(&TokenKind::RBrace)?;
665        Ok(AstPacketDecl {
666            name,
667            fields,
668            annotations,
669            exported,
670            span: Some(start),
671        })
672    }
673
674    // ── Frame ──
675
676    fn parse_frame(
677        &mut self,
678        annotations: Vec<AstAnnotation>,
679        exported: bool,
680    ) -> Result<AstFrameDecl> {
681        let start = self.span();
682        self.expect(&TokenKind::Frame)?;
683        let (name, _) = self.expect_name()?;
684        self.expect(&TokenKind::Assign)?;
685        self.expect(&TokenKind::Match)?;
686        let (tag_field, _) = self.expect_name_or_keyword()?;
687        self.expect(&TokenKind::Colon)?;
688        let tag_type = self.parse_type_ref_name()?;
689        self.expect(&TokenKind::LBrace)?;
690        let branches = self.parse_frame_branches()?;
691        self.expect(&TokenKind::RBrace)?;
692        Ok(AstFrameDecl {
693            name,
694            tag_field,
695            tag_type,
696            branches,
697            annotations,
698            exported,
699            span: Some(start),
700        })
701    }
702
703    fn parse_frame_branches(&mut self) -> Result<Vec<AstFrameBranch>> {
704        let mut branches = Vec::new();
705        while !self.at(&TokenKind::RBrace) {
706            branches.push(self.parse_frame_branch()?);
707            self.eat(&TokenKind::Comma);
708        }
709        Ok(branches)
710    }
711
712    fn parse_frame_branch(&mut self) -> Result<AstFrameBranch> {
713        let start = self.span();
714        let pattern = self.parse_pattern()?;
715        self.expect(&TokenKind::FatArrow)?;
716        let (variant_name, _) = self.expect_name()?;
717        self.expect(&TokenKind::LBrace)?;
718        let fields = if self.at(&TokenKind::RBrace) {
719            Vec::new()
720        } else {
721            self.parse_field_list()?
722        };
723        self.expect(&TokenKind::RBrace)?;
724        Ok(AstFrameBranch {
725            pattern,
726            variant_name,
727            fields,
728            span: Some(start),
729        })
730    }
731
732    // ── Capsule ──
733
734    fn parse_capsule(
735        &mut self,
736        annotations: Vec<AstAnnotation>,
737        exported: bool,
738    ) -> Result<AstCapsuleDecl> {
739        let start = self.span();
740        self.expect(&TokenKind::Capsule)?;
741        let (name, _) = self.expect_name()?;
742        self.expect(&TokenKind::LBrace)?;
743
744        // Parse header fields until we hit "payload:"
745        let mut fields = Vec::new();
746        loop {
747            // Check for the payload field pattern: NAME ":" "match" ...
748            if let TokenKind::Name(fname) = self.peek().clone()
749                && fname == "payload"
750            {
751                // Peek ahead: payload : match
752                let saved = self.pos;
753                self.advance(); // skip "payload"
754                if self.at(&TokenKind::Colon) {
755                    self.advance(); // skip ":"
756                    if self.at(&TokenKind::Match) {
757                        // This is the payload match — parse it
758                        break;
759                    }
760                }
761                // Not a payload match, restore
762                self.pos = saved;
763            }
764            fields.push(self.parse_field_item()?);
765            self.eat(&TokenKind::Comma);
766        }
767
768        // Already consumed "payload" ":" and positioned at "match"
769        self.expect(&TokenKind::Match)?;
770
771        // capsule_tag = NAME | "(" expr ")"
772        let payload_tag = if self.eat(&TokenKind::LParen) {
773            let expr = self.parse_expr()?;
774            self.expect(&TokenKind::RParen)?;
775            AstPayloadTagSelector::Expr { expr }
776        } else {
777            let (tag_name, _) = self.expect_name_or_keyword()?;
778            AstPayloadTagSelector::Field {
779                field_name: tag_name,
780            }
781        };
782
783        self.expect(&TokenKind::Within)?;
784        let (payload_within, _) = self.expect_name_or_keyword()?;
785
786        self.expect(&TokenKind::LBrace)?;
787        let branches = self.parse_frame_branches()?;
788        self.expect(&TokenKind::RBrace)?;
789
790        // Close the capsule body
791        self.eat(&TokenKind::Comma);
792        self.expect(&TokenKind::RBrace)?;
793
794        Ok(AstCapsuleDecl {
795            name,
796            fields,
797            payload_tag,
798            payload_within,
799            branches,
800            annotations,
801            exported,
802            span: Some(start),
803        })
804    }
805
806    // ── State Machine ──
807
808    fn parse_state_machine(
809        &mut self,
810        annotations: Vec<AstAnnotation>,
811        exported: bool,
812    ) -> Result<AstStateMachineDecl> {
813        let start = self.span();
814        self.expect(&TokenKind::State)?;
815        self.expect(&TokenKind::Machine)?;
816        let (name, _) = self.expect_name()?;
817        self.expect(&TokenKind::LBrace)?;
818
819        let mut states = Vec::new();
820        let mut initial_state = String::new();
821        let mut transitions = Vec::new();
822        let mut verify_declarations = Vec::new();
823
824        while !self.at(&TokenKind::RBrace) {
825            match self.peek() {
826                TokenKind::State => {
827                    states.push(self.parse_state_decl()?);
828                }
829                TokenKind::Initial => {
830                    self.advance();
831                    let (iname, _) = self.expect_name()?;
832                    initial_state = iname;
833                }
834                TokenKind::Transition => {
835                    transitions.push(self.parse_transition()?);
836                }
837                TokenKind::Name(n) if n == "verify" => {
838                    verify_declarations.push(self.parse_verify_decl()?);
839                }
840                _ => {
841                    return Err(
842                        self.error(format!("unexpected in state machine: {:?}", self.peek()))
843                    );
844                }
845            }
846        }
847        self.expect(&TokenKind::RBrace)?;
848
849        Ok(AstStateMachineDecl {
850            name,
851            states,
852            initial_state,
853            transitions,
854            verify_declarations,
855            annotations,
856            exported,
857            span: Some(start),
858        })
859    }
860
861    fn parse_state_decl(&mut self) -> Result<AstStateDecl> {
862        let start = self.span();
863        self.expect(&TokenKind::State)?;
864        let (name, _) = self.expect_name()?;
865
866        let mut fields = Vec::new();
867        let mut is_terminal = false;
868
869        // Optional fields block
870        if self.eat(&TokenKind::LBrace) {
871            while !self.at(&TokenKind::RBrace) {
872                let fstart = self.span();
873                let (fname, _) = self.expect_name()?;
874                self.expect(&TokenKind::Colon)?;
875                let type_expr = self.parse_type_expr()?;
876                let default_value = if self.eat(&TokenKind::Assign) {
877                    Some(self.parse_literal_value()?)
878                } else {
879                    None
880                };
881                fields.push(AstStateFieldDef {
882                    name: fname,
883                    type_expr,
884                    default_value,
885                    span: Some(fstart),
886                });
887                self.eat(&TokenKind::Comma);
888            }
889            self.expect(&TokenKind::RBrace)?;
890        }
891
892        // [terminal]
893        if self.eat(&TokenKind::LBracket) {
894            self.expect(&TokenKind::Terminal)?;
895            self.expect(&TokenKind::RBracket)?;
896            is_terminal = true;
897        }
898
899        Ok(AstStateDecl {
900            name,
901            fields,
902            is_terminal,
903            span: Some(start),
904        })
905    }
906
907    fn parse_transition(&mut self) -> Result<AstTransitionDecl> {
908        let start = self.span();
909        self.expect(&TokenKind::Transition)?;
910
911        // src state: NAME | "*"
912        let src_state = if self.eat(&TokenKind::Star) {
913            "*".to_string()
914        } else {
915            let (s, _) = self.expect_name()?;
916            s
917        };
918
919        self.expect(&TokenKind::Arrow)?;
920        let (dst_state, _) = self.expect_name()?;
921
922        self.expect(&TokenKind::LBrace)?;
923
924        let mut events = Vec::new();
925        let mut guard = None;
926        let mut actions = Vec::new();
927        let mut delegate = None;
928        let mut has_guard = false;
929        let mut has_action = false;
930        let mut has_delegate = false;
931
932        while !self.at(&TokenKind::RBrace) {
933            match self.peek() {
934                TokenKind::On => {
935                    events.push(self.parse_event_decl()?);
936                }
937                TokenKind::Guard => {
938                    if has_guard {
939                        return Err(self.error("duplicate 'guard' clause in transition".into()));
940                    }
941                    has_guard = true;
942                    self.advance();
943                    guard = Some(self.parse_expr()?);
944                }
945                TokenKind::Action => {
946                    if has_action {
947                        return Err(self.error("duplicate 'action' clause in transition".into()));
948                    }
949                    has_action = true;
950                    self.advance();
951                    self.expect(&TokenKind::LBrace)?;
952                    while !self.at(&TokenKind::RBrace) {
953                        actions.push(self.parse_assignment()?);
954                        self.eat(&TokenKind::Semicolon);
955                    }
956                    self.expect(&TokenKind::RBrace)?;
957                }
958                TokenKind::Delegate => {
959                    if has_delegate {
960                        return Err(self.error("duplicate 'delegate' clause in transition".into()));
961                    }
962                    has_delegate = true;
963                    delegate = Some(self.parse_delegate_clause()?);
964                }
965                _ => {
966                    return Err(self.error(format!("unexpected in transition: {:?}", self.peek())));
967                }
968            }
969        }
970        self.expect(&TokenKind::RBrace)?;
971
972        Ok(AstTransitionDecl {
973            src_state,
974            dst_state,
975            events,
976            guard,
977            actions,
978            delegate,
979            span: Some(start),
980        })
981    }
982
983    fn parse_event_decl(&mut self) -> Result<AstEventDecl> {
984        let start = self.span();
985        self.expect(&TokenKind::On)?;
986        let (name, _) = self.expect_name_or_keyword()?;
987        let mut params = Vec::new();
988        if self.eat(&TokenKind::LParen) {
989            if !self.at(&TokenKind::RParen) {
990                loop {
991                    let pstart = self.span();
992                    let (pname, _) = self.expect_name()?;
993                    self.expect(&TokenKind::Colon)?;
994                    let type_expr = self.parse_type_expr()?;
995                    params.push(AstEventParam {
996                        name: pname,
997                        type_expr,
998                        span: Some(pstart),
999                    });
1000                    if !self.eat(&TokenKind::Comma) {
1001                        break;
1002                    }
1003                }
1004            }
1005            self.expect(&TokenKind::RParen)?;
1006        }
1007        Ok(AstEventDecl {
1008            name,
1009            params,
1010            span: Some(start),
1011        })
1012    }
1013
1014    fn parse_assignment(&mut self) -> Result<AstAssignment> {
1015        let start = self.span();
1016        let target = self.parse_postfix_expr()?;
1017        let op = if self.eat(&TokenKind::PlusAssign) {
1018            "+=".to_string()
1019        } else {
1020            self.expect(&TokenKind::Assign)?;
1021            "=".to_string()
1022        };
1023        let value = self.parse_expr()?;
1024        Ok(AstAssignment {
1025            target,
1026            op,
1027            value,
1028            span: Some(start),
1029        })
1030    }
1031
1032    fn parse_delegate_clause(&mut self) -> Result<AstDelegateClause> {
1033        let start = self.span();
1034        self.expect(&TokenKind::Delegate)?;
1035        let target = self.parse_postfix_expr()?;
1036        self.expect(&TokenKind::LArrow)?;
1037        let (event_name, _) = self.expect_name()?;
1038        Ok(AstDelegateClause {
1039            target,
1040            event_name,
1041            span: Some(start),
1042        })
1043    }
1044
1045    fn parse_verify_decl(&mut self) -> Result<AstVerifyDecl> {
1046        let start = self.span();
1047        self.advance(); // skip "verify"
1048
1049        // Check if it's `verify property Name: formula`
1050        if let TokenKind::Name(ref n) = self.peek().clone()
1051            && n == "property"
1052        {
1053            self.advance(); // skip "property"
1054            let (prop_name, _) = self.expect_name()?;
1055            self.expect(&TokenKind::Colon)?;
1056            let formula = self.parse_verify_formula()?;
1057            return Ok(AstVerifyDecl::Property {
1058                name: prop_name,
1059                formula,
1060                span: Some(start),
1061            });
1062        }
1063
1064        // Otherwise it's a built-in: `verify Name`
1065        let (builtin_name, _) = self.expect_name()?;
1066        Ok(AstVerifyDecl::BuiltIn {
1067            name: builtin_name,
1068            span: Some(start),
1069        })
1070    }
1071
1072    /// Parse a verify formula expression. Uses recursive descent with explicit
1073    /// precedence levels:
1074    ///   formula     → implies_expr
1075    ///   implies_expr → or_expr ( ( '->' | '~>' ) or_expr )*
1076    ///   or_expr     → and_expr ( 'or' and_expr )*
1077    ///   and_expr    → compare_expr ( 'and' compare_expr )*
1078    ///   compare_expr → unary_expr ( ( '<' | '<=' | '>' | '>=' | '==' | '!=' ) unary_expr )?
1079    ///   unary_expr  → '[]' unary_expr | '<>' unary_expr | 'not' unary_expr | primary
1080    ///   primary     → 'in_state' '(' Name ')' | 'true' | 'false' | Integer | Name ( '.' Name )* | '(' formula ')'
1081    fn parse_verify_formula(&mut self) -> Result<AstVerifyFormula> {
1082        self.parse_verify_implies()
1083    }
1084
1085    fn parse_verify_implies(&mut self) -> Result<AstVerifyFormula> {
1086        let mut left = self.parse_verify_or()?;
1087        loop {
1088            if self.at(&TokenKind::Arrow) {
1089                self.advance();
1090                let right = self.parse_verify_or()?;
1091                left = AstVerifyFormula::Implies {
1092                    left: Box::new(left),
1093                    right: Box::new(right),
1094                };
1095            } else if self.at(&TokenKind::TildeGt) {
1096                self.advance();
1097                let right = self.parse_verify_or()?;
1098                left = AstVerifyFormula::LeadsTo {
1099                    left: Box::new(left),
1100                    right: Box::new(right),
1101                };
1102            } else {
1103                break;
1104            }
1105        }
1106        Ok(left)
1107    }
1108
1109    fn parse_verify_or(&mut self) -> Result<AstVerifyFormula> {
1110        let mut left = self.parse_verify_and()?;
1111        while self.at(&TokenKind::Or) {
1112            self.advance();
1113            let right = self.parse_verify_and()?;
1114            left = AstVerifyFormula::Or {
1115                left: Box::new(left),
1116                right: Box::new(right),
1117            };
1118        }
1119        Ok(left)
1120    }
1121
1122    fn parse_verify_and(&mut self) -> Result<AstVerifyFormula> {
1123        let mut left = self.parse_verify_compare()?;
1124        while self.at(&TokenKind::And) {
1125            self.advance();
1126            let right = self.parse_verify_compare()?;
1127            left = AstVerifyFormula::And {
1128                left: Box::new(left),
1129                right: Box::new(right),
1130            };
1131        }
1132        Ok(left)
1133    }
1134
1135    fn parse_verify_compare(&mut self) -> Result<AstVerifyFormula> {
1136        let left = self.parse_verify_unary()?;
1137        let op = match self.peek() {
1138            TokenKind::Lt => Some("<"),
1139            TokenKind::Le => Some("<="),
1140            TokenKind::Gt => Some(">"),
1141            TokenKind::Ge => Some(">="),
1142            TokenKind::EqEq => Some("=="),
1143            TokenKind::BangEq => Some("!="),
1144            _ => None,
1145        };
1146        if let Some(op_str) = op {
1147            let op_string = op_str.to_string();
1148            self.advance();
1149            let right = self.parse_verify_unary()?;
1150            Ok(AstVerifyFormula::Compare {
1151                left: Box::new(left),
1152                op: op_string,
1153                right: Box::new(right),
1154            })
1155        } else {
1156            Ok(left)
1157        }
1158    }
1159
1160    fn parse_verify_unary(&mut self) -> Result<AstVerifyFormula> {
1161        // [] formula (Always)
1162        if self.at(&TokenKind::LBracket) {
1163            // Look ahead: [] means LBracket followed immediately by RBracket
1164            let saved = self.pos;
1165            self.advance(); // skip '['
1166            if self.at(&TokenKind::RBracket) {
1167                self.advance(); // skip ']'
1168                let inner = self.parse_verify_unary()?;
1169                return Ok(AstVerifyFormula::Always {
1170                    inner: Box::new(inner),
1171                });
1172            }
1173            // Not [], restore position
1174            self.pos = saved;
1175        }
1176
1177        // <> formula (Eventually) — Lt followed by Gt
1178        if self.at(&TokenKind::Lt) {
1179            let saved = self.pos;
1180            self.advance(); // skip '<'
1181            if self.at(&TokenKind::Gt) {
1182                self.advance(); // skip '>'
1183                let inner = self.parse_verify_unary()?;
1184                return Ok(AstVerifyFormula::Eventually {
1185                    inner: Box::new(inner),
1186                });
1187            }
1188            // Not <>, restore position
1189            self.pos = saved;
1190        }
1191
1192        // not formula
1193        if self.at(&TokenKind::Not) {
1194            self.advance();
1195            let inner = self.parse_verify_unary()?;
1196            return Ok(AstVerifyFormula::Not {
1197                inner: Box::new(inner),
1198            });
1199        }
1200
1201        self.parse_verify_primary()
1202    }
1203
1204    fn parse_verify_primary(&mut self) -> Result<AstVerifyFormula> {
1205        // in_state(Name)
1206        if self.at(&TokenKind::InState) {
1207            self.advance();
1208            self.expect(&TokenKind::LParen)?;
1209            let (state_name, _) = self.expect_name()?;
1210            self.expect(&TokenKind::RParen)?;
1211            return Ok(AstVerifyFormula::InState { state_name });
1212        }
1213
1214        // true / false
1215        if self.at(&TokenKind::True) {
1216            self.advance();
1217            return Ok(AstVerifyFormula::Literal {
1218                value: AstLiteralValue::Bool(true),
1219            });
1220        }
1221        if self.at(&TokenKind::False) {
1222            self.advance();
1223            return Ok(AstVerifyFormula::Literal {
1224                value: AstLiteralValue::Bool(false),
1225            });
1226        }
1227
1228        // Integer literal
1229        if let TokenKind::Integer(n) = self.peek().clone() {
1230            self.advance();
1231            return Ok(AstVerifyFormula::Literal {
1232                value: AstLiteralValue::Int(n),
1233            });
1234        }
1235
1236        // Parenthesized formula
1237        if self.at(&TokenKind::LParen) {
1238            self.advance();
1239            let inner = self.parse_verify_formula()?;
1240            self.expect(&TokenKind::RParen)?;
1241            return Ok(inner);
1242        }
1243
1244        // Name — possibly dotted path like src.field
1245        if let Some(name) = self.token_as_name() {
1246            self.advance();
1247            let mut path = vec![name];
1248            while self.eat(&TokenKind::Dot) {
1249                let (next, _) = self.expect_name()?;
1250                path.push(next);
1251            }
1252            return Ok(AstVerifyFormula::FieldRef { path });
1253        }
1254
1255        Err(self.error(format!("expected verify formula, found {:?}", self.peek())))
1256    }
1257
1258    // ── Fields ──
1259
1260    fn parse_field_list(&mut self) -> Result<Vec<AstFieldItem>> {
1261        let mut items = Vec::new();
1262        while !self.at(&TokenKind::RBrace) {
1263            items.push(self.parse_field_item()?);
1264            self.eat(&TokenKind::Comma);
1265        }
1266        Ok(items)
1267    }
1268
1269    fn parse_struct_field_list(&mut self) -> Result<Vec<AstFieldDef>> {
1270        let mut fields = Vec::new();
1271        while !self.at(&TokenKind::RBrace) {
1272            let anns = self.collect_annotations()?;
1273            let start = self.span();
1274            let (name, _) = self.expect_name()?;
1275            self.expect(&TokenKind::Colon)?;
1276            let type_expr = self.parse_type_expr()?;
1277            fields.push(AstFieldDef {
1278                name,
1279                type_expr,
1280                annotations: anns,
1281                span: Some(start),
1282            });
1283            self.eat(&TokenKind::Comma);
1284        }
1285        Ok(fields)
1286    }
1287
1288    fn parse_field_item(&mut self) -> Result<AstFieldItem> {
1289        match self.peek() {
1290            TokenKind::Let => {
1291                let start = self.span();
1292                self.advance();
1293                let (name, _) = self.expect_name()?;
1294                self.expect(&TokenKind::Colon)?;
1295                let type_name = self.parse_type_ref_name()?;
1296                self.expect(&TokenKind::Assign)?;
1297                let expr = self.parse_expr()?;
1298                Ok(AstFieldItem::Derived(AstDerivedField {
1299                    name,
1300                    type_name,
1301                    expr,
1302                    span: Some(start),
1303                }))
1304            }
1305            TokenKind::Require => {
1306                let start = self.span();
1307                self.advance();
1308                let expr = self.parse_expr()?;
1309                Ok(AstFieldItem::Require(AstRequireClause {
1310                    expr,
1311                    span: Some(start),
1312                }))
1313            }
1314            _ => {
1315                let anns = self.collect_annotations()?;
1316                let start = self.span();
1317                let (name, _) = self.expect_name_or_keyword()?;
1318                self.expect(&TokenKind::Colon)?;
1319                let type_expr = self.parse_type_expr()?;
1320                Ok(AstFieldItem::Field(AstFieldDef {
1321                    name,
1322                    type_expr,
1323                    annotations: anns,
1324                    span: Some(start),
1325                }))
1326            }
1327        }
1328    }
1329
1330    // ── Type Expressions ──
1331
1332    fn parse_type_expr(&mut self) -> Result<AstTypeExpr> {
1333        match self.peek() {
1334            TokenKind::Match => self.parse_match_type_expr(),
1335            TokenKind::If => self.parse_optional_type_expr(),
1336            TokenKind::LBracket => self.parse_array_type_expr(),
1337            TokenKind::Bytes => self.parse_bytes_type_expr(),
1338            TokenKind::Bits => self.parse_bits_type_expr(),
1339            TokenKind::Bit => {
1340                let span = self.span();
1341                self.advance();
1342                Ok(AstTypeExpr::Bits {
1343                    width: 1,
1344                    span: Some(span),
1345                })
1346            }
1347            _ => {
1348                let span = self.span();
1349                let name = self.parse_type_ref_name()?;
1350                // Check for asn1(...) function-call syntax
1351                if name == "asn1" && self.at(&TokenKind::LParen) {
1352                    return self.parse_asn1_type_expr(span);
1353                }
1354                Ok(AstTypeExpr::Named {
1355                    name,
1356                    span: Some(span),
1357                })
1358            }
1359        }
1360    }
1361
1362    fn parse_asn1_type_expr(&mut self, start: Span) -> Result<AstTypeExpr> {
1363        self.expect(&TokenKind::LParen)?;
1364
1365        // Type name
1366        let (type_name, _) = self.expect_name()?;
1367        self.expect(&TokenKind::Comma)?;
1368
1369        // encoding: <name>
1370        let (enc_kw, _) = self.expect_name()?;
1371        if enc_kw != "encoding" {
1372            return Err(self.error(format!("expected 'encoding', found '{enc_kw}'")));
1373        }
1374        self.expect(&TokenKind::Colon)?;
1375        let (encoding, _) = self.expect_name()?;
1376        self.expect(&TokenKind::Comma)?;
1377
1378        // length: <expr> OR remaining
1379        let length = if self.eat(&TokenKind::Remaining) {
1380            Asn1Length::Remaining
1381        } else {
1382            let (len_kw, _) = self.expect_name()?;
1383            if len_kw != "length" {
1384                return Err(self.error(format!(
1385                    "expected 'length' or 'remaining', found '{len_kw}'"
1386                )));
1387            }
1388            self.expect(&TokenKind::Colon)?;
1389            let expr = self.parse_expr()?;
1390            Asn1Length::Expr(Box::new(expr))
1391        };
1392
1393        self.expect(&TokenKind::RParen)?;
1394
1395        Ok(AstTypeExpr::Asn1 {
1396            type_name,
1397            encoding,
1398            length,
1399            span: Some(start),
1400        })
1401    }
1402
1403    fn parse_match_type_expr(&mut self) -> Result<AstTypeExpr> {
1404        let start = self.span();
1405        self.expect(&TokenKind::Match)?;
1406        let (field_name, _) = self.expect_name()?;
1407        self.expect(&TokenKind::LBrace)?;
1408        let mut branches = Vec::new();
1409        while !self.at(&TokenKind::RBrace) {
1410            let bstart = self.span();
1411            let pattern = self.parse_pattern()?;
1412            self.expect(&TokenKind::FatArrow)?;
1413            let result_type = self.parse_type_expr()?;
1414            branches.push(AstMatchBranch {
1415                pattern,
1416                result_type,
1417                span: Some(bstart),
1418            });
1419            self.eat(&TokenKind::Comma);
1420        }
1421        self.expect(&TokenKind::RBrace)?;
1422        Ok(AstTypeExpr::Match {
1423            field_name,
1424            branches,
1425            span: Some(start),
1426        })
1427    }
1428
1429    fn parse_optional_type_expr(&mut self) -> Result<AstTypeExpr> {
1430        let start = self.span();
1431        self.expect(&TokenKind::If)?;
1432        let condition = self.parse_expr()?;
1433        self.expect(&TokenKind::LBrace)?;
1434        let inner_type = self.parse_type_expr()?;
1435        self.expect(&TokenKind::RBrace)?;
1436        Ok(AstTypeExpr::Optional {
1437            condition,
1438            inner_type: Box::new(inner_type),
1439            span: Some(start),
1440        })
1441    }
1442
1443    fn parse_array_type_expr(&mut self) -> Result<AstTypeExpr> {
1444        let start = self.span();
1445        self.expect(&TokenKind::LBracket)?;
1446        let element_type = self.parse_type_expr()?;
1447        self.expect(&TokenKind::Semicolon)?;
1448
1449        let count = if self.eat(&TokenKind::Fill) {
1450            AstArrayCount::Fill
1451        } else {
1452            AstArrayCount::Expr(self.parse_expr()?)
1453        };
1454
1455        // Optional: "] within EXPR" for fill-within arrays (M15)
1456        self.expect(&TokenKind::RBracket)?;
1457
1458        let within_expr = if self.at(&TokenKind::Within) {
1459            // Only valid with fill arrays: [T; fill] within expr
1460            self.advance();
1461            Some(Box::new(self.parse_expr()?))
1462        } else {
1463            None
1464        };
1465
1466        Ok(AstTypeExpr::Array {
1467            element_type: Box::new(element_type),
1468            count,
1469            within_expr,
1470            span: Some(start),
1471        })
1472    }
1473
1474    fn parse_bytes_type_expr(&mut self) -> Result<AstTypeExpr> {
1475        let start = self.span();
1476        self.expect(&TokenKind::Bytes)?;
1477        self.expect(&TokenKind::LBracket)?;
1478
1479        // bytes[remaining]
1480        if self.eat(&TokenKind::Remaining) {
1481            self.expect(&TokenKind::RBracket)?;
1482            return Ok(AstTypeExpr::Bytes {
1483                kind: AstBytesKind::Remaining,
1484                fixed_size: None,
1485                size_expr: None,
1486                span: Some(start),
1487            });
1488        }
1489
1490        // Check for "length:" or "length_or_remaining:" with lookahead
1491        if let TokenKind::Name(n) = self.peek().clone()
1492            && (n == "length" || n == "length_or_remaining")
1493            && matches!(self.tokens[self.pos + 1].kind, TokenKind::Colon)
1494        {
1495            self.advance(); // skip "length" / "length_or_remaining"
1496            self.advance(); // skip ":"
1497            let expr = self.parse_expr()?;
1498            let kind = if n == "length" {
1499                AstBytesKind::Length
1500            } else {
1501                AstBytesKind::LengthOrRemaining
1502            };
1503            self.expect(&TokenKind::RBracket)?;
1504            return Ok(AstTypeExpr::Bytes {
1505                kind,
1506                fixed_size: None,
1507                size_expr: Some(Box::new(expr)),
1508                span: Some(start),
1509            });
1510        }
1511
1512        // bytes[N] — fixed size integer
1513        if let TokenKind::Integer(n) = *self.peek() {
1514            // Only treat as fixed if the next token after the integer is ']'
1515            if matches!(self.tokens[self.pos + 1].kind, TokenKind::RBracket) {
1516                self.advance();
1517                self.expect(&TokenKind::RBracket)?;
1518                return Ok(AstTypeExpr::Bytes {
1519                    kind: AstBytesKind::Fixed,
1520                    fixed_size: Some(n as u64),
1521                    size_expr: None,
1522                    span: Some(start),
1523                });
1524            }
1525        }
1526
1527        // bytes[EXPR] — expression for length (shorthand for bytes[length: EXPR])
1528        let expr = self.parse_expr()?;
1529        self.expect(&TokenKind::RBracket)?;
1530        Ok(AstTypeExpr::Bytes {
1531            kind: AstBytesKind::Length,
1532            fixed_size: None,
1533            size_expr: Some(Box::new(expr)),
1534            span: Some(start),
1535        })
1536    }
1537
1538    fn parse_bits_type_expr(&mut self) -> Result<AstTypeExpr> {
1539        let start = self.span();
1540        self.expect(&TokenKind::Bits)?;
1541        self.expect(&TokenKind::LBracket)?;
1542        let width = self.parse_integer()? as u16;
1543        self.expect(&TokenKind::RBracket)?;
1544        Ok(AstTypeExpr::Bits {
1545            width,
1546            span: Some(start),
1547        })
1548    }
1549
1550    // ── Patterns ──
1551
1552    fn parse_pattern(&mut self) -> Result<AstPattern> {
1553        let start = self.span();
1554        // Check for wildcard "_"
1555        if let TokenKind::Name(n) = self.peek().clone()
1556            && n == "_"
1557        {
1558            self.advance();
1559            return Ok(AstPattern::Wildcard { span: Some(start) });
1560        }
1561
1562        let value = self.parse_integer()?;
1563
1564        if self.eat(&TokenKind::DotDotEq) {
1565            let end = self.parse_integer()?;
1566            Ok(AstPattern::RangeInclusive {
1567                start: value,
1568                end,
1569                span: Some(start),
1570            })
1571        } else {
1572            Ok(AstPattern::Value {
1573                value,
1574                span: Some(start),
1575            })
1576        }
1577    }
1578
1579    // ── Expressions (precedence climbing) ──
1580    // Precedence (low to high):
1581    //   coalesce (??)
1582    //   or
1583    //   and
1584    //   comparison (==, !=, <, <=, >, >=)
1585    //   bitor (|)
1586    //   bitxor (^)
1587    //   bitand (&)
1588    //   shift (<<, >>)
1589    //   add (+, -)
1590    //   mul (*, /, %)
1591    //   unary (!, -)
1592    //   postfix (., [], [..])
1593
1594    fn parse_expr(&mut self) -> Result<AstExpr> {
1595        self.parse_coalesce_expr()
1596    }
1597
1598    fn parse_coalesce_expr(&mut self) -> Result<AstExpr> {
1599        let start = self.span();
1600        let mut expr = self.parse_or_expr()?;
1601        if self.eat(&TokenKind::QuestionQuestion) {
1602            let default = self.parse_or_expr()?;
1603            expr = AstExpr::Coalesce {
1604                expr: Box::new(expr),
1605                default: Box::new(default),
1606                span: Some(start),
1607            };
1608        }
1609        Ok(expr)
1610    }
1611
1612    fn parse_or_expr(&mut self) -> Result<AstExpr> {
1613        let start = self.span();
1614        let mut left = self.parse_and_expr()?;
1615        while self.eat(&TokenKind::Or) {
1616            let right = self.parse_and_expr()?;
1617            left = AstExpr::Binary {
1618                op: BinOp::Or,
1619                left: Box::new(left),
1620                right: Box::new(right),
1621                span: Some(start),
1622            };
1623        }
1624        Ok(left)
1625    }
1626
1627    fn parse_and_expr(&mut self) -> Result<AstExpr> {
1628        let start = self.span();
1629        let mut left = self.parse_compare_expr()?;
1630        while self.eat(&TokenKind::And) {
1631            let right = self.parse_compare_expr()?;
1632            left = AstExpr::Binary {
1633                op: BinOp::And,
1634                left: Box::new(left),
1635                right: Box::new(right),
1636                span: Some(start),
1637            };
1638        }
1639        Ok(left)
1640    }
1641
1642    fn parse_compare_expr(&mut self) -> Result<AstExpr> {
1643        let start = self.span();
1644        let left = self.parse_bitor_expr()?;
1645        let op = match self.peek() {
1646            TokenKind::EqEq => Some(BinOp::Eq),
1647            TokenKind::BangEq => Some(BinOp::Ne),
1648            TokenKind::Lt => Some(BinOp::Lt),
1649            TokenKind::Le => Some(BinOp::Le),
1650            TokenKind::Gt => Some(BinOp::Gt),
1651            TokenKind::Ge => Some(BinOp::Ge),
1652            _ => None,
1653        };
1654        if let Some(op) = op {
1655            self.advance();
1656            let right = self.parse_bitor_expr()?;
1657            Ok(AstExpr::Binary {
1658                op,
1659                left: Box::new(left),
1660                right: Box::new(right),
1661                span: Some(start),
1662            })
1663        } else {
1664            Ok(left)
1665        }
1666    }
1667
1668    fn parse_bitor_expr(&mut self) -> Result<AstExpr> {
1669        let start = self.span();
1670        let mut left = self.parse_bitxor_expr()?;
1671        while self.eat(&TokenKind::Pipe) {
1672            let right = self.parse_bitxor_expr()?;
1673            left = AstExpr::Binary {
1674                op: BinOp::BitOr,
1675                left: Box::new(left),
1676                right: Box::new(right),
1677                span: Some(start),
1678            };
1679        }
1680        Ok(left)
1681    }
1682
1683    fn parse_bitxor_expr(&mut self) -> Result<AstExpr> {
1684        let start = self.span();
1685        let mut left = self.parse_bitand_expr()?;
1686        while self.eat(&TokenKind::Caret) {
1687            let right = self.parse_bitand_expr()?;
1688            left = AstExpr::Binary {
1689                op: BinOp::BitXor,
1690                left: Box::new(left),
1691                right: Box::new(right),
1692                span: Some(start),
1693            };
1694        }
1695        Ok(left)
1696    }
1697
1698    fn parse_bitand_expr(&mut self) -> Result<AstExpr> {
1699        let start = self.span();
1700        let mut left = self.parse_shift_expr()?;
1701        while self.eat(&TokenKind::Amp) {
1702            let right = self.parse_shift_expr()?;
1703            left = AstExpr::Binary {
1704                op: BinOp::BitAnd,
1705                left: Box::new(left),
1706                right: Box::new(right),
1707                span: Some(start),
1708            };
1709        }
1710        Ok(left)
1711    }
1712
1713    fn parse_shift_expr(&mut self) -> Result<AstExpr> {
1714        let start = self.span();
1715        let mut left = self.parse_add_expr()?;
1716        loop {
1717            let op = match self.peek() {
1718                TokenKind::Shl => Some(BinOp::Shl),
1719                TokenKind::Shr => Some(BinOp::Shr),
1720                _ => None,
1721            };
1722            if let Some(op) = op {
1723                self.advance();
1724                let right = self.parse_add_expr()?;
1725                left = AstExpr::Binary {
1726                    op,
1727                    left: Box::new(left),
1728                    right: Box::new(right),
1729                    span: Some(start),
1730                };
1731            } else {
1732                break;
1733            }
1734        }
1735        Ok(left)
1736    }
1737
1738    fn parse_add_expr(&mut self) -> Result<AstExpr> {
1739        let start = self.span();
1740        let mut left = self.parse_mul_expr()?;
1741        loop {
1742            let op = match self.peek() {
1743                TokenKind::Plus => Some(BinOp::Add),
1744                TokenKind::Minus => Some(BinOp::Sub),
1745                _ => None,
1746            };
1747            if let Some(op) = op {
1748                self.advance();
1749                let right = self.parse_mul_expr()?;
1750                left = AstExpr::Binary {
1751                    op,
1752                    left: Box::new(left),
1753                    right: Box::new(right),
1754                    span: Some(start),
1755                };
1756            } else {
1757                break;
1758            }
1759        }
1760        Ok(left)
1761    }
1762
1763    fn parse_mul_expr(&mut self) -> Result<AstExpr> {
1764        let start = self.span();
1765        let mut left = self.parse_unary_expr()?;
1766        loop {
1767            let op = match self.peek() {
1768                TokenKind::Star => Some(BinOp::Mul),
1769                TokenKind::Slash => Some(BinOp::Div),
1770                TokenKind::Percent => Some(BinOp::Mod),
1771                _ => None,
1772            };
1773            if let Some(op) = op {
1774                self.advance();
1775                let right = self.parse_unary_expr()?;
1776                left = AstExpr::Binary {
1777                    op,
1778                    left: Box::new(left),
1779                    right: Box::new(right),
1780                    span: Some(start),
1781                };
1782            } else {
1783                break;
1784            }
1785        }
1786        Ok(left)
1787    }
1788
1789    fn parse_unary_expr(&mut self) -> Result<AstExpr> {
1790        let start = self.span();
1791        match self.peek() {
1792            TokenKind::Bang => {
1793                self.advance();
1794                let operand = self.parse_unary_expr()?;
1795                Ok(AstExpr::Unary {
1796                    op: UnaryOp::Not,
1797                    operand: Box::new(operand),
1798                    span: Some(start),
1799                })
1800            }
1801            TokenKind::Minus => {
1802                self.advance();
1803                let operand = self.parse_unary_expr()?;
1804                Ok(AstExpr::Unary {
1805                    op: UnaryOp::Neg,
1806                    operand: Box::new(operand),
1807                    span: Some(start),
1808                })
1809            }
1810            TokenKind::Not => {
1811                self.advance();
1812                let operand = self.parse_unary_expr()?;
1813                Ok(AstExpr::Unary {
1814                    op: UnaryOp::Not,
1815                    operand: Box::new(operand),
1816                    span: Some(start),
1817                })
1818            }
1819            _ => self.parse_postfix_expr(),
1820        }
1821    }
1822
1823    fn parse_postfix_expr(&mut self) -> Result<AstExpr> {
1824        let start = self.span();
1825        let mut expr = self.parse_primary_expr()?;
1826
1827        loop {
1828            match self.peek() {
1829                TokenKind::Dot => {
1830                    self.advance();
1831                    let (field, _) = self.expect_name_or_keyword()?;
1832                    expr = AstExpr::MemberAccess {
1833                        base: Box::new(expr),
1834                        field,
1835                        span: Some(start),
1836                    };
1837                }
1838                TokenKind::LBracket => {
1839                    self.advance();
1840                    let index = self.parse_expr()?;
1841                    // Check for slice: expr[start..end]
1842                    if self.eat(&TokenKind::DotDot) {
1843                        let end = self.parse_expr()?;
1844                        self.expect(&TokenKind::RBracket)?;
1845                        expr = AstExpr::Slice {
1846                            base: Box::new(expr),
1847                            start: Box::new(index),
1848                            end: Box::new(end),
1849                            span: Some(start),
1850                        };
1851                    } else {
1852                        self.expect(&TokenKind::RBracket)?;
1853                        expr = AstExpr::Subscript {
1854                            base: Box::new(expr),
1855                            index: Box::new(index),
1856                            span: Some(start),
1857                        };
1858                    }
1859                }
1860                TokenKind::InState => {
1861                    self.advance();
1862                    self.expect(&TokenKind::LParen)?;
1863                    let (state_name, _) = self.expect_name()?;
1864                    self.expect(&TokenKind::RParen)?;
1865                    expr = AstExpr::InState {
1866                        expr: Box::new(expr),
1867                        state_name,
1868                        span: Some(start),
1869                    };
1870                }
1871                _ => break,
1872            }
1873        }
1874        Ok(expr)
1875    }
1876
1877    fn parse_primary_expr(&mut self) -> Result<AstExpr> {
1878        let start = self.span();
1879
1880        match self.peek().clone() {
1881            TokenKind::Integer(value) => {
1882                self.advance();
1883                Ok(AstExpr::Int {
1884                    value,
1885                    span: Some(start),
1886                })
1887            }
1888            TokenKind::True => {
1889                self.advance();
1890                Ok(AstExpr::Bool {
1891                    value: true,
1892                    span: Some(start),
1893                })
1894            }
1895            TokenKind::False => {
1896                self.advance();
1897                Ok(AstExpr::Bool {
1898                    value: false,
1899                    span: Some(start),
1900                })
1901            }
1902            TokenKind::Null => {
1903                self.advance();
1904                Ok(AstExpr::Null { span: Some(start) })
1905            }
1906            TokenKind::LParen => {
1907                self.advance();
1908                let expr = self.parse_expr()?;
1909                self.expect(&TokenKind::RParen)?;
1910                Ok(expr)
1911            }
1912            TokenKind::Fill => {
1913                self.advance();
1914                self.expect(&TokenKind::LParen)?;
1915                let value = self.parse_expr()?;
1916                self.expect(&TokenKind::Comma)?;
1917                let count = self.parse_expr()?;
1918                self.expect(&TokenKind::RParen)?;
1919                Ok(AstExpr::Fill {
1920                    value: Box::new(value),
1921                    count: Box::new(count),
1922                    span: Some(start),
1923                })
1924            }
1925            TokenKind::All => {
1926                self.advance();
1927                self.expect(&TokenKind::LParen)?;
1928                let collection = self.parse_expr()?;
1929                self.expect(&TokenKind::Comma)?;
1930                // Expect in_state(StateName)
1931                self.expect(&TokenKind::InState)?;
1932                self.expect(&TokenKind::LParen)?;
1933                let (state_name, _) = self.expect_name()?;
1934                self.expect(&TokenKind::RParen)?;
1935                self.expect(&TokenKind::RParen)?;
1936                Ok(AstExpr::All {
1937                    collection: Box::new(collection),
1938                    state_name,
1939                    span: Some(start),
1940                })
1941            }
1942            _ => {
1943                // Try to parse as a name (including keywords used as identifiers)
1944                if let Some(name) = self.token_as_name() {
1945                    self.advance();
1946                    // Check for state constructor: Name::StateName(args)
1947                    if self.at(&TokenKind::ColonColon) {
1948                        self.advance();
1949                        let (state_name, _) = self.expect_name()?;
1950                        let mut args = Vec::new();
1951                        if self.eat(&TokenKind::LParen) {
1952                            if !self.at(&TokenKind::RParen) {
1953                                args.push(self.parse_expr()?);
1954                                while self.eat(&TokenKind::Comma) {
1955                                    args.push(self.parse_expr()?);
1956                                }
1957                            }
1958                            self.expect(&TokenKind::RParen)?;
1959                        }
1960                        Ok(AstExpr::StateConstructor {
1961                            sm_name: name,
1962                            state_name,
1963                            args,
1964                            span: Some(start),
1965                        })
1966                    } else {
1967                        Ok(AstExpr::NameRef {
1968                            name,
1969                            span: Some(start),
1970                        })
1971                    }
1972                } else {
1973                    Err(self.error(format!("expected expression, found {:?}", self.peek())))
1974                }
1975            }
1976        }
1977    }
1978
1979    // ── Helpers ──
1980
1981    fn parse_type_ref_name(&mut self) -> Result<String> {
1982        // Primitives, user-defined names, and keywords that can be type names
1983        if let Some(name) = self.token_as_name() {
1984            self.advance();
1985            Ok(name)
1986        } else {
1987            Err(self.error(format!("expected type name, found {:?}", self.peek())))
1988        }
1989    }
1990
1991    fn parse_integer(&mut self) -> Result<i64> {
1992        match self.peek().clone() {
1993            TokenKind::Integer(v) => {
1994                self.advance();
1995                Ok(v)
1996            }
1997            _ => Err(self.error(format!("expected integer, found {:?}", self.peek()))),
1998        }
1999    }
2000
2001    fn parse_literal_value(&mut self) -> Result<AstLiteralValue> {
2002        match self.peek().clone() {
2003            TokenKind::Integer(v) => {
2004                self.advance();
2005                Ok(AstLiteralValue::Int(v))
2006            }
2007            TokenKind::True => {
2008                self.advance();
2009                Ok(AstLiteralValue::Bool(true))
2010            }
2011            TokenKind::False => {
2012                self.advance();
2013                Ok(AstLiteralValue::Bool(false))
2014            }
2015            TokenKind::StringLit(v) => {
2016                self.advance();
2017                Ok(AstLiteralValue::String(v))
2018            }
2019            TokenKind::Null => {
2020                self.advance();
2021                Ok(AstLiteralValue::Null)
2022            }
2023            _ => Err(self.error(format!("expected literal, found {:?}", self.peek()))),
2024        }
2025    }
2026
2027    // ── Extern ASN.1 ──
2028
2029    fn parse_extern_asn1(&mut self, _annotations: Vec<AstAnnotation>) -> Result<AstTopItem> {
2030        let start = self.span();
2031        self.advance(); // skip "extern"
2032
2033        // Expect "asn1" as a name token
2034        let (kw, _) = self.expect_name()?;
2035        if kw != "asn1" {
2036            return Err(self.error(format!("expected 'asn1' after 'extern', found '{kw}'")));
2037        }
2038
2039        // Expect string literal for path
2040        let path = match self.peek().clone() {
2041            TokenKind::StringLit(s) => {
2042                self.advance();
2043                s
2044            }
2045            _ => return Err(self.error("expected string literal for ASN.1 file path".into())),
2046        };
2047
2048        // Optional: use <module_path>
2049        let rust_module = if let Some(name) = self.token_as_name() {
2050            if name == "use" {
2051                self.advance(); // skip "use"
2052                let (first, _) = self.expect_name()?;
2053                let mut mod_path = first;
2054                while self.eat(&TokenKind::ColonColon) {
2055                    let (part, _) = self.expect_name()?;
2056                    mod_path = format!("{mod_path}::{part}");
2057                }
2058                Some(mod_path)
2059            } else {
2060                None
2061            }
2062        } else {
2063            None
2064        };
2065
2066        // Expect { TypeA, TypeB, ... }
2067        self.expect(&TokenKind::LBrace)?;
2068        let mut type_names = Vec::new();
2069        while !self.at(&TokenKind::RBrace) {
2070            let (name, _) = self.expect_name()?;
2071            type_names.push(name);
2072            if !self.eat(&TokenKind::Comma) {
2073                break;
2074            }
2075        }
2076        self.expect(&TokenKind::RBrace)?;
2077
2078        Ok(AstTopItem::ExternAsn1(AstExternAsn1 {
2079            path,
2080            rust_module,
2081            type_names,
2082            span: Some(start),
2083        }))
2084    }
2085}
2086
2087// ── Public parse function ──
2088
2089pub fn parse(source: &str) -> std::result::Result<AstModule, ParseError> {
2090    let tokens = crate::lexer::Lexer::new(source)
2091        .tokenize()
2092        .map_err(|e| ParseError {
2093            msg: e.msg,
2094            span: Some(Span::new(e.offset as u32, 0)),
2095        })?;
2096    Parser::new(tokens).parse_module()
2097}