Skip to main content

synta_codegen/
parser.rs

1//! ASN.1 schema parser
2
3use crate::ast::*;
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct ParseError {
8    pub message: String,
9    pub line: usize,
10    pub column: usize,
11}
12
13impl fmt::Display for ParseError {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        write!(
16            f,
17            "Parse error at {}:{}: {}",
18            self.line, self.column, self.message
19        )
20    }
21}
22
23impl std::error::Error for ParseError {}
24
25type Result<T> = std::result::Result<T, ParseError>;
26
27// ASN.1 X.680 Reserved Keywords - All keywords are case-sensitive per X.680 specification
28// These are organized by category for maintainability
29
30/// Type constructor keywords
31const TYPE_CONSTRUCTORS: &[&str] = &["SEQUENCE", "SET", "CHOICE", "OF"];
32
33/// Field modifier keywords
34const FIELD_MODIFIERS: &[&str] = &["OPTIONAL", "DEFAULT"];
35
36/// Primitive type keywords (all uppercase per X.680)
37const PRIMITIVE_TYPES: &[&str] = &[
38    "INTEGER",
39    "BOOLEAN",
40    "OCTET",
41    "STRING",
42    "BIT",
43    "OBJECT",
44    "IDENTIFIER",
45    "NULL",
46    "REAL",
47    "ENUMERATED",
48];
49
50/// Built-in string types (mixed case per X.680)
51/// These can be used both as keywords and as type references
52const STRING_TYPES: &[&str] = &[
53    "UTF8String",
54    "PrintableString",
55    "IA5String",
56    "TeletexString",
57    "T61String",
58    "BMPString",
59    "UniversalString",
60    "GeneralString",
61    "GraphicString",
62    "NumericString",
63    "ObjectDescriptor",
64    "VideotexString",
65    "VisibleString",
66    "ISO646String",
67];
68
69/// Time type keywords
70const TIME_TYPES: &[&str] = &[
71    "UTCTime",
72    "GeneralizedTime",
73    "DATE",
74    "TIME",
75    "TIME-OF-DAY",
76    "DATE-TIME",
77    "DURATION",
78];
79
80/// Tagging keywords
81const TAGGING_KEYWORDS: &[&str] = &[
82    "EXPLICIT",
83    "IMPLICIT",
84    "AUTOMATIC",
85    "TAGS",
86    "UNIVERSAL",
87    "APPLICATION",
88    "PRIVATE",
89    "CONTEXT",
90    "IMPLIED",
91];
92
93/// Module definition keywords
94const MODULE_KEYWORDS: &[&str] = &["BEGIN", "END", "DEFINITIONS"];
95
96/// Constraint keywords
97const CONSTRAINT_KEYWORDS: &[&str] = &[
98    "SIZE",
99    "MIN",
100    "MAX",
101    "FROM",
102    "PATTERN",
103    "CONTAINING",
104    "WITH",
105    "COMPONENTS",
106];
107
108/// Set operation keywords
109const SET_OPERATIONS: &[&str] = &["ALL", "EXCEPT", "INCLUDES", "INTERSECTION", "UNION"];
110
111/// Import/export keywords
112const IMPORT_EXPORT: &[&str] = &["IMPORTS", "EXPORTS"];
113
114/// Special keywords
115const SPECIAL_KEYWORDS: &[&str] = &[
116    "ANY",
117    "DEFINED",
118    "BY",
119    "ABSENT",
120    "PRESENT",
121    "TRUE",
122    "FALSE",
123    "EXTENSIBILITY",
124    "ENCODED",
125    "PLUS-INFINITY",
126    "MINUS-INFINITY",
127    "NOT-A-NUMBER",
128];
129
130/// Class-related keywords
131const CLASS_KEYWORDS: &[&str] = &[
132    "CLASS",
133    "UNIQUE",
134    "SYNTAX",
135    "TYPE-IDENTIFIER",
136    "ABSTRACT-SYNTAX",
137];
138
139/// Additional type keywords
140const ADDITIONAL_TYPES: &[&str] = &[
141    "EXTERNAL",
142    "EMBEDDED",
143    "PDV",
144    "CHARACTER",
145    "RELATIVE-OID",
146    "OID-IRI",
147    "RELATIVE-OID-IRI",
148];
149
150/// Check if a string is an ASN.1 reserved keyword
151fn is_asn1_keyword(s: &str) -> bool {
152    TYPE_CONSTRUCTORS.contains(&s)
153        || FIELD_MODIFIERS.contains(&s)
154        || PRIMITIVE_TYPES.contains(&s)
155        || STRING_TYPES.contains(&s)
156        || TIME_TYPES.contains(&s)
157        || TAGGING_KEYWORDS.contains(&s)
158        || MODULE_KEYWORDS.contains(&s)
159        || CONSTRAINT_KEYWORDS.contains(&s)
160        || SET_OPERATIONS.contains(&s)
161        || IMPORT_EXPORT.contains(&s)
162        || SPECIAL_KEYWORDS.contains(&s)
163        || CLASS_KEYWORDS.contains(&s)
164        || ADDITIONAL_TYPES.contains(&s)
165}
166
167/// Built-in types that can be used as type references (keywords that represent types)
168fn is_builtin_type_keyword(s: &str) -> bool {
169    STRING_TYPES.contains(&s) || TIME_TYPES.contains(&s) || ADDITIONAL_TYPES.contains(&s)
170}
171
172/// Tokenizer for ASN.1 schemas
173#[derive(Clone)]
174struct Lexer {
175    input: Vec<char>,
176    pos: usize,
177    line: usize,
178    column: usize,
179}
180
181#[derive(Debug, Clone, PartialEq)]
182enum Token {
183    Identifier(String),
184    Number(u32),
185    Keyword(String),
186    Symbol(String),
187    Eof,
188}
189
190impl Lexer {
191    fn new(input: &str) -> Self {
192        Self {
193            input: input.chars().collect(),
194            pos: 0,
195            line: 1,
196            column: 1,
197        }
198    }
199
200    fn current(&self) -> Option<char> {
201        self.input.get(self.pos).copied()
202    }
203
204    fn advance(&mut self) -> Option<char> {
205        if let Some(ch) = self.current() {
206            self.pos += 1;
207            if ch == '\n' {
208                self.line += 1;
209                self.column = 1;
210            } else {
211                self.column += 1;
212            }
213            Some(ch)
214        } else {
215            None
216        }
217    }
218
219    fn skip_whitespace(&mut self) {
220        while let Some(ch) = self.current() {
221            if ch.is_whitespace() {
222                self.advance();
223            } else if ch == '-' && self.peek(1) == Some('-') {
224                // Skip comments (-- to end of line)
225                while let Some(ch) = self.current() {
226                    self.advance();
227                    if ch == '\n' {
228                        break;
229                    }
230                }
231            } else {
232                break;
233            }
234        }
235    }
236
237    fn peek(&self, offset: usize) -> Option<char> {
238        self.input.get(self.pos + offset).copied()
239    }
240
241    fn next_token(&mut self) -> Result<Token> {
242        self.skip_whitespace();
243
244        let ch = match self.current() {
245            Some(ch) => ch,
246            None => return Ok(Token::Eof),
247        };
248
249        // Quoted strings
250        if ch == '"' {
251            self.advance(); // consume opening quote
252            let mut string = String::new();
253            while let Some(ch) = self.current() {
254                if ch == '"' {
255                    self.advance(); // consume closing quote
256                    break;
257                } else if ch == '\\' {
258                    // Handle escape sequences
259                    self.advance();
260                    if let Some(escaped) = self.current() {
261                        match escaped {
262                            'n' => string.push('\n'),
263                            't' => string.push('\t'),
264                            'r' => string.push('\r'),
265                            '\\' => string.push('\\'),
266                            '"' => string.push('"'),
267                            _ => string.push(escaped),
268                        }
269                        self.advance();
270                    }
271                } else {
272                    string.push(ch);
273                    self.advance();
274                }
275            }
276            return Ok(Token::Identifier(string)); // Return as identifier for now
277        }
278
279        // Numbers
280        if ch.is_ascii_digit() {
281            let mut num = String::new();
282            while let Some(ch) = self.current() {
283                if ch.is_ascii_digit() {
284                    num.push(ch);
285                    self.advance();
286                } else {
287                    break;
288                }
289            }
290            return Ok(Token::Number(num.parse().unwrap()));
291        }
292
293        // Class field references: &identifier (X.681 §9)
294        // Consumed as a single Identifier token with the '&' prefix included.
295        if ch == '&' && self.peek(1).is_some_and(|c| c.is_alphabetic()) {
296            self.advance(); // consume '&'
297            let mut ident = String::from("&");
298            while let Some(ch) = self.current() {
299                if ch.is_alphanumeric() || ch == '-' {
300                    ident.push(ch);
301                    self.advance();
302                } else {
303                    break;
304                }
305            }
306            return Ok(Token::Identifier(ident));
307        }
308
309        // Identifiers and keywords
310        if ch.is_alphabetic() {
311            let mut ident = String::new();
312            while let Some(ch) = self.current() {
313                if ch.is_alphanumeric() || ch == '-' {
314                    ident.push(ch);
315                    self.advance();
316                } else {
317                    break;
318                }
319            }
320
321            // X.680 specifies that ASN.1 keywords are case-sensitive.
322            // Check if this identifier matches a reserved keyword exactly.
323            if is_asn1_keyword(&ident) {
324                return Ok(Token::Keyword(ident));
325            }
326
327            return Ok(Token::Identifier(ident));
328        }
329
330        // Multi-character symbols (check these first!)
331        if ch == ':' && self.peek(1) == Some(':') && self.peek(2) == Some('=') {
332            self.advance();
333            self.advance();
334            self.advance();
335            return Ok(Token::Symbol("::=".to_string()));
336        }
337
338        if ch == '.' && self.peek(1) == Some('.') && self.peek(2) == Some('.') {
339            self.advance();
340            self.advance();
341            self.advance();
342            return Ok(Token::Symbol("...".to_string()));
343        }
344
345        if ch == '.' && self.peek(1) == Some('.') {
346            self.advance();
347            self.advance();
348            return Ok(Token::Symbol("..".to_string()));
349        }
350
351        // Minus sign (but not if it's part of -- comment, which is handled in skip_whitespace)
352        if ch == '-' && self.peek(1) != Some('-') {
353            self.advance();
354            return Ok(Token::Symbol("-".to_string()));
355        }
356
357        // Single-character symbols
358        if matches!(
359            ch,
360            '{' | '}' | '[' | ']' | '(' | ')' | ',' | ':' | '|' | '^' | '@' | ';' | '.'
361        ) {
362            self.advance();
363            return Ok(Token::Symbol(ch.to_string()));
364        }
365
366        Err(ParseError {
367            message: format!("Unexpected character: {}", ch),
368            line: self.line,
369            column: self.column,
370        })
371    }
372}
373
374/// Parser for ASN.1 schemas
375pub struct Parser {
376    lexer: Lexer,
377    current: Token,
378    /// Default tagging mode derived from the module's `DEFINITIONS [IMPLICIT|EXPLICIT] TAGS`
379    /// declaration.  Starts as `Explicit` (the ASN.1 default when no keyword is present) and is
380    /// updated in `parse_module()` after the header is parsed.
381    default_tagging: Tagging,
382}
383
384impl Parser {
385    pub fn new(input: &str) -> Result<Self> {
386        let mut lexer = Lexer::new(input);
387        let current = lexer.next_token()?;
388        Ok(Self {
389            lexer,
390            current,
391            default_tagging: Tagging::Explicit,
392        })
393    }
394
395    fn advance(&mut self) -> Result<()> {
396        self.current = self.lexer.next_token()?;
397        Ok(())
398    }
399
400    fn expect_keyword(&mut self, keyword: &str) -> Result<()> {
401        if let Token::Keyword(kw) = &self.current {
402            if kw == keyword {
403                self.advance()?;
404                return Ok(());
405            }
406        }
407        Err(ParseError {
408            message: format!("Expected keyword '{}', got {:?}", keyword, self.current),
409            line: self.lexer.line,
410            column: self.lexer.column,
411        })
412    }
413
414    fn expect_symbol(&mut self, symbol: &str) -> Result<()> {
415        if let Token::Symbol(sym) = &self.current {
416            if sym == symbol {
417                self.advance()?;
418                return Ok(());
419            }
420        }
421        Err(ParseError {
422            message: format!("Expected symbol '{}', got {:?}", symbol, self.current),
423            line: self.lexer.line,
424            column: self.lexer.column,
425        })
426    }
427
428    fn expect_identifier(&mut self) -> Result<String> {
429        if let Token::Identifier(name) = &self.current {
430            let result = name.clone();
431            self.advance()?;
432            return Ok(result);
433        }
434        Err(ParseError {
435            message: format!("Expected identifier, got {:?}", self.current),
436            line: self.lexer.line,
437            column: self.lexer.column,
438        })
439    }
440
441    /// Parse size constraint (e.g., (SIZE (16)) or (SIZE (1..64)))
442    fn parse_size_constraint(&mut self) -> Result<Option<SizeConstraint>> {
443        if !matches!(self.current, Token::Symbol(ref s) if s == "(") {
444            return Ok(None);
445        }
446
447        self.advance()?; // consume '('
448
449        // Check for SIZE keyword
450        if !matches!(self.current, Token::Keyword(ref kw) if kw == "SIZE") {
451            // Not a SIZE constraint - skip it
452            while !matches!(self.current, Token::Symbol(ref s) if s == ")") {
453                if matches!(self.current, Token::Eof) {
454                    break;
455                }
456                self.advance()?;
457            }
458            if matches!(self.current, Token::Symbol(ref s) if s == ")") {
459                self.advance()?;
460            }
461            return Ok(None);
462        }
463
464        self.advance()?; // consume SIZE
465        self.expect_symbol("(")?;
466
467        // Parse size value
468        let min = if let Token::Number(n) = self.current {
469            let val = n;
470            self.advance()?;
471            Some(val as u64)
472        } else {
473            None
474        };
475
476        let constraint = if matches!(self.current, Token::Symbol(ref s) if s == "..") {
477            self.advance()?;
478            let max = if let Token::Number(n) = self.current {
479                let val = n;
480                self.advance()?;
481                Some(val as u64)
482            } else {
483                None
484            };
485            SizeConstraint::Range(min, max)
486        } else if let Some(size) = min {
487            SizeConstraint::Fixed(size)
488        } else {
489            return Ok(None);
490        };
491
492        self.expect_symbol(")")?; // inner paren
493        self.expect_symbol(")")?; // outer paren
494
495        Ok(Some(constraint))
496    }
497
498    /// Parse an integer value (positive or negative)
499    fn parse_integer_value(&mut self) -> Result<Option<i64>> {
500        // Check for negative sign
501        let negative = if matches!(self.current, Token::Symbol(ref s) if s == "-") {
502            self.advance()?;
503            true
504        } else {
505            false
506        };
507
508        if let Token::Number(n) = self.current {
509            let val = if negative { -(n as i64) } else { n as i64 };
510            self.advance()?;
511            Ok(Some(val))
512        } else {
513            Ok(None)
514        }
515    }
516
517    /// Parse a constraint value (X.680: integer, named value, MIN, or MAX)
518    fn parse_constraint_value(&mut self) -> Result<ConstraintValue> {
519        // Check for MIN keyword
520        if matches!(self.current, Token::Keyword(ref kw) if kw == "MIN") {
521            self.advance()?;
522            return Ok(ConstraintValue::Min);
523        }
524
525        // Check for MAX keyword
526        if matches!(self.current, Token::Keyword(ref kw) if kw == "MAX") {
527            self.advance()?;
528            return Ok(ConstraintValue::Max);
529        }
530
531        // Check for named value (identifier)
532        if let Token::Identifier(ref name) = self.current {
533            let name = name.clone();
534            self.advance()?;
535            return Ok(ConstraintValue::NamedValue(name));
536        }
537
538        // Check for integer value
539        if let Some(val) = self.parse_integer_value()? {
540            return Ok(ConstraintValue::Integer(val));
541        }
542
543        Err(ParseError {
544            message: "Expected constraint value (integer, MIN, MAX, or identifier)".to_string(),
545            line: self.lexer.line,
546            column: self.lexer.column,
547        })
548    }
549
550    /// Parse a subtype constraint with union/intersection operators
551    fn parse_subtype_constraint(&mut self) -> Result<SubtypeConstraint> {
552        // Parse the first constraint element
553        let first = self.parse_single_constraint()?;
554
555        // Check for union (|) or intersection (^) operators
556        let mut elements = vec![first];
557        let mut is_union = false;
558        let mut is_intersection = false;
559
560        while matches!(self.current, Token::Symbol(ref s) if s == "|" || s == "^") {
561            let op = if let Token::Symbol(ref s) = self.current {
562                s.clone()
563            } else {
564                unreachable!()
565            };
566
567            if op == "|" {
568                is_union = true;
569            } else if op == "^" {
570                is_intersection = true;
571            }
572
573            self.advance()?; // consume operator
574            elements.push(self.parse_single_constraint()?);
575        }
576
577        // Return appropriate constraint type
578        if is_union && is_intersection {
579            return Err(ParseError {
580                message: "Cannot mix union (|) and intersection (^) operators without parentheses"
581                    .to_string(),
582                line: self.lexer.line,
583                column: self.lexer.column,
584            });
585        }
586
587        if is_union {
588            Ok(SubtypeConstraint::Union(elements))
589        } else if is_intersection {
590            Ok(SubtypeConstraint::Intersection(elements))
591        } else {
592            Ok(elements.into_iter().next().unwrap())
593        }
594    }
595
596    /// Parse a single constraint element (value, range, or parenthesized constraint)
597    fn parse_single_constraint(&mut self) -> Result<SubtypeConstraint> {
598        // Check for ALL EXCEPT
599        if matches!(self.current, Token::Keyword(ref kw) if kw == "ALL") {
600            self.advance()?;
601            self.expect_keyword("EXCEPT")?;
602            let inner = self.parse_single_constraint()?;
603            return Ok(SubtypeConstraint::Complement(Box::new(inner)));
604        }
605
606        // Check for parenthesized constraint
607        if matches!(self.current, Token::Symbol(ref s) if s == "(") {
608            self.advance()?; // consume '('
609            let constraint = self.parse_subtype_constraint()?;
610            self.expect_symbol(")")?;
611            return Ok(constraint);
612        }
613
614        // Parse first value
615        let first_value = self.parse_constraint_value()?;
616
617        // Check for range operator (..)
618        if matches!(self.current, Token::Symbol(ref s) if s == "..") {
619            self.advance()?; // consume '..'
620            let second_value = self.parse_constraint_value()?;
621            return Ok(SubtypeConstraint::ValueRange {
622                min: first_value,
623                max: second_value,
624            });
625        }
626
627        // Single value constraint
628        Ok(SubtypeConstraint::SingleValue(first_value))
629    }
630
631    /// Parse a permitted alphabet constraint: FROM ("A".."Z" | "0".."9")
632    fn parse_permitted_alphabet(&mut self) -> Result<SubtypeConstraint> {
633        self.expect_keyword("FROM")?;
634        self.expect_symbol("(")?;
635
636        let mut ranges = Vec::new();
637
638        loop {
639            // Parse a string literal or character range
640            if let Token::Identifier(ref s) = self.current {
641                // String literal - extract character range
642                let chars: Vec<char> = s.chars().collect();
643                if chars.len() == 1 {
644                    let ch = chars[0];
645                    self.advance()?;
646
647                    // Check for range operator
648                    if matches!(self.current, Token::Symbol(ref sym) if sym == "..") {
649                        self.advance()?; // consume '..'
650
651                        // Parse end character
652                        if let Token::Identifier(ref end_s) = self.current {
653                            let end_chars: Vec<char> = end_s.chars().collect();
654                            if end_chars.len() == 1 {
655                                ranges.push(CharRange {
656                                    min: ch,
657                                    max: end_chars[0],
658                                });
659                                self.advance()?;
660                            }
661                        }
662                    } else {
663                        // Single character
664                        ranges.push(CharRange { min: ch, max: ch });
665                    }
666                }
667            }
668
669            // Check for more ranges
670            if matches!(self.current, Token::Symbol(ref s) if s == "|") {
671                self.advance()?; // consume '|'
672            } else {
673                break;
674            }
675        }
676
677        self.expect_symbol(")")?;
678        Ok(SubtypeConstraint::PermittedAlphabet(ranges))
679    }
680
681    /// Parse a pattern constraint: PATTERN "regex"
682    fn parse_pattern(&mut self) -> Result<SubtypeConstraint> {
683        self.expect_keyword("PATTERN")?;
684
685        // Pattern should be a string literal
686        if let Token::Identifier(ref pattern) = self.current {
687            let pattern_str = pattern.clone();
688            self.advance()?;
689            Ok(SubtypeConstraint::Pattern(pattern_str))
690        } else {
691            Err(ParseError {
692                message: "Expected pattern string after PATTERN keyword".to_string(),
693                line: self.lexer.line,
694                column: self.lexer.column,
695            })
696        }
697    }
698
699    /// Parse a DEFAULT value (number, boolean, string, etc.)
700    fn parse_default_value(&mut self) -> Result<String> {
701        let value = match &self.current {
702            Token::Number(n) => {
703                let val = n.to_string();
704                self.advance()?;
705                val
706            }
707            Token::Symbol(s) if s == "-" => {
708                // Negative number
709                self.advance()?;
710                if let Token::Number(n) = self.current {
711                    let val = format!("-{}", n);
712                    self.advance()?;
713                    val
714                } else {
715                    return Err(ParseError {
716                        message: "Expected number after '-'".to_string(),
717                        line: self.lexer.line,
718                        column: self.lexer.column,
719                    });
720                }
721            }
722            Token::Keyword(kw) if kw == "TRUE" => {
723                self.advance()?;
724                "true".to_string()
725            }
726            Token::Keyword(kw) if kw == "FALSE" => {
727                self.advance()?;
728                "false".to_string()
729            }
730            Token::Identifier(s) => {
731                // Could be a string literal (from quoted string) or named value
732                let val = s.clone();
733                self.advance()?;
734                // If it looks like a string literal, quote it
735                // Otherwise assume it's a named constant
736                val
737            }
738            _ => {
739                return Err(ParseError {
740                    message: format!("Unexpected token in DEFAULT value: {:?}", self.current),
741                    line: self.lexer.line,
742                    column: self.lexer.column,
743                });
744            }
745        };
746
747        Ok(value)
748    }
749
750    /// Helper to parse a string type with optional constraints
751    /// This reduces code duplication for UTF8String, PrintableString, IA5String, etc.
752    fn parse_string_type(&mut self, base_type: Type) -> Result<Type> {
753        self.advance()?;
754
755        // Check for X.680 string constraints (SIZE, FROM, PATTERN)
756        if let Some(constraint) = self.parse_string_constraint()? {
757            return Ok(Type::Constrained {
758                base_type: Box::new(base_type),
759                constraint: Constraint {
760                    spec: ConstraintSpec::Subtype(constraint),
761                    exception: None,
762                },
763            });
764        }
765
766        Ok(base_type)
767    }
768
769    /// Parse string constraints (SIZE, FROM, PATTERN)
770    /// Supports combined constraints: (SIZE (...) FROM (...))
771    fn parse_string_constraint(&mut self) -> Result<Option<SubtypeConstraint>> {
772        if !matches!(self.current, Token::Symbol(ref s) if s == "(") {
773            return Ok(None);
774        }
775
776        self.advance()?; // consume '('
777
778        // Collect multiple constraints that can be combined
779        let mut constraints = Vec::new();
780
781        // Parse first constraint
782        if let Some(constraint) = self.parse_single_string_constraint()? {
783            constraints.push(constraint);
784        }
785
786        // Check for additional constraints (combined constraints)
787        // e.g., (SIZE (4..6) FROM ("0".."9"))
788        while !matches!(self.current, Token::Symbol(ref s) if s == ")") {
789            if matches!(self.current, Token::Eof) {
790                break;
791            }
792
793            // Try to parse another constraint keyword
794            if let Some(constraint) = self.parse_single_string_constraint()? {
795                constraints.push(constraint);
796            } else {
797                // If not a recognized constraint, skip to closing paren
798                break;
799            }
800        }
801
802        self.expect_symbol(")")?; // outer paren
803
804        // Return appropriate constraint based on count
805        match constraints.len() {
806            0 => Ok(None),
807            1 => Ok(Some(constraints.into_iter().next().unwrap())),
808            _ => {
809                // Multiple constraints - combine with Intersection
810                Ok(Some(SubtypeConstraint::Intersection(constraints)))
811            }
812        }
813    }
814
815    /// Parse a single string constraint keyword (SIZE, FROM, PATTERN, CONTAINING)
816    fn parse_single_string_constraint(&mut self) -> Result<Option<SubtypeConstraint>> {
817        // Check for SIZE keyword
818        if matches!(self.current, Token::Keyword(ref kw) if kw == "SIZE") {
819            self.advance()?; // consume SIZE
820            self.expect_symbol("(")?;
821
822            // Parse size value or range
823            let size_constraint = self.parse_subtype_constraint()?;
824
825            self.expect_symbol(")")?; // inner paren
826                                      // Don't consume outer paren here - let caller handle it
827
828            return Ok(Some(SubtypeConstraint::SizeConstraint(Box::new(
829                size_constraint,
830            ))));
831        }
832
833        // Check for FROM keyword
834        if matches!(self.current, Token::Keyword(ref kw) if kw == "FROM") {
835            let constraint = self.parse_permitted_alphabet()?;
836            // Don't consume outer paren here - let caller handle it
837            return Ok(Some(constraint));
838        }
839
840        // Check for PATTERN keyword
841        if matches!(self.current, Token::Keyword(ref kw) if kw == "PATTERN") {
842            let constraint = self.parse_pattern()?;
843            // Don't consume outer paren here - let caller handle it
844            return Ok(Some(constraint));
845        }
846
847        // Check for CONTAINING keyword (Phase 3)
848        if matches!(self.current, Token::Keyword(ref kw) if kw == "CONTAINING") {
849            self.advance()?; // consume CONTAINING
850            let contained_type = self.parse_type()?;
851            // Don't consume outer paren here - let caller handle it
852            return Ok(Some(SubtypeConstraint::ContainedSubtype(Box::new(
853                contained_type,
854            ))));
855        }
856
857        Ok(None)
858    }
859
860    /// Parse EXPORTS clause
861    /// EXPORTS Type1, Type2, Type3; or EXPORTS ALL;
862    fn parse_exports(&mut self) -> Result<Vec<String>> {
863        let mut exports = Vec::new();
864
865        // Check if EXPORTS keyword is present
866        if !matches!(self.current, Token::Keyword(ref kw) if kw == "EXPORTS") {
867            return Ok(exports);
868        }
869
870        self.advance()?; // consume EXPORTS
871
872        // Check for "EXPORTS ALL;"
873        if matches!(self.current, Token::Keyword(ref kw) if kw == "ALL") {
874            self.advance()?; // consume ALL
875            if matches!(self.current, Token::Symbol(ref s) if s == ";") {
876                self.advance()?; // consume ';'
877            }
878            // Return empty vec - ALL means export everything
879            // Code generator will handle this appropriately
880            return Ok(exports);
881        }
882
883        // Parse exported symbol names
884        loop {
885            if matches!(self.current, Token::Symbol(ref s) if s == ";") {
886                self.advance()?; // consume ';'
887                break;
888            }
889
890            if matches!(self.current, Token::Eof)
891                || matches!(self.current, Token::Keyword(ref kw) if kw == "IMPORTS" || kw == "END")
892            {
893                // Semicolon is optional in some cases
894                break;
895            }
896
897            let name = self.expect_identifier()?;
898            exports.push(name);
899
900            // Check for comma
901            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
902                self.advance()?; // consume ','
903            }
904        }
905
906        Ok(exports)
907    }
908
909    /// Parse IMPORTS clause
910    /// IMPORTS Type1, Type2 FROM Module1 Type3 FROM Module2;
911    fn parse_imports(&mut self) -> Result<Vec<Import>> {
912        let mut imports = Vec::new();
913
914        // Check if IMPORTS keyword is present
915        if !matches!(self.current, Token::Keyword(ref kw) if kw == "IMPORTS") {
916            return Ok(imports);
917        }
918
919        self.advance()?; // consume IMPORTS
920
921        // Parse import declarations
922        loop {
923            if matches!(self.current, Token::Symbol(ref s) if s == ";") {
924                self.advance()?; // consume ';'
925                break;
926            }
927
928            if matches!(self.current, Token::Eof)
929                || matches!(self.current, Token::Keyword(ref kw) if kw == "END")
930            {
931                // Semicolon is optional in some cases
932                break;
933            }
934
935            // Parse symbols (Type1, Type2, ...)
936            let mut symbols = Vec::new();
937            loop {
938                if matches!(self.current, Token::Keyword(ref kw) if kw == "FROM") {
939                    break;
940                }
941
942                let name = self.expect_identifier()?;
943
944                // Skip optional parameterized type arguments after identifier,
945                // e.g. `AlgorithmIdentifier{}` or `AlgorithmIdentifier{T, {S}}`.
946                if matches!(self.current, Token::Symbol(ref s) if s == "{") {
947                    self.skip_balanced_braces()?;
948                }
949
950                symbols.push(name);
951
952                // Check for comma
953                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
954                    self.advance()?; // consume ','
955                } else {
956                    break;
957                }
958            }
959
960            // Expect FROM keyword
961            self.expect_keyword("FROM")?;
962
963            // Parse module name
964            let module_name = self.expect_identifier()?;
965
966            // Skip optional module OID block after the module name,
967            // e.g. `FROM AlgorithmInformation-2009 { iso(1) ... }`.
968            if matches!(self.current, Token::Symbol(ref s) if s == "{") {
969                self.skip_balanced_braces()?;
970            }
971
972            imports.push(Import {
973                symbols,
974                module_name,
975            });
976
977            // Check if there are more imports or end of IMPORTS clause
978            if matches!(self.current, Token::Symbol(ref s) if s == ";") {
979                self.advance()?; // consume ';'
980                break;
981            }
982
983            // If no semicolon, check for additional import groups or end
984            if matches!(self.current, Token::Eof)
985                || matches!(self.current, Token::Keyword(ref kw) if kw == "END")
986                || !matches!(self.current, Token::Identifier(_))
987            {
988                break;
989            }
990        }
991
992        Ok(imports)
993    }
994
995    /// Parse a complete module
996    pub fn parse_module(&mut self) -> Result<Module> {
997        let name = self.expect_identifier()?;
998
999        // Parse optional module OID
1000        let oid = if let Token::Symbol(ref sym) = self.current {
1001            if sym == "{" {
1002                Some(self.parse_module_oid()?)
1003            } else {
1004                None
1005            }
1006        } else {
1007            None
1008        };
1009
1010        self.expect_keyword("DEFINITIONS")?;
1011
1012        // Parse optional tagging mode
1013        let tagging_mode = if let Token::Keyword(ref kw) = self.current {
1014            match kw.as_str() {
1015                "EXPLICIT" => {
1016                    self.advance()?;
1017                    self.expect_keyword("TAGS")?;
1018                    Some(crate::ast::TaggingMode::Explicit)
1019                }
1020                "IMPLICIT" => {
1021                    self.advance()?;
1022                    self.expect_keyword("TAGS")?;
1023                    Some(crate::ast::TaggingMode::Implicit)
1024                }
1025                "AUTOMATIC" => {
1026                    self.advance()?;
1027                    self.expect_keyword("TAGS")?;
1028                    Some(crate::ast::TaggingMode::Automatic)
1029                }
1030                _ => None,
1031            }
1032        } else {
1033            None
1034        };
1035
1036        // Propagate the module-level tagging default to the parser so that bare [N] tags
1037        // in SEQUENCE fields use the correct default (IMPLICIT for "DEFINITIONS IMPLICIT TAGS",
1038        // etc.).  AUTOMATIC behaves like IMPLICIT for field tagging purposes.
1039        self.default_tagging = match &tagging_mode {
1040            Some(crate::ast::TaggingMode::Implicit) | Some(crate::ast::TaggingMode::Automatic) => {
1041                Tagging::Implicit
1042            }
1043            _ => Tagging::Explicit,
1044        };
1045
1046        self.expect_symbol("::=")?;
1047        self.expect_keyword("BEGIN")?;
1048
1049        // Parse EXPORTS if present
1050        let exports = self.parse_exports()?;
1051
1052        // Parse IMPORTS if present
1053        let imports = self.parse_imports()?;
1054
1055        // Parse definitions and value assignments
1056        let mut definitions = Vec::new();
1057        let mut values = Vec::new();
1058        while !matches!(self.current, Token::Keyword(ref kw) if kw == "END") {
1059            if matches!(self.current, Token::Eof) {
1060                break;
1061            }
1062            // Priority order:
1063            //  1. Classic value assignment (name OBJECT|INTEGER|BOOLEAN ::= value)
1064            //  2. IOC value assignment (name ClassName ::= { ... }) — consumed and discarded
1065            //  3. Type definition (TypeName ::= Type)
1066            if let Some(value_assignment) = self.try_parse_value_assignment()? {
1067                values.push(value_assignment);
1068            } else if self.try_skip_class_alias()? {
1069                // Class alias assignment (e.g. `MyClass ::= TYPE-IDENTIFIER`) consumed and discarded
1070            } else if self.try_skip_ioc_assignment()? {
1071                // IOC assignment consumed; loop continues to the next definition
1072            } else {
1073                definitions.push(self.parse_definition()?);
1074            }
1075        }
1076
1077        if matches!(self.current, Token::Keyword(ref kw) if kw == "END") {
1078            self.advance()?;
1079        }
1080
1081        Ok(Module {
1082            name,
1083            oid,
1084            tagging_mode,
1085            imports,
1086            exports,
1087            definitions,
1088            values,
1089        })
1090    }
1091
1092    /// Parse module OID: { iso(1) identified-organization(3) ... }
1093    /// Returns a vector of OID components as strings for simplicity
1094    fn parse_module_oid(&mut self) -> Result<Vec<String>> {
1095        self.expect_symbol("{")?;
1096        let mut oid_parts = Vec::new();
1097
1098        // Parse OID components until we hit the closing brace
1099        while !matches!(self.current, Token::Symbol(ref sym) if sym == "}") {
1100            match &self.current {
1101                Token::Identifier(id) => {
1102                    oid_parts.push(id.clone());
1103                    self.advance()?;
1104
1105                    // Check for (number) after identifier
1106                    if let Token::Symbol(ref sym) = self.current {
1107                        if sym == "(" {
1108                            self.advance()?;
1109                            if let Token::Number(n) = self.current {
1110                                oid_parts.push(n.to_string());
1111                                self.advance()?;
1112                            }
1113                            self.expect_symbol(")")?;
1114                        }
1115                    }
1116                }
1117                Token::Number(n) => {
1118                    oid_parts.push(n.to_string());
1119                    self.advance()?;
1120                }
1121                Token::Eof => {
1122                    return Err(ParseError {
1123                        message: "Unexpected end of input in module OID".to_string(),
1124                        line: self.lexer.line,
1125                        column: self.lexer.column,
1126                    });
1127                }
1128                _ => {
1129                    // Skip other tokens (like whitespace, etc.)
1130                    self.advance()?;
1131                }
1132            }
1133        }
1134
1135        self.expect_symbol("}")?;
1136        Ok(oid_parts)
1137    }
1138
1139    fn parse_definition(&mut self) -> Result<Definition> {
1140        let name = self.expect_identifier()?;
1141
1142        // Skip optional parameterized type formal parameters after the type name,
1143        // e.g. `AttributeSet{ATTRIBUTE:AttrSet} ::= SEQUENCE { ... }`.
1144        // The parameter list carries governance information only; no DER encoding
1145        // information is lost by discarding it.
1146        if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1147            self.skip_balanced_braces()?;
1148        }
1149
1150        self.expect_symbol("::=")?;
1151        let ty = self.parse_type()?;
1152
1153        // Skip any trailing constraint expression that follows the type definition
1154        // in 2009-syntax modules.  The most common case is the `(WITH COMPONENTS { ... })`
1155        // subtype constraint after a SEQUENCE or CHOICE, e.g.:
1156        //   `AuthorityKeyIdentifier ::= SEQUENCE { ... } (WITH COMPONENTS { ... })`
1157        // These are value-range / component presence constraints that carry no
1158        // encoding information synta needs; discarding them is safe.
1159        if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1160            self.skip_balanced_parens()?;
1161        }
1162
1163        Ok(Definition { name, ty })
1164    }
1165
1166    /// Try to parse a value assignment (e.g., oidName OBJECT IDENTIFIER ::= { 1 2 3 })
1167    /// Returns None if this is not a value assignment (it's a type definition instead)
1168    fn try_parse_value_assignment(&mut self) -> Result<Option<crate::ast::ValueAssignment>> {
1169        // Look ahead to determine if this is a value assignment
1170        // Value assignment: name Type ::= value
1171        // Type definition: TypeName ::= Type
1172        // We can distinguish by checking if there's a type keyword before ::=
1173
1174        // We need at least: IDENTIFIER KEYWORD ::=
1175        // For value assignment, the second token should be OBJECT, INTEGER, BOOLEAN, etc.
1176        let is_value_assignment = if let Token::Identifier(_) = &self.current {
1177            // Peek ahead - if it's a type keyword, it's likely a value assignment
1178            matches!(self.peek_next_token(), Token::Keyword(ref kw)
1179                if kw == "OBJECT" || kw == "INTEGER" || kw == "BOOLEAN")
1180        } else {
1181            false
1182        };
1183
1184        if !is_value_assignment {
1185            return Ok(None);
1186        }
1187
1188        // Parse value assignment
1189        let name = self.expect_identifier()?;
1190        let ty = self.parse_type()?;
1191        self.expect_symbol("::=")?;
1192        let value = self.parse_value(&ty)?;
1193
1194        Ok(Some(crate::ast::ValueAssignment { name, ty, value }))
1195    }
1196
1197    /// Try to consume a class alias assignment of the form:
1198    ///   `TypeName ::= TYPE-IDENTIFIER` or `TypeName ::= ABSTRACT-SYNTAX`
1199    ///
1200    /// These are X.681 §14.2 built-in class assignments that carry no concrete
1201    /// DER encoding.  Returning `true` causes the module parser to discard the
1202    /// definition without generating any Rust type.
1203    fn try_skip_class_alias(&mut self) -> Result<bool> {
1204        // Pattern: Identifier ::= (TYPE-IDENTIFIER | ABSTRACT-SYNTAX)
1205        // We peek: current = Identifier, next = ::=, after-next = keyword
1206        let is_ident = matches!(self.current, Token::Identifier(_));
1207        if !is_ident {
1208            return Ok(false);
1209        }
1210
1211        // Save state so we can restore if this is NOT a class alias
1212        let saved_lexer = self.lexer.clone();
1213        let saved_current = self.current.clone();
1214
1215        self.advance()?; // consume identifier
1216
1217        // Must be followed by ::=
1218        if !matches!(self.current, Token::Symbol(ref s) if s == "::=") {
1219            self.lexer = saved_lexer;
1220            self.current = saved_current;
1221            return Ok(false);
1222        }
1223        self.advance()?; // consume ::=
1224
1225        // Check if the RHS is a class-defining keyword
1226        let is_class_keyword = matches!(
1227            self.current,
1228            Token::Keyword(ref kw) if kw == "TYPE-IDENTIFIER" || kw == "ABSTRACT-SYNTAX"
1229        );
1230
1231        if !is_class_keyword {
1232            // Restore and let parse_definition handle it
1233            self.lexer = saved_lexer;
1234            self.current = saved_current;
1235            return Ok(false);
1236        }
1237
1238        // Consume the class keyword (and any trailing parts)
1239        self.advance()?;
1240        Ok(true)
1241    }
1242
1243    /// Try to consume an Information Object Set assignment (X.681 §12), returning
1244    /// `true` if one was consumed and `false` if the current token is not the start
1245    /// of an IOC assignment.
1246    ///
1247    /// Pattern: `name ClassName ::= { ... }` where `ClassName` is an identifier
1248    /// (not a built-in keyword).  This distinguishes IOC assignments from:
1249    ///  - Type definitions (`TypeName ::= ...`) where `::=` immediately follows
1250    ///    the first identifier.
1251    ///  - Classic value assignments where the second token is a built-in keyword
1252    ///    (`OBJECT`, `INTEGER`, `BOOLEAN`), handled by `try_parse_value_assignment`.
1253    ///
1254    /// IOC assignments carry no DER type information and are discarded.
1255    fn try_skip_ioc_assignment(&mut self) -> Result<bool> {
1256        // An IOC assignment begins with Identifier (name) followed by Identifier
1257        // (class name) — neither the assignment operator nor a built-in keyword.
1258        let is_ioc = if let Token::Identifier(_) = &self.current {
1259            matches!(self.peek_next_token(), Token::Identifier(_))
1260        } else {
1261            false
1262        };
1263
1264        if !is_ioc {
1265            return Ok(false);
1266        }
1267
1268        // Save state so we can backtrack if the two-identifier sequence is not
1269        // actually an IOC assignment (i.e. the mandatory '::=' is absent).
1270        let saved_lexer = self.lexer.clone();
1271        let saved_current = self.current.clone();
1272
1273        // Consume: name  ClassName  ::=  { ... }
1274        self.advance()?; // consume assignment name
1275        self.advance()?; // consume class name
1276
1277        if !matches!(self.current, Token::Symbol(ref s) if s == "::=") {
1278            // Not an IOC assignment — restore state and let the caller handle it.
1279            self.lexer = saved_lexer;
1280            self.current = saved_current;
1281            return Ok(false);
1282        }
1283        self.advance()?; // consume ::=
1284
1285        if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1286            self.skip_balanced_braces()?;
1287        } else {
1288            // Scalar value — consume single token
1289            self.advance()?;
1290        }
1291
1292        Ok(true)
1293    }
1294
1295    /// Peek at the next token without consuming it
1296    fn peek_next_token(&mut self) -> Token {
1297        // Save current state
1298        let saved_lexer = self.lexer.clone();
1299        let saved_current = self.current.clone();
1300
1301        // Consume current token and get next
1302        let _ = self.advance();
1303        let next = self.current.clone();
1304
1305        // Restore state
1306        self.lexer = saved_lexer;
1307        self.current = saved_current;
1308
1309        next
1310    }
1311
1312    /// Parse a value based on its type
1313    fn parse_value(&mut self, ty: &Type) -> Result<crate::ast::Value> {
1314        match ty {
1315            Type::ObjectIdentifier => {
1316                // Parse OID value: { ... }
1317                self.expect_symbol("{")?;
1318                let mut components = Vec::new();
1319
1320                while !matches!(self.current, Token::Symbol(ref sym) if sym == "}") {
1321                    if matches!(self.current, Token::Eof) {
1322                        return Err(ParseError {
1323                            message: "Unexpected EOF in OID value".to_string(),
1324                            line: self.lexer.line,
1325                            column: self.lexer.column,
1326                        });
1327                    }
1328
1329                    // Parse OID component: a plain number, a named reference, or the
1330                    // `name(number)` form used by RFC module OIDs (e.g. `iso(1)`).
1331                    // When `name(number)` is used, the numeric value is authoritative
1332                    // and the name is discarded.
1333                    match &self.current {
1334                        Token::Number(n) => {
1335                            components.push(crate::ast::OidComponent::Number(*n));
1336                            self.advance()?;
1337                        }
1338                        Token::Identifier(name) => {
1339                            let id = name.clone();
1340                            self.advance()?;
1341                            // Check for (number) suffix — `iso(1)`, `us(840)`, etc.
1342                            if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1343                                self.advance()?; // consume '('
1344                                if let Token::Number(n) = self.current {
1345                                    self.advance()?;
1346                                    self.expect_symbol(")")?;
1347                                    components.push(crate::ast::OidComponent::Number(n));
1348                                } else {
1349                                    self.expect_symbol(")")?;
1350                                    components.push(crate::ast::OidComponent::NamedRef(id));
1351                                }
1352                            } else {
1353                                components.push(crate::ast::OidComponent::NamedRef(id));
1354                            }
1355                        }
1356                        _ => {
1357                            return Err(ParseError {
1358                                message: format!(
1359                                    "Expected number or identifier in OID value, got {:?}",
1360                                    self.current
1361                                ),
1362                                line: self.lexer.line,
1363                                column: self.lexer.column,
1364                            });
1365                        }
1366                    }
1367                }
1368
1369                self.expect_symbol("}")?;
1370                Ok(crate::ast::Value::ObjectIdentifier(components))
1371            }
1372            Type::Integer(_, _) => {
1373                // Parse integer value
1374                if let Token::Number(n) = self.current {
1375                    self.advance()?;
1376                    Ok(crate::ast::Value::Integer(n as i64))
1377                } else {
1378                    Err(ParseError {
1379                        message: format!(
1380                            "Expected number for INTEGER value, got {:?}",
1381                            self.current
1382                        ),
1383                        line: self.lexer.line,
1384                        column: self.lexer.column,
1385                    })
1386                }
1387            }
1388            Type::Boolean => {
1389                // Parse boolean value
1390                match &self.current {
1391                    Token::Keyword(kw) if kw == "TRUE" => {
1392                        self.advance()?;
1393                        Ok(crate::ast::Value::Boolean(true))
1394                    }
1395                    Token::Keyword(kw) if kw == "FALSE" => {
1396                        self.advance()?;
1397                        Ok(crate::ast::Value::Boolean(false))
1398                    }
1399                    _ => Err(ParseError {
1400                        message: format!(
1401                            "Expected TRUE or FALSE for BOOLEAN value, got {:?}",
1402                            self.current
1403                        ),
1404                        line: self.lexer.line,
1405                        column: self.lexer.column,
1406                    }),
1407                }
1408            }
1409            _ => Err(ParseError {
1410                message: format!("Value assignments not supported for type {:?}", ty),
1411                line: self.lexer.line,
1412                column: self.lexer.column,
1413            }),
1414        }
1415    }
1416
1417    fn parse_type(&mut self) -> Result<Type> {
1418        // Check for tagged type
1419        if let Token::Symbol(ref sym) = self.current {
1420            if sym == "[" {
1421                return self.parse_tagged_type();
1422            }
1423        }
1424
1425        if let Token::Keyword(ref kw) = self.current.clone() {
1426            match kw.as_str() {
1427                "SEQUENCE" => {
1428                    self.advance()?;
1429                    // Handle SIZE constraint before OF: `SEQUENCE SIZE (1..MAX) OF ...`
1430                    if matches!(self.current, Token::Keyword(ref k) if k == "SIZE") {
1431                        self.advance()?; // consume SIZE
1432                                         // Skip the (min..max) constraint
1433                                         // Skip the (min..max) constraint
1434                        if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1435                            self.skip_balanced_parens()?;
1436                        }
1437                    }
1438                    if matches!(self.current, Token::Keyword(ref k) if k == "OF") {
1439                        self.advance()?;
1440                        let inner = self.parse_type()?;
1441                        let size_constraint = self.parse_size_constraint()?;
1442                        return Ok(Type::SequenceOf(Box::new(inner), size_constraint));
1443                    }
1444                    self.expect_symbol("{")?;
1445                    let fields = self.parse_sequence_fields()?;
1446                    self.expect_symbol("}")?;
1447                    return Ok(Type::Sequence(fields));
1448                }
1449                "SET" => {
1450                    self.advance()?;
1451                    // Handle SIZE constraint before OF: `SET SIZE (1..MAX) OF ...`
1452                    if matches!(self.current, Token::Keyword(ref k) if k == "SIZE") {
1453                        self.advance()?; // consume SIZE
1454                                         // Skip the (min..max) constraint
1455                                         // Skip the (min..max) constraint
1456                        if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1457                            self.skip_balanced_parens()?;
1458                        }
1459                    }
1460                    if matches!(self.current, Token::Keyword(ref k) if k == "OF") {
1461                        self.advance()?;
1462                        let inner = self.parse_type()?;
1463                        let size_constraint = self.parse_size_constraint()?;
1464                        return Ok(Type::SetOf(Box::new(inner), size_constraint));
1465                    }
1466                    self.expect_symbol("{")?;
1467                    let fields = self.parse_sequence_fields()?;
1468                    self.expect_symbol("}")?;
1469                    return Ok(Type::Set(fields));
1470                }
1471                "CHOICE" => {
1472                    self.advance()?;
1473                    self.expect_symbol("{")?;
1474                    let variants = self.parse_choice_variants()?;
1475                    self.expect_symbol("}")?;
1476                    return Ok(Type::Choice(variants));
1477                }
1478                "INTEGER" => {
1479                    self.advance()?;
1480
1481                    // Check for named number list: INTEGER {name(value), ...}
1482                    let named_numbers = if matches!(self.current, Token::Symbol(ref s) if s == "{")
1483                    {
1484                        self.advance()?; // consume '{'
1485                        let numbers = self.parse_named_numbers()?;
1486                        self.expect_symbol("}")?;
1487                        numbers
1488                    } else {
1489                        Vec::new()
1490                    };
1491
1492                    // Check for X.680 constraint
1493                    if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1494                        self.advance()?; // consume '('
1495                        let constraint = self.parse_subtype_constraint()?;
1496                        self.expect_symbol(")")?;
1497
1498                        // Create X.680 constrained type
1499                        return Ok(Type::Constrained {
1500                            base_type: Box::new(Type::Integer(None, named_numbers)),
1501                            constraint: Constraint {
1502                                spec: ConstraintSpec::Subtype(constraint),
1503                                exception: None,
1504                            },
1505                        });
1506                    }
1507
1508                    // Return INTEGER with optional named numbers
1509                    return Ok(Type::Integer(None, named_numbers));
1510                }
1511                "ENUMERATED" => {
1512                    self.advance()?;
1513
1514                    // ENUMERATED must have named values
1515                    self.expect_symbol("{")?;
1516                    let named_values = self.parse_named_numbers()?;
1517                    self.expect_symbol("}")?;
1518
1519                    if named_values.is_empty() {
1520                        return Err(ParseError {
1521                            message: "ENUMERATED must have at least one named value".to_string(),
1522                            line: self.lexer.line,
1523                            column: self.lexer.column,
1524                        });
1525                    }
1526
1527                    return Ok(Type::Enumerated(named_values));
1528                }
1529                "REAL" => {
1530                    self.advance()?;
1531                    return Ok(Type::Real);
1532                }
1533                "BOOLEAN" => {
1534                    self.advance()?;
1535                    return Ok(Type::Boolean);
1536                }
1537                "OCTET" => {
1538                    self.advance()?;
1539                    self.expect_keyword("STRING")?;
1540
1541                    // Check for X.680 string constraints (SIZE, FROM, PATTERN)
1542                    if let Some(constraint) = self.parse_string_constraint()? {
1543                        return Ok(Type::Constrained {
1544                            base_type: Box::new(Type::OctetString(None)),
1545                            constraint: Constraint {
1546                                spec: ConstraintSpec::Subtype(constraint),
1547                                exception: None,
1548                            },
1549                        });
1550                    }
1551
1552                    return Ok(Type::OctetString(None));
1553                }
1554                "BIT" => {
1555                    self.advance()?;
1556                    self.expect_keyword("STRING")?;
1557
1558                    // Check for named bit list: { bitName(n), ... }
1559                    let named_bits = if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1560                        self.advance()?; // consume '{'
1561                        let bits = self.parse_named_numbers()?;
1562                        self.expect_symbol("}")?;
1563                        bits
1564                    } else {
1565                        Vec::new()
1566                    };
1567
1568                    // Check for X.680 string constraints (SIZE, FROM, PATTERN)
1569                    if let Some(size_constraint) = self.parse_string_constraint()? {
1570                        if named_bits.is_empty() {
1571                            return Ok(Type::Constrained {
1572                                base_type: Box::new(Type::BitString(None)),
1573                                constraint: Constraint {
1574                                    spec: ConstraintSpec::Subtype(size_constraint),
1575                                    exception: None,
1576                                },
1577                            });
1578                        } else {
1579                            // Named bits + size constraint: use Intersection
1580                            return Ok(Type::Constrained {
1581                                base_type: Box::new(Type::BitString(None)),
1582                                constraint: Constraint {
1583                                    spec: ConstraintSpec::Subtype(SubtypeConstraint::Intersection(
1584                                        vec![
1585                                            SubtypeConstraint::NamedBitList(named_bits),
1586                                            size_constraint,
1587                                        ],
1588                                    )),
1589                                    exception: None,
1590                                },
1591                            });
1592                        }
1593                    }
1594
1595                    if !named_bits.is_empty() {
1596                        return Ok(Type::Constrained {
1597                            base_type: Box::new(Type::BitString(None)),
1598                            constraint: Constraint {
1599                                spec: ConstraintSpec::Subtype(SubtypeConstraint::NamedBitList(
1600                                    named_bits,
1601                                )),
1602                                exception: None,
1603                            },
1604                        });
1605                    }
1606
1607                    return Ok(Type::BitString(None));
1608                }
1609                "OBJECT" => {
1610                    self.advance()?;
1611                    self.expect_keyword("IDENTIFIER")?;
1612                    return Ok(Type::ObjectIdentifier);
1613                }
1614                "NULL" => {
1615                    self.advance()?;
1616                    return Ok(Type::Null);
1617                }
1618                "UTF8String" => return self.parse_string_type(Type::Utf8String(None)),
1619                "PrintableString" => return self.parse_string_type(Type::PrintableString(None)),
1620                "IA5String" => return self.parse_string_type(Type::IA5String(None)),
1621                "TeletexString" | "T61String" => {
1622                    return self.parse_string_type(Type::TeletexString(None))
1623                }
1624                "UniversalString" => return self.parse_string_type(Type::UniversalString(None)),
1625                "BMPString" => return self.parse_string_type(Type::BmpString(None)),
1626                "GeneralString" => return self.parse_string_type(Type::GeneralString(None)),
1627                "NumericString" => return self.parse_string_type(Type::NumericString(None)),
1628                "VisibleString" => return self.parse_string_type(Type::VisibleString(None)),
1629                "UTCTime" => {
1630                    self.advance()?;
1631                    return Ok(Type::UtcTime);
1632                }
1633                "GeneralizedTime" => {
1634                    self.advance()?;
1635                    return Ok(Type::GeneralizedTime);
1636                }
1637                "ANY" => {
1638                    self.advance()?;
1639                    // Check for "DEFINED BY fieldname"
1640                    if matches!(self.current, Token::Keyword(ref kw) if kw == "DEFINED") {
1641                        self.advance()?; // consume DEFINED
1642                        self.expect_keyword("BY")?;
1643                        let field_name = self.expect_identifier()?;
1644                        return Ok(Type::AnyDefinedBy(field_name));
1645                    }
1646                    return Ok(Type::Any);
1647                }
1648                "CLASS" => {
1649                    self.advance()?;
1650                    return self.parse_class_body();
1651                }
1652                // Built-in information object classes used as type aliases (X.681 §14).
1653                // `TYPE-IDENTIFIER` and `ABSTRACT-SYNTAX` are class names that appear in
1654                // type-assignment position (e.g. `MyClass ::= TYPE-IDENTIFIER`).  Treat
1655                // them as ANY since they carry no concrete DER structure.
1656                "TYPE-IDENTIFIER" | "ABSTRACT-SYNTAX" => {
1657                    self.advance()?;
1658                    return Ok(Type::Any);
1659                }
1660                _ => {}
1661            }
1662        }
1663
1664        // Type reference - accept both identifiers and keywords that represent built-in types
1665        // Per X.680, built-in types like TeletexString, BMPString, etc. are keywords but can be used as types
1666        let type_name = if let Token::Identifier(name) = &self.current {
1667            Some(name.clone())
1668        } else if let Token::Keyword(kw) = &self.current {
1669            // Allow built-in type names that are keywords but should be usable as types
1670            if is_builtin_type_keyword(kw) {
1671                Some(kw.clone())
1672            } else {
1673                None
1674            }
1675        } else {
1676            None
1677        };
1678
1679        if let Some(result) = type_name {
1680            self.advance()?;
1681
1682            // Skip optional parameterized type arguments,
1683            // e.g. `AlgorithmIdentifier{ KEM-ALGORITHM, {KEMAlgSet} }`.
1684            // The type is still resolved as a plain TypeRef; the parameter set
1685            // carries no DER encoding information.
1686            if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1687                self.skip_balanced_braces()?;
1688            }
1689
1690            // Handle `INSTANCE OF TypeName` (X.681 §14) — treat as ANY.
1691            // The `INSTANCE` identifier is already consumed as the TypeRef name.
1692            // The `OF` keyword and following class name are discarded.
1693            if result == "INSTANCE" && matches!(self.current, Token::Keyword(ref k) if k == "OF") {
1694                self.advance()?; // consume OF
1695                                 // Consume the class name (identifier)
1696                                 // Consume the class name (identifier)
1697                self.advance()?;
1698                // Skip optional parameterized arguments
1699                if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1700                    self.skip_balanced_braces()?;
1701                }
1702                return Ok(Type::Any);
1703            }
1704
1705            // Handle IOC field access notation: `ClassName.&field({params})`.
1706            // This appears in 2009-syntax modules as a field type, e.g.:
1707            //   `type  ATTRIBUTE.&id({AttrSet})`
1708            //   `parameters  ALGORITHM-TYPE.&Params({AlgorithmSet}{@algorithm}) OPTIONAL`
1709            //
1710            // For `&id` fields, the class definition always constrains the type to
1711            // `OBJECT IDENTIFIER UNIQUE`, so we resolve these to ObjectIdentifier.
1712            // All other IOC field accesses are treated as ANY (Type::Any).
1713            if matches!(self.current, Token::Symbol(ref s) if s == ".") {
1714                self.advance()?; // consume '.'
1715                                 // Consume the &field identifier and remember its name
1716                                 // Consume the &field identifier and remember its name
1717                let field_name = if let Token::Identifier(ref name) = self.current {
1718                    let n = name.clone();
1719                    self.advance()?;
1720                    n
1721                } else {
1722                    self.advance()?;
1723                    String::new()
1724                };
1725                // Skip any optional parameterized argument groups {..} or (..) after the field name
1726                loop {
1727                    if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1728                        self.skip_balanced_braces()?;
1729                    } else if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1730                        self.skip_balanced_parens()?;
1731                    } else {
1732                        break;
1733                    }
1734                }
1735                // Resolve &id to ObjectIdentifier (X.681 convention: &id fields are OIDs)
1736                if field_name == "&id" {
1737                    return Ok(Type::ObjectIdentifier);
1738                }
1739                return Ok(Type::Any);
1740            }
1741
1742            // Check for constraint on type reference (subtype definition)
1743            if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1744                // Peek ahead to determine if this is a string constraint or value constraint
1745                self.advance()?; // consume '('
1746
1747                // Check if current token (after '(') is a string constraint keyword
1748                let is_string_constraint = if let Token::Keyword(ref kw) = self.current {
1749                    matches!(kw.as_str(), "SIZE" | "FROM" | "PATTERN" | "CONTAINING")
1750                } else {
1751                    false
1752                };
1753
1754                // Parse the appropriate constraint type
1755                let constraint = if is_string_constraint {
1756                    // Parse string constraint (SIZE, FROM, PATTERN)
1757                    let mut constraints = Vec::new();
1758
1759                    while !matches!(self.current, Token::Symbol(ref s) if s == ")") {
1760                        if matches!(self.current, Token::Eof) {
1761                            break;
1762                        }
1763
1764                        if let Some(c) = self.parse_single_string_constraint()? {
1765                            constraints.push(c);
1766                        } else {
1767                            break;
1768                        }
1769                    }
1770
1771                    self.expect_symbol(")")?;
1772
1773                    match constraints.len() {
1774                        0 => {
1775                            return Err(ParseError {
1776                                message: "Expected string constraint".to_string(),
1777                                line: self.lexer.line,
1778                                column: self.lexer.column,
1779                            })
1780                        }
1781                        1 => constraints.into_iter().next().unwrap(),
1782                        _ => SubtypeConstraint::Intersection(constraints),
1783                    }
1784                } else {
1785                    // Parse value constraint (integer ranges, etc.)
1786                    let c = self.parse_subtype_constraint()?;
1787                    self.expect_symbol(")")?;
1788                    c
1789                };
1790
1791                // Create X.680 constrained type with TypeRef as base
1792                return Ok(Type::Constrained {
1793                    base_type: Box::new(Type::TypeRef(result)),
1794                    constraint: Constraint {
1795                        spec: ConstraintSpec::Subtype(constraint),
1796                        exception: None,
1797                    },
1798                });
1799            }
1800
1801            return Ok(Type::TypeRef(result));
1802        }
1803
1804        Err(ParseError {
1805            message: format!("Expected type, got {:?}", self.current),
1806            line: self.lexer.line,
1807            column: self.lexer.column,
1808        })
1809    }
1810
1811    fn parse_tagged_type(&mut self) -> Result<Type> {
1812        self.expect_symbol("[")?;
1813
1814        // Check for optional tag class keyword: APPLICATION, UNIVERSAL, PRIVATE
1815        let class = if matches!(self.current, Token::Keyword(ref kw) if kw == "APPLICATION") {
1816            self.advance()?;
1817            TagClass::Application
1818        } else if matches!(self.current, Token::Keyword(ref kw) if kw == "UNIVERSAL") {
1819            self.advance()?;
1820            TagClass::Universal
1821        } else if matches!(self.current, Token::Keyword(ref kw) if kw == "PRIVATE") {
1822            self.advance()?;
1823            TagClass::Private
1824        } else {
1825            TagClass::ContextSpecific
1826        };
1827
1828        let number = if let Token::Number(n) = self.current {
1829            self.advance()?;
1830            n
1831        } else {
1832            return Err(ParseError {
1833                message: "Expected tag number".to_string(),
1834                line: self.lexer.line,
1835                column: self.lexer.column,
1836            });
1837        };
1838
1839        self.expect_symbol("]")?;
1840
1841        // Check for EXPLICIT or IMPLICIT
1842        let tagging = if matches!(self.current, Token::Keyword(ref kw) if kw == "EXPLICIT") {
1843            self.advance()?;
1844            Tagging::Explicit
1845        } else if matches!(self.current, Token::Keyword(ref kw) if kw == "IMPLICIT") {
1846            self.advance()?;
1847            Tagging::Implicit
1848        } else {
1849            self.default_tagging.clone() // use the module-level default
1850        };
1851
1852        let inner = self.parse_type()?;
1853
1854        Ok(Type::Tagged {
1855            tag: TagInfo {
1856                class,
1857                number,
1858                tagging,
1859            },
1860            inner: Box::new(inner),
1861        })
1862    }
1863
1864    fn parse_sequence_fields(&mut self) -> Result<Vec<SequenceField>> {
1865        let mut fields = Vec::new();
1866
1867        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
1868            if matches!(self.current, Token::Eof) {
1869                break;
1870            }
1871
1872            // Skip extension markers (...)
1873            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
1874                self.advance()?;
1875                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1876                    self.advance()?;
1877                }
1878                continue;
1879            }
1880
1881            // Handle version extension addition groups: [[N: field1, field2, ... ]]
1882            // These are used in 2009-syntax modules to group optional extension fields
1883            // by version number.  The contained fields are flattened into the SEQUENCE.
1884            if matches!(self.current, Token::Symbol(ref s) if s == "[") {
1885                // Peek to see if the next token is also '[' (double bracket)
1886                let saved_lexer = self.lexer.clone();
1887                let saved_current = self.current.clone();
1888                self.advance()?; // consume first '['
1889                if matches!(self.current, Token::Symbol(ref s) if s == "[") {
1890                    self.advance()?; // consume second '['
1891                                     // Skip optional version number and colon: N:
1892                    if let Token::Number(_) = self.current {
1893                        self.advance()?; // consume N
1894                    }
1895                    if matches!(self.current, Token::Symbol(ref s) if s == ":") {
1896                        self.advance()?; // consume ':'
1897                    }
1898                    // Parse fields until ']]'
1899                    while !matches!(self.current, Token::Symbol(ref s) if s == "]" || s == "}") {
1900                        if matches!(self.current, Token::Eof) {
1901                            break;
1902                        }
1903                        // Skip extension markers inside the group
1904                        if matches!(self.current, Token::Symbol(ref s) if s == "...") {
1905                            self.advance()?;
1906                            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1907                                self.advance()?;
1908                            }
1909                            continue;
1910                        }
1911                        let fname = self.expect_identifier()?;
1912                        let fty = self.parse_type()?;
1913                        let foptional = if matches!(self.current, Token::Keyword(ref kw) if kw == "OPTIONAL")
1914                        {
1915                            self.advance()?;
1916                            true
1917                        } else {
1918                            false
1919                        };
1920                        let fdefault = if matches!(self.current, Token::Keyword(ref kw) if kw == "DEFAULT")
1921                        {
1922                            self.advance()?;
1923                            let dv = self.parse_default_value()?;
1924                            Some(dv)
1925                        } else {
1926                            None
1927                        };
1928                        fields.push(SequenceField {
1929                            name: fname,
1930                            ty: fty,
1931                            optional: foptional,
1932                            default: fdefault,
1933                        });
1934                        if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1935                            self.advance()?;
1936                        }
1937                    }
1938                    // Consume closing ']]'
1939                    if matches!(self.current, Token::Symbol(ref s) if s == "]") {
1940                        self.advance()?; // first ']'
1941                    }
1942                    if matches!(self.current, Token::Symbol(ref s) if s == "]") {
1943                        self.advance()?; // second ']'
1944                    }
1945                    if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1946                        self.advance()?;
1947                    }
1948                    continue;
1949                } else {
1950                    // Not a double bracket — restore and fall through to normal parsing
1951                    self.lexer = saved_lexer;
1952                    self.current = saved_current;
1953                }
1954            }
1955
1956            let name = self.expect_identifier()?;
1957            let ty = self.parse_type()?;
1958
1959            let optional = if matches!(self.current, Token::Keyword(ref kw) if kw == "OPTIONAL") {
1960                self.advance()?;
1961                true
1962            } else {
1963                false
1964            };
1965
1966            let default = if matches!(self.current, Token::Keyword(ref kw) if kw == "DEFAULT") {
1967                self.advance()?;
1968                // Parse the default value
1969                let default_value = self.parse_default_value()?;
1970                Some(default_value)
1971            } else {
1972                None
1973            };
1974
1975            fields.push(SequenceField {
1976                name,
1977                ty,
1978                optional,
1979                default,
1980            });
1981
1982            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1983                self.advance()?;
1984            }
1985        }
1986
1987        Ok(fields)
1988    }
1989
1990    fn parse_choice_variants(&mut self) -> Result<Vec<ChoiceVariant>> {
1991        let mut variants = Vec::new();
1992
1993        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
1994            if matches!(self.current, Token::Eof) {
1995                break;
1996            }
1997
1998            // Skip extension markers (...)
1999            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
2000                self.advance()?;
2001                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
2002                    self.advance()?;
2003                }
2004                continue;
2005            }
2006
2007            let name = self.expect_identifier()?;
2008            let ty = self.parse_type()?;
2009
2010            variants.push(ChoiceVariant { name, ty });
2011
2012            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
2013                self.advance()?;
2014            }
2015        }
2016
2017        Ok(variants)
2018    }
2019
2020    /// Parse an ASN.1 Information Object Class body (X.681 §9).
2021    ///
2022    /// Called after the `CLASS` keyword has been consumed.  Parses:
2023    ///
2024    /// ```text
2025    /// CLASS { &field [TYPE] [UNIQUE] [OPTIONAL] [DEFAULT value], ... }
2026    ///         [WITH SYNTAX { ... }]
2027    /// ```
2028    ///
2029    /// The `WITH SYNTAX` block (if present) is consumed and discarded — its
2030    /// content is arbitrary keyword syntax and has no DER representation.
2031    /// The resulting [`Type::Class`] stores only the field names and the
2032    /// `UNIQUE`/`OPTIONAL` qualifiers; actual type expressions within the
2033    /// class body are also consumed and discarded.
2034    fn parse_class_body(&mut self) -> Result<Type> {
2035        self.expect_symbol("{")?;
2036
2037        let mut fields = Vec::new();
2038
2039        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
2040            if matches!(self.current, Token::Eof) {
2041                break;
2042            }
2043
2044            // Skip extension markers
2045            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
2046                self.advance()?;
2047                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
2048                    self.advance()?;
2049                }
2050                continue;
2051            }
2052
2053            // Each field begins with &name
2054            let field_name = if let Token::Identifier(ref id) = self.current {
2055                if id.starts_with('&') {
2056                    let name = id.strip_prefix('&').unwrap_or(id).to_string();
2057                    self.advance()?;
2058                    name
2059                } else {
2060                    // Not a field reference — skip token and try to recover
2061                    self.advance()?;
2062                    continue;
2063                }
2064            } else {
2065                // Non-identifier token — skip and recover
2066                self.advance()?;
2067                continue;
2068            };
2069
2070            // Consume optional type expression and qualifiers until ',', '}', or '...'
2071            // We track brace depth to handle nested { } in DEFAULT values.
2072            let mut unique = false;
2073            let mut optional = false;
2074            let mut depth = 0usize;
2075
2076            loop {
2077                match &self.current {
2078                    Token::Symbol(ref s) if s == "}" && depth == 0 => break,
2079                    Token::Symbol(ref s) if s == "," && depth == 0 => break,
2080                    Token::Symbol(ref s) if s == "..." && depth == 0 => break,
2081                    Token::Symbol(ref s) if s == "{" => {
2082                        depth += 1;
2083                        self.advance()?;
2084                    }
2085                    Token::Symbol(ref s) if s == "}" => {
2086                        depth -= 1;
2087                        self.advance()?;
2088                    }
2089                    Token::Keyword(ref kw) if kw == "UNIQUE" && depth == 0 => {
2090                        unique = true;
2091                        self.advance()?;
2092                    }
2093                    Token::Keyword(ref kw) if kw == "OPTIONAL" && depth == 0 => {
2094                        optional = true;
2095                        self.advance()?;
2096                    }
2097                    Token::Eof => break,
2098                    _ => {
2099                        self.advance()?;
2100                    }
2101                }
2102            }
2103
2104            fields.push(ClassField {
2105                name: field_name,
2106                unique,
2107                optional,
2108            });
2109
2110            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
2111                self.advance()?;
2112            }
2113        }
2114
2115        self.expect_symbol("}")?;
2116
2117        // Consume optional WITH SYNTAX { ... } block
2118        if matches!(self.current, Token::Keyword(ref kw) if kw == "WITH") {
2119            self.advance()?; // consume WITH
2120            if matches!(self.current, Token::Keyword(ref kw) if kw == "SYNTAX") {
2121                self.advance()?; // consume SYNTAX
2122                                 // The syntax block is a balanced { ... } with arbitrary token content
2123                self.skip_balanced_braces()?;
2124            }
2125        }
2126
2127        Ok(Type::Class(fields))
2128    }
2129
2130    /// Consume a balanced `{ ... }` block, discarding all tokens inside.
2131    ///
2132    /// Handles nested braces.  Assumes the opening `{` is the current token.
2133    fn skip_balanced_braces(&mut self) -> Result<()> {
2134        self.expect_symbol("{")?;
2135        let mut depth = 1usize;
2136        while depth > 0 {
2137            match &self.current {
2138                Token::Symbol(ref s) if s == "{" => {
2139                    depth += 1;
2140                    self.advance()?;
2141                }
2142                Token::Symbol(ref s) if s == "}" => {
2143                    depth -= 1;
2144                    self.advance()?;
2145                }
2146                Token::Eof => {
2147                    return Err(ParseError {
2148                        message: "Unexpected EOF inside braced block".to_string(),
2149                        line: self.lexer.line,
2150                        column: self.lexer.column,
2151                    });
2152                }
2153                _ => {
2154                    self.advance()?;
2155                }
2156            }
2157        }
2158        Ok(())
2159    }
2160
2161    /// Consume a balanced `( ... )` block, discarding all tokens inside.
2162    ///
2163    /// Used to skip parameterized argument groups in IOC field access expressions,
2164    /// e.g. the `({AttrSet})` and `({AttrSet}{@type})` parts of
2165    /// `ATTRIBUTE.&id({AttrSet})` and `ATTRIBUTE.&Type({AttrSet}{@type})`.
2166    fn skip_balanced_parens(&mut self) -> Result<()> {
2167        self.expect_symbol("(")?;
2168        let mut depth = 1usize;
2169        while depth > 0 {
2170            match &self.current {
2171                Token::Symbol(ref s) if s == "(" => {
2172                    depth += 1;
2173                    self.advance()?;
2174                }
2175                Token::Symbol(ref s) if s == ")" => {
2176                    depth -= 1;
2177                    self.advance()?;
2178                }
2179                Token::Eof => {
2180                    return Err(ParseError {
2181                        message: "Unexpected EOF inside parenthesized block".to_string(),
2182                        line: self.lexer.line,
2183                        column: self.lexer.column,
2184                    });
2185                }
2186                _ => {
2187                    self.advance()?;
2188                }
2189            }
2190        }
2191        Ok(())
2192    }
2193
2194    /// Parse named number list: name1(value1), name2(value2), ...
2195    fn parse_named_numbers(&mut self) -> Result<Vec<NamedNumber>> {
2196        let mut numbers = Vec::new();
2197
2198        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
2199            if matches!(self.current, Token::Eof) {
2200                break;
2201            }
2202
2203            // Skip extension markers (...)
2204            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
2205                self.advance()?;
2206                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
2207                    self.advance()?;
2208                }
2209                continue;
2210            }
2211
2212            // Parse name
2213            let name = self.expect_identifier()?;
2214
2215            // Optional explicit numeric value: name(N)
2216            // If absent, auto-number (X.680 §19.5 auto-numbering for ENUMERATED).
2217            let value = if matches!(self.current, Token::Symbol(ref s) if s == "(") {
2218                self.advance()?; // consume '('
2219                let v = self.parse_integer_value()?.ok_or_else(|| ParseError {
2220                    message: "Expected number value for named number".to_string(),
2221                    line: self.lexer.line,
2222                    column: self.lexer.column,
2223                })?;
2224                self.expect_symbol(")")?;
2225                v
2226            } else {
2227                // Auto-number: next value after the last one (or 0 for first)
2228                numbers
2229                    .last()
2230                    .map(|n: &NamedNumber| n.value + 1)
2231                    .unwrap_or(0)
2232            };
2233
2234            numbers.push(NamedNumber { name, value });
2235
2236            // Optional comma
2237            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
2238                self.advance()?;
2239            }
2240        }
2241
2242        Ok(numbers)
2243    }
2244}
2245
2246/// Parse an ASN.1 module from a string
2247pub fn parse(input: &str) -> Result<Module> {
2248    let mut parser = Parser::new(input)?;
2249    parser.parse_module()
2250}
2251
2252#[cfg(test)]
2253mod tests {
2254    use super::*;
2255
2256    #[test]
2257    fn test_parse_simple_sequence() {
2258        let input = r#"
2259            TestModule DEFINITIONS ::= BEGIN
2260                SimpleSeq ::= SEQUENCE {
2261                    field1 INTEGER,
2262                    field2 OCTET STRING
2263                }
2264            END
2265        "#;
2266
2267        let module = parse(input).unwrap();
2268        assert_eq!(module.name, "TestModule");
2269        assert_eq!(module.definitions.len(), 1);
2270
2271        let def = &module.definitions[0];
2272        assert_eq!(def.name, "SimpleSeq");
2273
2274        if let Type::Sequence(fields) = &def.ty {
2275            assert_eq!(fields.len(), 2);
2276            assert_eq!(fields[0].name, "field1");
2277            assert!(matches!(fields[0].ty, Type::Integer(_, _)));
2278        } else {
2279            panic!("Expected SEQUENCE type");
2280        }
2281    }
2282
2283    #[test]
2284    fn test_parse_choice() {
2285        let input = r#"
2286            TestModule DEFINITIONS ::= BEGIN
2287                MyChoice ::= CHOICE {
2288                    option1 INTEGER,
2289                    option2 BOOLEAN
2290                }
2291            END
2292        "#;
2293
2294        let module = parse(input).unwrap();
2295        let def = &module.definitions[0];
2296
2297        if let Type::Choice(variants) = &def.ty {
2298            assert_eq!(variants.len(), 2);
2299            assert_eq!(variants[0].name, "option1");
2300        } else {
2301            panic!("Expected CHOICE type");
2302        }
2303    }
2304
2305    #[test]
2306    fn test_parse_tagged_type() {
2307        let input = r#"
2308            TestModule DEFINITIONS ::= BEGIN
2309                TaggedSeq ::= SEQUENCE {
2310                    field1 [0] EXPLICIT INTEGER,
2311                    field2 [1] IMPLICIT OCTET STRING
2312                }
2313            END
2314        "#;
2315
2316        let module = parse(input).unwrap();
2317        let def = &module.definitions[0];
2318
2319        if let Type::Sequence(fields) = &def.ty {
2320            if let Type::Tagged { tag, .. } = &fields[0].ty {
2321                assert_eq!(tag.number, 0);
2322                assert_eq!(tag.tagging, Tagging::Explicit);
2323            } else {
2324                panic!("Expected tagged type");
2325            }
2326        } else {
2327            panic!("Expected SEQUENCE type");
2328        }
2329    }
2330
2331    #[test]
2332    fn test_implicit_tags_module_default() {
2333        // In a "DEFINITIONS IMPLICIT TAGS" module, a bare [N] tag (no EXPLICIT/IMPLICIT keyword)
2334        // must default to IMPLICIT.  An explicitly-marked [N] EXPLICIT must remain EXPLICIT.
2335        let input = r#"
2336            TestModule DEFINITIONS IMPLICIT TAGS ::= BEGIN
2337                TaggedSeq ::= SEQUENCE {
2338                    field1 [0] INTEGER,
2339                    field2 [1] EXPLICIT OCTET STRING,
2340                    field3 [2] IMPLICIT BOOLEAN
2341                }
2342            END
2343        "#;
2344
2345        let module = parse(input).unwrap();
2346        assert_eq!(module.tagging_mode, Some(crate::ast::TaggingMode::Implicit));
2347        let def = &module.definitions[0];
2348        if let Type::Sequence(fields) = &def.ty {
2349            // bare [0] — should inherit IMPLICIT from module header
2350            if let Type::Tagged { tag, .. } = &fields[0].ty {
2351                assert_eq!(tag.number, 0);
2352                assert_eq!(
2353                    tag.tagging,
2354                    Tagging::Implicit,
2355                    "bare tag should be IMPLICIT in IMPLICIT TAGS module"
2356                );
2357            } else {
2358                panic!("Expected tagged type for field1");
2359            }
2360            // [1] EXPLICIT — explicit keyword overrides module default
2361            if let Type::Tagged { tag, .. } = &fields[1].ty {
2362                assert_eq!(tag.number, 1);
2363                assert_eq!(
2364                    tag.tagging,
2365                    Tagging::Explicit,
2366                    "[1] EXPLICIT should stay EXPLICIT"
2367                );
2368            } else {
2369                panic!("Expected tagged type for field2");
2370            }
2371            // [2] IMPLICIT — explicit keyword matches module default
2372            if let Type::Tagged { tag, .. } = &fields[2].ty {
2373                assert_eq!(tag.number, 2);
2374                assert_eq!(tag.tagging, Tagging::Implicit);
2375            } else {
2376                panic!("Expected tagged type for field3");
2377            }
2378        } else {
2379            panic!("Expected SEQUENCE type");
2380        }
2381    }
2382
2383    #[test]
2384    fn test_explicit_tags_module_default() {
2385        // In a "DEFINITIONS EXPLICIT TAGS" module (or no keyword — same thing), a bare [N]
2386        // tag must default to EXPLICIT.
2387        let input = r#"
2388            TestModule DEFINITIONS EXPLICIT TAGS ::= BEGIN
2389                TaggedSeq ::= SEQUENCE {
2390                    field1 [0] INTEGER
2391                }
2392            END
2393        "#;
2394
2395        let module = parse(input).unwrap();
2396        let def = &module.definitions[0];
2397        if let Type::Sequence(fields) = &def.ty {
2398            if let Type::Tagged { tag, .. } = &fields[0].ty {
2399                assert_eq!(tag.number, 0);
2400                assert_eq!(
2401                    tag.tagging,
2402                    Tagging::Explicit,
2403                    "bare tag should be EXPLICIT in EXPLICIT TAGS module"
2404                );
2405            } else {
2406                panic!("Expected tagged type");
2407            }
2408        } else {
2409            panic!("Expected SEQUENCE type");
2410        }
2411    }
2412
2413    #[test]
2414    fn test_parse_optional_field() {
2415        let input = r#"
2416            TestModule DEFINITIONS ::= BEGIN
2417                OptSeq ::= SEQUENCE {
2418                    required INTEGER,
2419                    optional BOOLEAN OPTIONAL
2420                }
2421            END
2422        "#;
2423
2424        let module = parse(input).unwrap();
2425        let def = &module.definitions[0];
2426
2427        if let Type::Sequence(fields) = &def.ty {
2428            assert!(!fields[0].optional);
2429            assert!(fields[1].optional);
2430        } else {
2431            panic!("Expected SEQUENCE type");
2432        }
2433    }
2434
2435    #[test]
2436    fn test_parse_value_constraint_range() {
2437        let input = r#"
2438            TestModule DEFINITIONS ::= BEGIN
2439                Int32 ::= INTEGER (-2147483648..2147483647)
2440            END
2441        "#;
2442
2443        let module = parse(input).unwrap();
2444        let def = &module.definitions[0];
2445
2446        assert_eq!(def.name, "Int32");
2447        // Now expects X.680 Constrained type
2448        if let Type::Constrained {
2449            base_type,
2450            constraint,
2451        } = &def.ty
2452        {
2453            assert!(matches!(base_type.as_ref(), Type::Integer(None, _)));
2454            if let ConstraintSpec::Subtype(SubtypeConstraint::ValueRange { min, max }) =
2455                &constraint.spec
2456            {
2457                assert_eq!(*min, ConstraintValue::Integer(-2147483648));
2458                assert_eq!(*max, ConstraintValue::Integer(2147483647));
2459            } else {
2460                panic!("Expected SubtypeConstraint::ValueRange");
2461            }
2462        } else {
2463            panic!("Expected Constrained type");
2464        }
2465    }
2466
2467    #[test]
2468    fn test_parse_value_constraint_single() {
2469        let input = r#"
2470            TestModule DEFINITIONS ::= BEGIN
2471                FixedValue ::= INTEGER (42)
2472            END
2473        "#;
2474
2475        let module = parse(input).unwrap();
2476        let def = &module.definitions[0];
2477
2478        // Now expects X.680 Constrained type
2479        if let Type::Constrained {
2480            base_type,
2481            constraint,
2482        } = &def.ty
2483        {
2484            assert!(matches!(base_type.as_ref(), Type::Integer(None, _)));
2485            if let ConstraintSpec::Subtype(SubtypeConstraint::SingleValue(val)) = &constraint.spec {
2486                assert_eq!(*val, ConstraintValue::Integer(42));
2487            } else {
2488                panic!("Expected SubtypeConstraint::SingleValue");
2489            }
2490        } else {
2491            panic!("Expected Constrained type");
2492        }
2493    }
2494
2495    #[test]
2496    fn test_parse_size_constraint() {
2497        // Note: SIZE constraints are parsed but currently skipped
2498        // This test verifies that OCTET STRING with SIZE parses without error
2499        let input = r#"
2500TestModule DEFINITIONS ::= BEGIN
2501    ShortString ::= OCTET STRING
2502END
2503        "#;
2504
2505        let module = parse(input).unwrap();
2506        let def = &module.definitions[0];
2507
2508        // For now, OCTET STRING without constraint should parse fine
2509        assert!(matches!(def.ty, Type::OctetString(_)));
2510    }
2511
2512    // X.680 Constraint Tests
2513
2514    #[test]
2515    fn test_parse_constraint_value_min_max() {
2516        let mut parser = Parser::new("MIN..MAX").unwrap();
2517
2518        let value1 = parser.parse_constraint_value().unwrap();
2519        assert_eq!(value1, ConstraintValue::Min);
2520
2521        parser.expect_symbol("..").unwrap();
2522
2523        let value2 = parser.parse_constraint_value().unwrap();
2524        assert_eq!(value2, ConstraintValue::Max);
2525    }
2526
2527    #[test]
2528    fn test_parse_constraint_value_integer() {
2529        let mut parser = Parser::new("42").unwrap();
2530
2531        let value = parser.parse_constraint_value().unwrap();
2532        assert_eq!(value, ConstraintValue::Integer(42));
2533    }
2534
2535    #[test]
2536    fn test_parse_constraint_value_negative() {
2537        let mut parser = Parser::new("-100").unwrap();
2538
2539        let value = parser.parse_constraint_value().unwrap();
2540        assert_eq!(value, ConstraintValue::Integer(-100));
2541    }
2542
2543    #[test]
2544    fn test_parse_constraint_value_named() {
2545        let mut parser = Parser::new("maxValue").unwrap();
2546
2547        let value = parser.parse_constraint_value().unwrap();
2548        assert_eq!(value, ConstraintValue::NamedValue("maxValue".to_string()));
2549    }
2550
2551    #[test]
2552    fn test_parse_single_value_constraint() {
2553        let mut parser = Parser::new("42").unwrap();
2554
2555        let constraint = parser.parse_single_constraint().unwrap();
2556        assert_eq!(
2557            constraint,
2558            SubtypeConstraint::SingleValue(ConstraintValue::Integer(42))
2559        );
2560    }
2561
2562    #[test]
2563    fn test_parse_value_range_constraint() {
2564        let mut parser = Parser::new("0..100").unwrap();
2565
2566        let constraint = parser.parse_single_constraint().unwrap();
2567        assert!(matches!(constraint, SubtypeConstraint::ValueRange { .. }));
2568    }
2569
2570    #[test]
2571    fn test_parse_min_max_range() {
2572        let mut parser = Parser::new("MIN..MAX").unwrap();
2573
2574        let constraint = parser.parse_single_constraint().unwrap();
2575        if let SubtypeConstraint::ValueRange { min, max } = constraint {
2576            assert_eq!(min, ConstraintValue::Min);
2577            assert_eq!(max, ConstraintValue::Max);
2578        } else {
2579            panic!("Expected ValueRange constraint");
2580        }
2581    }
2582
2583    #[test]
2584    fn test_parse_union_constraint() {
2585        let mut parser = Parser::new("1 | 2 | 3").unwrap();
2586
2587        let constraint = parser.parse_subtype_constraint().unwrap();
2588        if let SubtypeConstraint::Union(elements) = constraint {
2589            assert_eq!(elements.len(), 3);
2590        } else {
2591            panic!("Expected Union constraint");
2592        }
2593    }
2594
2595    #[test]
2596    fn test_parse_intersection_constraint() {
2597        let mut parser = Parser::new("(0..100) ^ (10 | 20 | 30)").unwrap();
2598
2599        let constraint = parser.parse_subtype_constraint().unwrap();
2600        if let SubtypeConstraint::Intersection(elements) = constraint {
2601            assert_eq!(elements.len(), 2);
2602        } else {
2603            panic!("Expected Intersection constraint");
2604        }
2605    }
2606
2607    #[test]
2608    fn test_parse_complement_constraint() {
2609        let mut parser = Parser::new("ALL EXCEPT 0").unwrap();
2610
2611        let constraint = parser.parse_single_constraint().unwrap();
2612        if let SubtypeConstraint::Complement(inner) = constraint {
2613            assert_eq!(
2614                *inner,
2615                SubtypeConstraint::SingleValue(ConstraintValue::Integer(0))
2616            );
2617        } else {
2618            panic!("Expected Complement constraint");
2619        }
2620    }
2621
2622    #[test]
2623    fn test_parse_pattern_constraint() {
2624        let input = r#"
2625TestModule DEFINITIONS ::= BEGIN
2626    EmailPattern ::= IA5String (PATTERN "[a-z]+@[a-z]+\.[a-z]+")
2627END
2628        "#;
2629
2630        let module = parse(input).unwrap();
2631        assert_eq!(module.definitions.len(), 1);
2632
2633        let def = &module.definitions[0];
2634        assert_eq!(def.name, "EmailPattern");
2635
2636        // Should be a constrained type
2637        if let Type::Constrained {
2638            base_type,
2639            constraint,
2640        } = &def.ty
2641        {
2642            // Accept either TypeRef or IA5String
2643            assert!(
2644                matches!(base_type.as_ref(), Type::IA5String(_))
2645                    || matches!(base_type.as_ref(), Type::TypeRef(s) if s == "IA5String")
2646            );
2647            if let ConstraintSpec::Subtype(SubtypeConstraint::Pattern(pattern)) = &constraint.spec {
2648                // Note: Single backslash in ASN.1 becomes single backslash in parsed string
2649                assert_eq!(pattern, "[a-z]+@[a-z]+.[a-z]+");
2650            } else {
2651                panic!("Expected Pattern constraint");
2652            }
2653        } else {
2654            panic!("Expected Constrained type");
2655        }
2656    }
2657
2658    #[test]
2659    fn test_parse_permitted_alphabet() {
2660        let input = r#"
2661TestModule DEFINITIONS ::= BEGIN
2662    MyNumericString ::= IA5String (FROM ("0".."9"))
2663END
2664        "#;
2665
2666        let module = parse(input).unwrap();
2667        let def = &module.definitions[0];
2668
2669        if let Type::Constrained { constraint, .. } = &def.ty {
2670            if let ConstraintSpec::Subtype(SubtypeConstraint::PermittedAlphabet(ranges)) =
2671                &constraint.spec
2672            {
2673                assert_eq!(ranges.len(), 1);
2674                assert_eq!(ranges[0].min, '0');
2675                assert_eq!(ranges[0].max, '9');
2676            } else {
2677                panic!("Expected PermittedAlphabet constraint");
2678            }
2679        } else {
2680            panic!("Expected Constrained type");
2681        }
2682    }
2683
2684    #[test]
2685    fn test_parse_containing_constraint() {
2686        let input = r#"
2687TestModule DEFINITIONS ::= BEGIN
2688    EncodedCert ::= OCTET STRING (CONTAINING INTEGER)
2689END
2690        "#;
2691
2692        let module = parse(input).unwrap();
2693        let def = &module.definitions[0];
2694
2695        if let Type::Constrained { constraint, .. } = &def.ty {
2696            if let ConstraintSpec::Subtype(SubtypeConstraint::ContainedSubtype(inner_type)) =
2697                &constraint.spec
2698            {
2699                assert!(matches!(inner_type.as_ref(), Type::Integer(_, _)));
2700            } else {
2701                panic!("Expected ContainedSubtype constraint");
2702            }
2703        } else {
2704            panic!("Expected Constrained type");
2705        }
2706    }
2707
2708    #[test]
2709    fn test_parse_inner_type_constraint() {
2710        let input = r#"
2711TestModule DEFINITIONS ::= BEGIN
2712    PositiveList ::= SEQUENCE OF INTEGER (1..MAX)
2713END
2714        "#;
2715
2716        let module = parse(input).unwrap();
2717        let def = &module.definitions[0];
2718
2719        // Inner type constraints on SEQUENCE OF create a SequenceOf with constrained inner type
2720        if let Type::SequenceOf(inner_type, _) = &def.ty {
2721            // The inner type should be constrained
2722            if let Type::Constrained {
2723                base_type,
2724                constraint,
2725            } = inner_type.as_ref()
2726            {
2727                assert!(matches!(base_type.as_ref(), Type::Integer(_, _)));
2728                if let ConstraintSpec::Subtype(SubtypeConstraint::ValueRange { min, max }) =
2729                    &constraint.spec
2730                {
2731                    assert_eq!(*min, ConstraintValue::Integer(1));
2732                    assert_eq!(*max, ConstraintValue::Max);
2733                } else {
2734                    panic!("Expected ValueRange constraint on inner type");
2735                }
2736            } else {
2737                panic!("Expected inner type to be Constrained");
2738            }
2739        } else {
2740            panic!("Expected SequenceOf type, got: {:?}", def.ty);
2741        }
2742    }
2743
2744    #[test]
2745    fn test_parse_complex_nested_union() {
2746        let input = r#"
2747TestModule DEFINITIONS ::= BEGIN
2748    ComplexRange ::= INTEGER (0..10 | 20..30 | 40..50)
2749END
2750        "#;
2751
2752        let module = parse(input).unwrap();
2753        let def = &module.definitions[0];
2754
2755        if let Type::Constrained { constraint, .. } = &def.ty {
2756            if let ConstraintSpec::Subtype(SubtypeConstraint::Union(elements)) = &constraint.spec {
2757                assert_eq!(elements.len(), 3);
2758                for element in elements {
2759                    assert!(matches!(element, SubtypeConstraint::ValueRange { .. }));
2760                }
2761            } else {
2762                panic!("Expected Union constraint");
2763            }
2764        } else {
2765            panic!("Expected Constrained type");
2766        }
2767    }
2768
2769    #[test]
2770    fn test_parse_nested_parentheses() {
2771        let input = r#"
2772TestModule DEFINITIONS ::= BEGIN
2773    Nested ::= INTEGER ((0..10) | (20..30))
2774END
2775        "#;
2776
2777        let module = parse(input).unwrap();
2778        let def = &module.definitions[0];
2779
2780        if let Type::Constrained { constraint, .. } = &def.ty {
2781            if let ConstraintSpec::Subtype(SubtypeConstraint::Union(elements)) = &constraint.spec {
2782                assert_eq!(elements.len(), 2);
2783            } else {
2784                panic!("Expected Union constraint");
2785            }
2786        } else {
2787            panic!("Expected Constrained type");
2788        }
2789    }
2790
2791    #[test]
2792    fn test_parse_size_constraint_on_string() {
2793        let input = r#"
2794TestModule DEFINITIONS ::= BEGIN
2795    ShortString ::= IA5String (SIZE (1..64))
2796END
2797        "#;
2798
2799        let result = parse(input);
2800        if let Err(e) = &result {
2801            println!("Parse error: {}", e);
2802        }
2803        let module = result.unwrap();
2804        let def = &module.definitions[0];
2805
2806        assert_eq!(def.name, "ShortString");
2807        // Expect Constrained type with SIZE constraint
2808        if let Type::Constrained {
2809            base_type,
2810            constraint,
2811        } = &def.ty
2812        {
2813            // The base type should be a TypeRef to IA5String now (not inline IA5String(None))
2814            // because the parser creates type references for known types
2815            println!("base_type: {:?}", base_type);
2816            // Accept either TypeRef or IA5String(None)
2817            assert!(
2818                matches!(base_type.as_ref(), Type::IA5String(None))
2819                    || matches!(base_type.as_ref(), Type::TypeRef(s) if s == "IA5String")
2820            );
2821            if let ConstraintSpec::Subtype(SubtypeConstraint::SizeConstraint(inner)) =
2822                &constraint.spec
2823            {
2824                // The inner constraint should be a ValueRange
2825                if let SubtypeConstraint::ValueRange { min, max } = inner.as_ref() {
2826                    assert_eq!(*min, ConstraintValue::Integer(1));
2827                    assert_eq!(*max, ConstraintValue::Integer(64));
2828                } else {
2829                    panic!("Expected ValueRange inside SIZE constraint");
2830                }
2831            } else {
2832                panic!("Expected SizeConstraint, got {:?}", constraint.spec);
2833            }
2834        } else {
2835            panic!("Expected Constrained type, got {:?}", def.ty);
2836        }
2837    }
2838}