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_ioc_assignment()? {
1069                // IOC assignment consumed; loop continues to the next definition
1070            } else {
1071                definitions.push(self.parse_definition()?);
1072            }
1073        }
1074
1075        if matches!(self.current, Token::Keyword(ref kw) if kw == "END") {
1076            self.advance()?;
1077        }
1078
1079        Ok(Module {
1080            name,
1081            oid,
1082            tagging_mode,
1083            imports,
1084            exports,
1085            definitions,
1086            values,
1087        })
1088    }
1089
1090    /// Parse module OID: { iso(1) identified-organization(3) ... }
1091    /// Returns a vector of OID components as strings for simplicity
1092    fn parse_module_oid(&mut self) -> Result<Vec<String>> {
1093        self.expect_symbol("{")?;
1094        let mut oid_parts = Vec::new();
1095
1096        // Parse OID components until we hit the closing brace
1097        while !matches!(self.current, Token::Symbol(ref sym) if sym == "}") {
1098            match &self.current {
1099                Token::Identifier(id) => {
1100                    oid_parts.push(id.clone());
1101                    self.advance()?;
1102
1103                    // Check for (number) after identifier
1104                    if let Token::Symbol(ref sym) = self.current {
1105                        if sym == "(" {
1106                            self.advance()?;
1107                            if let Token::Number(n) = self.current {
1108                                oid_parts.push(n.to_string());
1109                                self.advance()?;
1110                            }
1111                            self.expect_symbol(")")?;
1112                        }
1113                    }
1114                }
1115                Token::Number(n) => {
1116                    oid_parts.push(n.to_string());
1117                    self.advance()?;
1118                }
1119                Token::Eof => {
1120                    return Err(ParseError {
1121                        message: "Unexpected end of input in module OID".to_string(),
1122                        line: self.lexer.line,
1123                        column: self.lexer.column,
1124                    });
1125                }
1126                _ => {
1127                    // Skip other tokens (like whitespace, etc.)
1128                    self.advance()?;
1129                }
1130            }
1131        }
1132
1133        self.expect_symbol("}")?;
1134        Ok(oid_parts)
1135    }
1136
1137    fn parse_definition(&mut self) -> Result<Definition> {
1138        let name = self.expect_identifier()?;
1139        self.expect_symbol("::=")?;
1140        let ty = self.parse_type()?;
1141
1142        Ok(Definition { name, ty })
1143    }
1144
1145    /// Try to parse a value assignment (e.g., oidName OBJECT IDENTIFIER ::= { 1 2 3 })
1146    /// Returns None if this is not a value assignment (it's a type definition instead)
1147    fn try_parse_value_assignment(&mut self) -> Result<Option<crate::ast::ValueAssignment>> {
1148        // Look ahead to determine if this is a value assignment
1149        // Value assignment: name Type ::= value
1150        // Type definition: TypeName ::= Type
1151        // We can distinguish by checking if there's a type keyword before ::=
1152
1153        // We need at least: IDENTIFIER KEYWORD ::=
1154        // For value assignment, the second token should be OBJECT, INTEGER, BOOLEAN, etc.
1155        let is_value_assignment = if let Token::Identifier(_) = &self.current {
1156            // Peek ahead - if it's a type keyword, it's likely a value assignment
1157            matches!(self.peek_next_token(), Token::Keyword(ref kw)
1158                if kw == "OBJECT" || kw == "INTEGER" || kw == "BOOLEAN")
1159        } else {
1160            false
1161        };
1162
1163        if !is_value_assignment {
1164            return Ok(None);
1165        }
1166
1167        // Parse value assignment
1168        let name = self.expect_identifier()?;
1169        let ty = self.parse_type()?;
1170        self.expect_symbol("::=")?;
1171        let value = self.parse_value(&ty)?;
1172
1173        Ok(Some(crate::ast::ValueAssignment { name, ty, value }))
1174    }
1175
1176    /// Try to consume an Information Object Set assignment (X.681 §12), returning
1177    /// `true` if one was consumed and `false` if the current token is not the start
1178    /// of an IOC assignment.
1179    ///
1180    /// Pattern: `name ClassName ::= { ... }` where `ClassName` is an identifier
1181    /// (not a built-in keyword).  This distinguishes IOC assignments from:
1182    ///  - Type definitions (`TypeName ::= ...`) where `::=` immediately follows
1183    ///    the first identifier.
1184    ///  - Classic value assignments where the second token is a built-in keyword
1185    ///    (`OBJECT`, `INTEGER`, `BOOLEAN`), handled by `try_parse_value_assignment`.
1186    ///
1187    /// IOC assignments carry no DER type information and are discarded.
1188    fn try_skip_ioc_assignment(&mut self) -> Result<bool> {
1189        // An IOC assignment begins with Identifier (name) followed by Identifier
1190        // (class name) — neither the assignment operator nor a built-in keyword.
1191        let is_ioc = if let Token::Identifier(_) = &self.current {
1192            matches!(self.peek_next_token(), Token::Identifier(_))
1193        } else {
1194            false
1195        };
1196
1197        if !is_ioc {
1198            return Ok(false);
1199        }
1200
1201        // Consume: name  ClassName  ::=  { ... }
1202        self.advance()?; // consume assignment name
1203        self.advance()?; // consume class name
1204
1205        if !matches!(self.current, Token::Symbol(ref s) if s == "::=") {
1206            return Err(ParseError {
1207                message: format!("Expected '::=' in IOC assignment, got {:?}", self.current),
1208                line: self.lexer.line,
1209                column: self.lexer.column,
1210            });
1211        }
1212        self.advance()?; // consume ::=
1213
1214        if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1215            self.skip_balanced_braces()?;
1216        } else {
1217            // Scalar value — consume single token
1218            self.advance()?;
1219        }
1220
1221        Ok(true)
1222    }
1223
1224    /// Peek at the next token without consuming it
1225    fn peek_next_token(&mut self) -> Token {
1226        // Save current state
1227        let saved_lexer = self.lexer.clone();
1228        let saved_current = self.current.clone();
1229
1230        // Consume current token and get next
1231        let _ = self.advance();
1232        let next = self.current.clone();
1233
1234        // Restore state
1235        self.lexer = saved_lexer;
1236        self.current = saved_current;
1237
1238        next
1239    }
1240
1241    /// Parse a value based on its type
1242    fn parse_value(&mut self, ty: &Type) -> Result<crate::ast::Value> {
1243        match ty {
1244            Type::ObjectIdentifier => {
1245                // Parse OID value: { ... }
1246                self.expect_symbol("{")?;
1247                let mut components = Vec::new();
1248
1249                while !matches!(self.current, Token::Symbol(ref sym) if sym == "}") {
1250                    if matches!(self.current, Token::Eof) {
1251                        return Err(ParseError {
1252                            message: "Unexpected EOF in OID value".to_string(),
1253                            line: self.lexer.line,
1254                            column: self.lexer.column,
1255                        });
1256                    }
1257
1258                    // Parse OID component: a plain number, a named reference, or the
1259                    // `name(number)` form used by RFC module OIDs (e.g. `iso(1)`).
1260                    // When `name(number)` is used, the numeric value is authoritative
1261                    // and the name is discarded.
1262                    match &self.current {
1263                        Token::Number(n) => {
1264                            components.push(crate::ast::OidComponent::Number(*n));
1265                            self.advance()?;
1266                        }
1267                        Token::Identifier(name) => {
1268                            let id = name.clone();
1269                            self.advance()?;
1270                            // Check for (number) suffix — `iso(1)`, `us(840)`, etc.
1271                            if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1272                                self.advance()?; // consume '('
1273                                if let Token::Number(n) = self.current {
1274                                    self.advance()?;
1275                                    self.expect_symbol(")")?;
1276                                    components.push(crate::ast::OidComponent::Number(n));
1277                                } else {
1278                                    self.expect_symbol(")")?;
1279                                    components.push(crate::ast::OidComponent::NamedRef(id));
1280                                }
1281                            } else {
1282                                components.push(crate::ast::OidComponent::NamedRef(id));
1283                            }
1284                        }
1285                        _ => {
1286                            return Err(ParseError {
1287                                message: format!(
1288                                    "Expected number or identifier in OID value, got {:?}",
1289                                    self.current
1290                                ),
1291                                line: self.lexer.line,
1292                                column: self.lexer.column,
1293                            });
1294                        }
1295                    }
1296                }
1297
1298                self.expect_symbol("}")?;
1299                Ok(crate::ast::Value::ObjectIdentifier(components))
1300            }
1301            Type::Integer(_, _) => {
1302                // Parse integer value
1303                if let Token::Number(n) = self.current {
1304                    self.advance()?;
1305                    Ok(crate::ast::Value::Integer(n as i64))
1306                } else {
1307                    Err(ParseError {
1308                        message: format!(
1309                            "Expected number for INTEGER value, got {:?}",
1310                            self.current
1311                        ),
1312                        line: self.lexer.line,
1313                        column: self.lexer.column,
1314                    })
1315                }
1316            }
1317            Type::Boolean => {
1318                // Parse boolean value
1319                match &self.current {
1320                    Token::Keyword(kw) if kw == "TRUE" => {
1321                        self.advance()?;
1322                        Ok(crate::ast::Value::Boolean(true))
1323                    }
1324                    Token::Keyword(kw) if kw == "FALSE" => {
1325                        self.advance()?;
1326                        Ok(crate::ast::Value::Boolean(false))
1327                    }
1328                    _ => Err(ParseError {
1329                        message: format!(
1330                            "Expected TRUE or FALSE for BOOLEAN value, got {:?}",
1331                            self.current
1332                        ),
1333                        line: self.lexer.line,
1334                        column: self.lexer.column,
1335                    }),
1336                }
1337            }
1338            _ => Err(ParseError {
1339                message: format!("Value assignments not supported for type {:?}", ty),
1340                line: self.lexer.line,
1341                column: self.lexer.column,
1342            }),
1343        }
1344    }
1345
1346    fn parse_type(&mut self) -> Result<Type> {
1347        // Check for tagged type
1348        if let Token::Symbol(ref sym) = self.current {
1349            if sym == "[" {
1350                return self.parse_tagged_type();
1351            }
1352        }
1353
1354        if let Token::Keyword(ref kw) = self.current.clone() {
1355            match kw.as_str() {
1356                "SEQUENCE" => {
1357                    self.advance()?;
1358                    if matches!(self.current, Token::Keyword(ref k) if k == "OF") {
1359                        self.advance()?;
1360                        let inner = self.parse_type()?;
1361                        let size_constraint = self.parse_size_constraint()?;
1362                        return Ok(Type::SequenceOf(Box::new(inner), size_constraint));
1363                    }
1364                    self.expect_symbol("{")?;
1365                    let fields = self.parse_sequence_fields()?;
1366                    self.expect_symbol("}")?;
1367                    return Ok(Type::Sequence(fields));
1368                }
1369                "SET" => {
1370                    self.advance()?;
1371                    if matches!(self.current, Token::Keyword(ref k) if k == "OF") {
1372                        self.advance()?;
1373                        let inner = self.parse_type()?;
1374                        let size_constraint = self.parse_size_constraint()?;
1375                        return Ok(Type::SetOf(Box::new(inner), size_constraint));
1376                    }
1377                    self.expect_symbol("{")?;
1378                    let fields = self.parse_sequence_fields()?;
1379                    self.expect_symbol("}")?;
1380                    return Ok(Type::Set(fields));
1381                }
1382                "CHOICE" => {
1383                    self.advance()?;
1384                    self.expect_symbol("{")?;
1385                    let variants = self.parse_choice_variants()?;
1386                    self.expect_symbol("}")?;
1387                    return Ok(Type::Choice(variants));
1388                }
1389                "INTEGER" => {
1390                    self.advance()?;
1391
1392                    // Check for named number list: INTEGER {name(value), ...}
1393                    let named_numbers = if matches!(self.current, Token::Symbol(ref s) if s == "{")
1394                    {
1395                        self.advance()?; // consume '{'
1396                        let numbers = self.parse_named_numbers()?;
1397                        self.expect_symbol("}")?;
1398                        numbers
1399                    } else {
1400                        Vec::new()
1401                    };
1402
1403                    // Check for X.680 constraint
1404                    if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1405                        self.advance()?; // consume '('
1406                        let constraint = self.parse_subtype_constraint()?;
1407                        self.expect_symbol(")")?;
1408
1409                        // Create X.680 constrained type
1410                        return Ok(Type::Constrained {
1411                            base_type: Box::new(Type::Integer(None, named_numbers)),
1412                            constraint: Constraint {
1413                                spec: ConstraintSpec::Subtype(constraint),
1414                                exception: None,
1415                            },
1416                        });
1417                    }
1418
1419                    // Return INTEGER with optional named numbers
1420                    return Ok(Type::Integer(None, named_numbers));
1421                }
1422                "ENUMERATED" => {
1423                    self.advance()?;
1424
1425                    // ENUMERATED must have named values
1426                    self.expect_symbol("{")?;
1427                    let named_values = self.parse_named_numbers()?;
1428                    self.expect_symbol("}")?;
1429
1430                    if named_values.is_empty() {
1431                        return Err(ParseError {
1432                            message: "ENUMERATED must have at least one named value".to_string(),
1433                            line: self.lexer.line,
1434                            column: self.lexer.column,
1435                        });
1436                    }
1437
1438                    return Ok(Type::Enumerated(named_values));
1439                }
1440                "REAL" => {
1441                    self.advance()?;
1442                    return Ok(Type::Real);
1443                }
1444                "BOOLEAN" => {
1445                    self.advance()?;
1446                    return Ok(Type::Boolean);
1447                }
1448                "OCTET" => {
1449                    self.advance()?;
1450                    self.expect_keyword("STRING")?;
1451
1452                    // Check for X.680 string constraints (SIZE, FROM, PATTERN)
1453                    if let Some(constraint) = self.parse_string_constraint()? {
1454                        return Ok(Type::Constrained {
1455                            base_type: Box::new(Type::OctetString(None)),
1456                            constraint: Constraint {
1457                                spec: ConstraintSpec::Subtype(constraint),
1458                                exception: None,
1459                            },
1460                        });
1461                    }
1462
1463                    return Ok(Type::OctetString(None));
1464                }
1465                "BIT" => {
1466                    self.advance()?;
1467                    self.expect_keyword("STRING")?;
1468
1469                    // Check for named bit list: { bitName(n), ... }
1470                    let named_bits = if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1471                        self.advance()?; // consume '{'
1472                        let bits = self.parse_named_numbers()?;
1473                        self.expect_symbol("}")?;
1474                        bits
1475                    } else {
1476                        Vec::new()
1477                    };
1478
1479                    // Check for X.680 string constraints (SIZE, FROM, PATTERN)
1480                    if let Some(size_constraint) = self.parse_string_constraint()? {
1481                        if named_bits.is_empty() {
1482                            return Ok(Type::Constrained {
1483                                base_type: Box::new(Type::BitString(None)),
1484                                constraint: Constraint {
1485                                    spec: ConstraintSpec::Subtype(size_constraint),
1486                                    exception: None,
1487                                },
1488                            });
1489                        } else {
1490                            // Named bits + size constraint: use Intersection
1491                            return Ok(Type::Constrained {
1492                                base_type: Box::new(Type::BitString(None)),
1493                                constraint: Constraint {
1494                                    spec: ConstraintSpec::Subtype(SubtypeConstraint::Intersection(
1495                                        vec![
1496                                            SubtypeConstraint::NamedBitList(named_bits),
1497                                            size_constraint,
1498                                        ],
1499                                    )),
1500                                    exception: None,
1501                                },
1502                            });
1503                        }
1504                    }
1505
1506                    if !named_bits.is_empty() {
1507                        return Ok(Type::Constrained {
1508                            base_type: Box::new(Type::BitString(None)),
1509                            constraint: Constraint {
1510                                spec: ConstraintSpec::Subtype(SubtypeConstraint::NamedBitList(
1511                                    named_bits,
1512                                )),
1513                                exception: None,
1514                            },
1515                        });
1516                    }
1517
1518                    return Ok(Type::BitString(None));
1519                }
1520                "OBJECT" => {
1521                    self.advance()?;
1522                    self.expect_keyword("IDENTIFIER")?;
1523                    return Ok(Type::ObjectIdentifier);
1524                }
1525                "NULL" => {
1526                    self.advance()?;
1527                    return Ok(Type::Null);
1528                }
1529                "UTF8String" => return self.parse_string_type(Type::Utf8String(None)),
1530                "PrintableString" => return self.parse_string_type(Type::PrintableString(None)),
1531                "IA5String" => return self.parse_string_type(Type::IA5String(None)),
1532                "TeletexString" | "T61String" => {
1533                    return self.parse_string_type(Type::TeletexString(None))
1534                }
1535                "UniversalString" => return self.parse_string_type(Type::UniversalString(None)),
1536                "BMPString" => return self.parse_string_type(Type::BmpString(None)),
1537                "GeneralString" => return self.parse_string_type(Type::GeneralString(None)),
1538                "NumericString" => return self.parse_string_type(Type::NumericString(None)),
1539                "VisibleString" => return self.parse_string_type(Type::VisibleString(None)),
1540                "UTCTime" => {
1541                    self.advance()?;
1542                    return Ok(Type::UtcTime);
1543                }
1544                "GeneralizedTime" => {
1545                    self.advance()?;
1546                    return Ok(Type::GeneralizedTime);
1547                }
1548                "ANY" => {
1549                    self.advance()?;
1550                    // Check for "DEFINED BY fieldname"
1551                    if matches!(self.current, Token::Keyword(ref kw) if kw == "DEFINED") {
1552                        self.advance()?; // consume DEFINED
1553                        self.expect_keyword("BY")?;
1554                        let field_name = self.expect_identifier()?;
1555                        return Ok(Type::AnyDefinedBy(field_name));
1556                    }
1557                    return Ok(Type::Any);
1558                }
1559                "CLASS" => {
1560                    self.advance()?;
1561                    return self.parse_class_body();
1562                }
1563                _ => {}
1564            }
1565        }
1566
1567        // Type reference - accept both identifiers and keywords that represent built-in types
1568        // Per X.680, built-in types like TeletexString, BMPString, etc. are keywords but can be used as types
1569        let type_name = if let Token::Identifier(name) = &self.current {
1570            Some(name.clone())
1571        } else if let Token::Keyword(kw) = &self.current {
1572            // Allow built-in type names that are keywords but should be usable as types
1573            if is_builtin_type_keyword(kw) {
1574                Some(kw.clone())
1575            } else {
1576                None
1577            }
1578        } else {
1579            None
1580        };
1581
1582        if let Some(result) = type_name {
1583            self.advance()?;
1584
1585            // Skip optional parameterized type arguments,
1586            // e.g. `AlgorithmIdentifier{ KEM-ALGORITHM, {KEMAlgSet} }`.
1587            // The type is still resolved as a plain TypeRef; the parameter set
1588            // carries no DER encoding information.
1589            if matches!(self.current, Token::Symbol(ref s) if s == "{") {
1590                self.skip_balanced_braces()?;
1591            }
1592
1593            // Check for constraint on type reference (subtype definition)
1594            if matches!(self.current, Token::Symbol(ref s) if s == "(") {
1595                // Peek ahead to determine if this is a string constraint or value constraint
1596                self.advance()?; // consume '('
1597
1598                // Check if current token (after '(') is a string constraint keyword
1599                let is_string_constraint = if let Token::Keyword(ref kw) = self.current {
1600                    matches!(kw.as_str(), "SIZE" | "FROM" | "PATTERN" | "CONTAINING")
1601                } else {
1602                    false
1603                };
1604
1605                // Parse the appropriate constraint type
1606                let constraint = if is_string_constraint {
1607                    // Parse string constraint (SIZE, FROM, PATTERN)
1608                    let mut constraints = Vec::new();
1609
1610                    while !matches!(self.current, Token::Symbol(ref s) if s == ")") {
1611                        if matches!(self.current, Token::Eof) {
1612                            break;
1613                        }
1614
1615                        if let Some(c) = self.parse_single_string_constraint()? {
1616                            constraints.push(c);
1617                        } else {
1618                            break;
1619                        }
1620                    }
1621
1622                    self.expect_symbol(")")?;
1623
1624                    match constraints.len() {
1625                        0 => {
1626                            return Err(ParseError {
1627                                message: "Expected string constraint".to_string(),
1628                                line: self.lexer.line,
1629                                column: self.lexer.column,
1630                            })
1631                        }
1632                        1 => constraints.into_iter().next().unwrap(),
1633                        _ => SubtypeConstraint::Intersection(constraints),
1634                    }
1635                } else {
1636                    // Parse value constraint (integer ranges, etc.)
1637                    let c = self.parse_subtype_constraint()?;
1638                    self.expect_symbol(")")?;
1639                    c
1640                };
1641
1642                // Create X.680 constrained type with TypeRef as base
1643                return Ok(Type::Constrained {
1644                    base_type: Box::new(Type::TypeRef(result)),
1645                    constraint: Constraint {
1646                        spec: ConstraintSpec::Subtype(constraint),
1647                        exception: None,
1648                    },
1649                });
1650            }
1651
1652            return Ok(Type::TypeRef(result));
1653        }
1654
1655        Err(ParseError {
1656            message: format!("Expected type, got {:?}", self.current),
1657            line: self.lexer.line,
1658            column: self.lexer.column,
1659        })
1660    }
1661
1662    fn parse_tagged_type(&mut self) -> Result<Type> {
1663        self.expect_symbol("[")?;
1664
1665        // Check for optional tag class keyword: APPLICATION, UNIVERSAL, PRIVATE
1666        let class = if matches!(self.current, Token::Keyword(ref kw) if kw == "APPLICATION") {
1667            self.advance()?;
1668            TagClass::Application
1669        } else if matches!(self.current, Token::Keyword(ref kw) if kw == "UNIVERSAL") {
1670            self.advance()?;
1671            TagClass::Universal
1672        } else if matches!(self.current, Token::Keyword(ref kw) if kw == "PRIVATE") {
1673            self.advance()?;
1674            TagClass::Private
1675        } else {
1676            TagClass::ContextSpecific
1677        };
1678
1679        let number = if let Token::Number(n) = self.current {
1680            self.advance()?;
1681            n
1682        } else {
1683            return Err(ParseError {
1684                message: "Expected tag number".to_string(),
1685                line: self.lexer.line,
1686                column: self.lexer.column,
1687            });
1688        };
1689
1690        self.expect_symbol("]")?;
1691
1692        // Check for EXPLICIT or IMPLICIT
1693        let tagging = if matches!(self.current, Token::Keyword(ref kw) if kw == "EXPLICIT") {
1694            self.advance()?;
1695            Tagging::Explicit
1696        } else if matches!(self.current, Token::Keyword(ref kw) if kw == "IMPLICIT") {
1697            self.advance()?;
1698            Tagging::Implicit
1699        } else {
1700            self.default_tagging.clone() // use the module-level default
1701        };
1702
1703        let inner = self.parse_type()?;
1704
1705        Ok(Type::Tagged {
1706            tag: TagInfo {
1707                class,
1708                number,
1709                tagging,
1710            },
1711            inner: Box::new(inner),
1712        })
1713    }
1714
1715    fn parse_sequence_fields(&mut self) -> Result<Vec<SequenceField>> {
1716        let mut fields = Vec::new();
1717
1718        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
1719            if matches!(self.current, Token::Eof) {
1720                break;
1721            }
1722
1723            // Skip extension markers (...)
1724            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
1725                self.advance()?;
1726                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1727                    self.advance()?;
1728                }
1729                continue;
1730            }
1731
1732            let name = self.expect_identifier()?;
1733            let ty = self.parse_type()?;
1734
1735            let optional = if matches!(self.current, Token::Keyword(ref kw) if kw == "OPTIONAL") {
1736                self.advance()?;
1737                true
1738            } else {
1739                false
1740            };
1741
1742            let default = if matches!(self.current, Token::Keyword(ref kw) if kw == "DEFAULT") {
1743                self.advance()?;
1744                // Parse the default value
1745                let default_value = self.parse_default_value()?;
1746                Some(default_value)
1747            } else {
1748                None
1749            };
1750
1751            fields.push(SequenceField {
1752                name,
1753                ty,
1754                optional,
1755                default,
1756            });
1757
1758            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1759                self.advance()?;
1760            }
1761        }
1762
1763        Ok(fields)
1764    }
1765
1766    fn parse_choice_variants(&mut self) -> Result<Vec<ChoiceVariant>> {
1767        let mut variants = Vec::new();
1768
1769        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
1770            if matches!(self.current, Token::Eof) {
1771                break;
1772            }
1773
1774            // Skip extension markers (...)
1775            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
1776                self.advance()?;
1777                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1778                    self.advance()?;
1779                }
1780                continue;
1781            }
1782
1783            let name = self.expect_identifier()?;
1784            let ty = self.parse_type()?;
1785
1786            variants.push(ChoiceVariant { name, ty });
1787
1788            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1789                self.advance()?;
1790            }
1791        }
1792
1793        Ok(variants)
1794    }
1795
1796    /// Parse an ASN.1 Information Object Class body (X.681 §9).
1797    ///
1798    /// Called after the `CLASS` keyword has been consumed.  Parses:
1799    ///
1800    /// ```text
1801    /// CLASS { &field [TYPE] [UNIQUE] [OPTIONAL] [DEFAULT value], ... }
1802    ///         [WITH SYNTAX { ... }]
1803    /// ```
1804    ///
1805    /// The `WITH SYNTAX` block (if present) is consumed and discarded — its
1806    /// content is arbitrary keyword syntax and has no DER representation.
1807    /// The resulting [`Type::Class`] stores only the field names and the
1808    /// `UNIQUE`/`OPTIONAL` qualifiers; actual type expressions within the
1809    /// class body are also consumed and discarded.
1810    fn parse_class_body(&mut self) -> Result<Type> {
1811        self.expect_symbol("{")?;
1812
1813        let mut fields = Vec::new();
1814
1815        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
1816            if matches!(self.current, Token::Eof) {
1817                break;
1818            }
1819
1820            // Skip extension markers
1821            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
1822                self.advance()?;
1823                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1824                    self.advance()?;
1825                }
1826                continue;
1827            }
1828
1829            // Each field begins with &name
1830            let field_name = if let Token::Identifier(ref id) = self.current {
1831                if id.starts_with('&') {
1832                    let name = id.strip_prefix('&').unwrap_or(id).to_string();
1833                    self.advance()?;
1834                    name
1835                } else {
1836                    // Not a field reference — skip token and try to recover
1837                    self.advance()?;
1838                    continue;
1839                }
1840            } else {
1841                // Non-identifier token — skip and recover
1842                self.advance()?;
1843                continue;
1844            };
1845
1846            // Consume optional type expression and qualifiers until ',', '}', or '...'
1847            // We track brace depth to handle nested { } in DEFAULT values.
1848            let mut unique = false;
1849            let mut optional = false;
1850            let mut depth = 0usize;
1851
1852            loop {
1853                match &self.current {
1854                    Token::Symbol(ref s) if s == "}" && depth == 0 => break,
1855                    Token::Symbol(ref s) if s == "," && depth == 0 => break,
1856                    Token::Symbol(ref s) if s == "..." && depth == 0 => break,
1857                    Token::Symbol(ref s) if s == "{" => {
1858                        depth += 1;
1859                        self.advance()?;
1860                    }
1861                    Token::Symbol(ref s) if s == "}" => {
1862                        depth -= 1;
1863                        self.advance()?;
1864                    }
1865                    Token::Keyword(ref kw) if kw == "UNIQUE" && depth == 0 => {
1866                        unique = true;
1867                        self.advance()?;
1868                    }
1869                    Token::Keyword(ref kw) if kw == "OPTIONAL" && depth == 0 => {
1870                        optional = true;
1871                        self.advance()?;
1872                    }
1873                    Token::Eof => break,
1874                    _ => {
1875                        self.advance()?;
1876                    }
1877                }
1878            }
1879
1880            fields.push(ClassField {
1881                name: field_name,
1882                unique,
1883                optional,
1884            });
1885
1886            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1887                self.advance()?;
1888            }
1889        }
1890
1891        self.expect_symbol("}")?;
1892
1893        // Consume optional WITH SYNTAX { ... } block
1894        if matches!(self.current, Token::Keyword(ref kw) if kw == "WITH") {
1895            self.advance()?; // consume WITH
1896            if matches!(self.current, Token::Keyword(ref kw) if kw == "SYNTAX") {
1897                self.advance()?; // consume SYNTAX
1898                                 // The syntax block is a balanced { ... } with arbitrary token content
1899                self.skip_balanced_braces()?;
1900            }
1901        }
1902
1903        Ok(Type::Class(fields))
1904    }
1905
1906    /// Consume a balanced `{ ... }` block, discarding all tokens inside.
1907    ///
1908    /// Handles nested braces.  Assumes the opening `{` is the current token.
1909    fn skip_balanced_braces(&mut self) -> Result<()> {
1910        self.expect_symbol("{")?;
1911        let mut depth = 1usize;
1912        while depth > 0 {
1913            match &self.current {
1914                Token::Symbol(ref s) if s == "{" => {
1915                    depth += 1;
1916                    self.advance()?;
1917                }
1918                Token::Symbol(ref s) if s == "}" => {
1919                    depth -= 1;
1920                    self.advance()?;
1921                }
1922                Token::Eof => {
1923                    return Err(ParseError {
1924                        message: "Unexpected EOF inside braced block".to_string(),
1925                        line: self.lexer.line,
1926                        column: self.lexer.column,
1927                    });
1928                }
1929                _ => {
1930                    self.advance()?;
1931                }
1932            }
1933        }
1934        Ok(())
1935    }
1936
1937    /// Parse named number list: name1(value1), name2(value2), ...
1938    fn parse_named_numbers(&mut self) -> Result<Vec<NamedNumber>> {
1939        let mut numbers = Vec::new();
1940
1941        while !matches!(self.current, Token::Symbol(ref s) if s == "}") {
1942            if matches!(self.current, Token::Eof) {
1943                break;
1944            }
1945
1946            // Skip extension markers (...)
1947            if matches!(self.current, Token::Symbol(ref s) if s == "...") {
1948                self.advance()?;
1949                if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1950                    self.advance()?;
1951                }
1952                continue;
1953            }
1954
1955            // Parse name
1956            let name = self.expect_identifier()?;
1957
1958            // Expect '('
1959            self.expect_symbol("(")?;
1960
1961            // Parse value
1962            let value = self.parse_integer_value()?.ok_or_else(|| ParseError {
1963                message: "Expected number value for named number".to_string(),
1964                line: self.lexer.line,
1965                column: self.lexer.column,
1966            })?;
1967
1968            // Expect ')'
1969            self.expect_symbol(")")?;
1970
1971            numbers.push(NamedNumber { name, value });
1972
1973            // Optional comma
1974            if matches!(self.current, Token::Symbol(ref s) if s == ",") {
1975                self.advance()?;
1976            }
1977        }
1978
1979        Ok(numbers)
1980    }
1981}
1982
1983/// Parse an ASN.1 module from a string
1984pub fn parse(input: &str) -> Result<Module> {
1985    let mut parser = Parser::new(input)?;
1986    parser.parse_module()
1987}
1988
1989#[cfg(test)]
1990mod tests {
1991    use super::*;
1992
1993    #[test]
1994    fn test_parse_simple_sequence() {
1995        let input = r#"
1996            TestModule DEFINITIONS ::= BEGIN
1997                SimpleSeq ::= SEQUENCE {
1998                    field1 INTEGER,
1999                    field2 OCTET STRING
2000                }
2001            END
2002        "#;
2003
2004        let module = parse(input).unwrap();
2005        assert_eq!(module.name, "TestModule");
2006        assert_eq!(module.definitions.len(), 1);
2007
2008        let def = &module.definitions[0];
2009        assert_eq!(def.name, "SimpleSeq");
2010
2011        if let Type::Sequence(fields) = &def.ty {
2012            assert_eq!(fields.len(), 2);
2013            assert_eq!(fields[0].name, "field1");
2014            assert!(matches!(fields[0].ty, Type::Integer(_, _)));
2015        } else {
2016            panic!("Expected SEQUENCE type");
2017        }
2018    }
2019
2020    #[test]
2021    fn test_parse_choice() {
2022        let input = r#"
2023            TestModule DEFINITIONS ::= BEGIN
2024                MyChoice ::= CHOICE {
2025                    option1 INTEGER,
2026                    option2 BOOLEAN
2027                }
2028            END
2029        "#;
2030
2031        let module = parse(input).unwrap();
2032        let def = &module.definitions[0];
2033
2034        if let Type::Choice(variants) = &def.ty {
2035            assert_eq!(variants.len(), 2);
2036            assert_eq!(variants[0].name, "option1");
2037        } else {
2038            panic!("Expected CHOICE type");
2039        }
2040    }
2041
2042    #[test]
2043    fn test_parse_tagged_type() {
2044        let input = r#"
2045            TestModule DEFINITIONS ::= BEGIN
2046                TaggedSeq ::= SEQUENCE {
2047                    field1 [0] EXPLICIT INTEGER,
2048                    field2 [1] IMPLICIT OCTET STRING
2049                }
2050            END
2051        "#;
2052
2053        let module = parse(input).unwrap();
2054        let def = &module.definitions[0];
2055
2056        if let Type::Sequence(fields) = &def.ty {
2057            if let Type::Tagged { tag, .. } = &fields[0].ty {
2058                assert_eq!(tag.number, 0);
2059                assert_eq!(tag.tagging, Tagging::Explicit);
2060            } else {
2061                panic!("Expected tagged type");
2062            }
2063        } else {
2064            panic!("Expected SEQUENCE type");
2065        }
2066    }
2067
2068    #[test]
2069    fn test_implicit_tags_module_default() {
2070        // In a "DEFINITIONS IMPLICIT TAGS" module, a bare [N] tag (no EXPLICIT/IMPLICIT keyword)
2071        // must default to IMPLICIT.  An explicitly-marked [N] EXPLICIT must remain EXPLICIT.
2072        let input = r#"
2073            TestModule DEFINITIONS IMPLICIT TAGS ::= BEGIN
2074                TaggedSeq ::= SEQUENCE {
2075                    field1 [0] INTEGER,
2076                    field2 [1] EXPLICIT OCTET STRING,
2077                    field3 [2] IMPLICIT BOOLEAN
2078                }
2079            END
2080        "#;
2081
2082        let module = parse(input).unwrap();
2083        assert_eq!(module.tagging_mode, Some(crate::ast::TaggingMode::Implicit));
2084        let def = &module.definitions[0];
2085        if let Type::Sequence(fields) = &def.ty {
2086            // bare [0] — should inherit IMPLICIT from module header
2087            if let Type::Tagged { tag, .. } = &fields[0].ty {
2088                assert_eq!(tag.number, 0);
2089                assert_eq!(
2090                    tag.tagging,
2091                    Tagging::Implicit,
2092                    "bare tag should be IMPLICIT in IMPLICIT TAGS module"
2093                );
2094            } else {
2095                panic!("Expected tagged type for field1");
2096            }
2097            // [1] EXPLICIT — explicit keyword overrides module default
2098            if let Type::Tagged { tag, .. } = &fields[1].ty {
2099                assert_eq!(tag.number, 1);
2100                assert_eq!(
2101                    tag.tagging,
2102                    Tagging::Explicit,
2103                    "[1] EXPLICIT should stay EXPLICIT"
2104                );
2105            } else {
2106                panic!("Expected tagged type for field2");
2107            }
2108            // [2] IMPLICIT — explicit keyword matches module default
2109            if let Type::Tagged { tag, .. } = &fields[2].ty {
2110                assert_eq!(tag.number, 2);
2111                assert_eq!(tag.tagging, Tagging::Implicit);
2112            } else {
2113                panic!("Expected tagged type for field3");
2114            }
2115        } else {
2116            panic!("Expected SEQUENCE type");
2117        }
2118    }
2119
2120    #[test]
2121    fn test_explicit_tags_module_default() {
2122        // In a "DEFINITIONS EXPLICIT TAGS" module (or no keyword — same thing), a bare [N]
2123        // tag must default to EXPLICIT.
2124        let input = r#"
2125            TestModule DEFINITIONS EXPLICIT TAGS ::= BEGIN
2126                TaggedSeq ::= SEQUENCE {
2127                    field1 [0] INTEGER
2128                }
2129            END
2130        "#;
2131
2132        let module = parse(input).unwrap();
2133        let def = &module.definitions[0];
2134        if let Type::Sequence(fields) = &def.ty {
2135            if let Type::Tagged { tag, .. } = &fields[0].ty {
2136                assert_eq!(tag.number, 0);
2137                assert_eq!(
2138                    tag.tagging,
2139                    Tagging::Explicit,
2140                    "bare tag should be EXPLICIT in EXPLICIT TAGS module"
2141                );
2142            } else {
2143                panic!("Expected tagged type");
2144            }
2145        } else {
2146            panic!("Expected SEQUENCE type");
2147        }
2148    }
2149
2150    #[test]
2151    fn test_parse_optional_field() {
2152        let input = r#"
2153            TestModule DEFINITIONS ::= BEGIN
2154                OptSeq ::= SEQUENCE {
2155                    required INTEGER,
2156                    optional BOOLEAN OPTIONAL
2157                }
2158            END
2159        "#;
2160
2161        let module = parse(input).unwrap();
2162        let def = &module.definitions[0];
2163
2164        if let Type::Sequence(fields) = &def.ty {
2165            assert!(!fields[0].optional);
2166            assert!(fields[1].optional);
2167        } else {
2168            panic!("Expected SEQUENCE type");
2169        }
2170    }
2171
2172    #[test]
2173    fn test_parse_value_constraint_range() {
2174        let input = r#"
2175            TestModule DEFINITIONS ::= BEGIN
2176                Int32 ::= INTEGER (-2147483648..2147483647)
2177            END
2178        "#;
2179
2180        let module = parse(input).unwrap();
2181        let def = &module.definitions[0];
2182
2183        assert_eq!(def.name, "Int32");
2184        // Now expects X.680 Constrained type
2185        if let Type::Constrained {
2186            base_type,
2187            constraint,
2188        } = &def.ty
2189        {
2190            assert!(matches!(base_type.as_ref(), Type::Integer(None, _)));
2191            if let ConstraintSpec::Subtype(SubtypeConstraint::ValueRange { min, max }) =
2192                &constraint.spec
2193            {
2194                assert_eq!(*min, ConstraintValue::Integer(-2147483648));
2195                assert_eq!(*max, ConstraintValue::Integer(2147483647));
2196            } else {
2197                panic!("Expected SubtypeConstraint::ValueRange");
2198            }
2199        } else {
2200            panic!("Expected Constrained type");
2201        }
2202    }
2203
2204    #[test]
2205    fn test_parse_value_constraint_single() {
2206        let input = r#"
2207            TestModule DEFINITIONS ::= BEGIN
2208                FixedValue ::= INTEGER (42)
2209            END
2210        "#;
2211
2212        let module = parse(input).unwrap();
2213        let def = &module.definitions[0];
2214
2215        // Now expects X.680 Constrained type
2216        if let Type::Constrained {
2217            base_type,
2218            constraint,
2219        } = &def.ty
2220        {
2221            assert!(matches!(base_type.as_ref(), Type::Integer(None, _)));
2222            if let ConstraintSpec::Subtype(SubtypeConstraint::SingleValue(val)) = &constraint.spec {
2223                assert_eq!(*val, ConstraintValue::Integer(42));
2224            } else {
2225                panic!("Expected SubtypeConstraint::SingleValue");
2226            }
2227        } else {
2228            panic!("Expected Constrained type");
2229        }
2230    }
2231
2232    #[test]
2233    fn test_parse_size_constraint() {
2234        // Note: SIZE constraints are parsed but currently skipped
2235        // This test verifies that OCTET STRING with SIZE parses without error
2236        let input = r#"
2237TestModule DEFINITIONS ::= BEGIN
2238    ShortString ::= OCTET STRING
2239END
2240        "#;
2241
2242        let module = parse(input).unwrap();
2243        let def = &module.definitions[0];
2244
2245        // For now, OCTET STRING without constraint should parse fine
2246        assert!(matches!(def.ty, Type::OctetString(_)));
2247    }
2248
2249    // X.680 Constraint Tests
2250
2251    #[test]
2252    fn test_parse_constraint_value_min_max() {
2253        let mut parser = Parser::new("MIN..MAX").unwrap();
2254
2255        let value1 = parser.parse_constraint_value().unwrap();
2256        assert_eq!(value1, ConstraintValue::Min);
2257
2258        parser.expect_symbol("..").unwrap();
2259
2260        let value2 = parser.parse_constraint_value().unwrap();
2261        assert_eq!(value2, ConstraintValue::Max);
2262    }
2263
2264    #[test]
2265    fn test_parse_constraint_value_integer() {
2266        let mut parser = Parser::new("42").unwrap();
2267
2268        let value = parser.parse_constraint_value().unwrap();
2269        assert_eq!(value, ConstraintValue::Integer(42));
2270    }
2271
2272    #[test]
2273    fn test_parse_constraint_value_negative() {
2274        let mut parser = Parser::new("-100").unwrap();
2275
2276        let value = parser.parse_constraint_value().unwrap();
2277        assert_eq!(value, ConstraintValue::Integer(-100));
2278    }
2279
2280    #[test]
2281    fn test_parse_constraint_value_named() {
2282        let mut parser = Parser::new("maxValue").unwrap();
2283
2284        let value = parser.parse_constraint_value().unwrap();
2285        assert_eq!(value, ConstraintValue::NamedValue("maxValue".to_string()));
2286    }
2287
2288    #[test]
2289    fn test_parse_single_value_constraint() {
2290        let mut parser = Parser::new("42").unwrap();
2291
2292        let constraint = parser.parse_single_constraint().unwrap();
2293        assert_eq!(
2294            constraint,
2295            SubtypeConstraint::SingleValue(ConstraintValue::Integer(42))
2296        );
2297    }
2298
2299    #[test]
2300    fn test_parse_value_range_constraint() {
2301        let mut parser = Parser::new("0..100").unwrap();
2302
2303        let constraint = parser.parse_single_constraint().unwrap();
2304        assert!(matches!(constraint, SubtypeConstraint::ValueRange { .. }));
2305    }
2306
2307    #[test]
2308    fn test_parse_min_max_range() {
2309        let mut parser = Parser::new("MIN..MAX").unwrap();
2310
2311        let constraint = parser.parse_single_constraint().unwrap();
2312        if let SubtypeConstraint::ValueRange { min, max } = constraint {
2313            assert_eq!(min, ConstraintValue::Min);
2314            assert_eq!(max, ConstraintValue::Max);
2315        } else {
2316            panic!("Expected ValueRange constraint");
2317        }
2318    }
2319
2320    #[test]
2321    fn test_parse_union_constraint() {
2322        let mut parser = Parser::new("1 | 2 | 3").unwrap();
2323
2324        let constraint = parser.parse_subtype_constraint().unwrap();
2325        if let SubtypeConstraint::Union(elements) = constraint {
2326            assert_eq!(elements.len(), 3);
2327        } else {
2328            panic!("Expected Union constraint");
2329        }
2330    }
2331
2332    #[test]
2333    fn test_parse_intersection_constraint() {
2334        let mut parser = Parser::new("(0..100) ^ (10 | 20 | 30)").unwrap();
2335
2336        let constraint = parser.parse_subtype_constraint().unwrap();
2337        if let SubtypeConstraint::Intersection(elements) = constraint {
2338            assert_eq!(elements.len(), 2);
2339        } else {
2340            panic!("Expected Intersection constraint");
2341        }
2342    }
2343
2344    #[test]
2345    fn test_parse_complement_constraint() {
2346        let mut parser = Parser::new("ALL EXCEPT 0").unwrap();
2347
2348        let constraint = parser.parse_single_constraint().unwrap();
2349        if let SubtypeConstraint::Complement(inner) = constraint {
2350            assert_eq!(
2351                *inner,
2352                SubtypeConstraint::SingleValue(ConstraintValue::Integer(0))
2353            );
2354        } else {
2355            panic!("Expected Complement constraint");
2356        }
2357    }
2358
2359    #[test]
2360    fn test_parse_pattern_constraint() {
2361        let input = r#"
2362TestModule DEFINITIONS ::= BEGIN
2363    EmailPattern ::= IA5String (PATTERN "[a-z]+@[a-z]+\.[a-z]+")
2364END
2365        "#;
2366
2367        let module = parse(input).unwrap();
2368        assert_eq!(module.definitions.len(), 1);
2369
2370        let def = &module.definitions[0];
2371        assert_eq!(def.name, "EmailPattern");
2372
2373        // Should be a constrained type
2374        if let Type::Constrained {
2375            base_type,
2376            constraint,
2377        } = &def.ty
2378        {
2379            // Accept either TypeRef or IA5String
2380            assert!(
2381                matches!(base_type.as_ref(), Type::IA5String(_))
2382                    || matches!(base_type.as_ref(), Type::TypeRef(s) if s == "IA5String")
2383            );
2384            if let ConstraintSpec::Subtype(SubtypeConstraint::Pattern(pattern)) = &constraint.spec {
2385                // Note: Single backslash in ASN.1 becomes single backslash in parsed string
2386                assert_eq!(pattern, "[a-z]+@[a-z]+.[a-z]+");
2387            } else {
2388                panic!("Expected Pattern constraint");
2389            }
2390        } else {
2391            panic!("Expected Constrained type");
2392        }
2393    }
2394
2395    #[test]
2396    fn test_parse_permitted_alphabet() {
2397        let input = r#"
2398TestModule DEFINITIONS ::= BEGIN
2399    MyNumericString ::= IA5String (FROM ("0".."9"))
2400END
2401        "#;
2402
2403        let module = parse(input).unwrap();
2404        let def = &module.definitions[0];
2405
2406        if let Type::Constrained { constraint, .. } = &def.ty {
2407            if let ConstraintSpec::Subtype(SubtypeConstraint::PermittedAlphabet(ranges)) =
2408                &constraint.spec
2409            {
2410                assert_eq!(ranges.len(), 1);
2411                assert_eq!(ranges[0].min, '0');
2412                assert_eq!(ranges[0].max, '9');
2413            } else {
2414                panic!("Expected PermittedAlphabet constraint");
2415            }
2416        } else {
2417            panic!("Expected Constrained type");
2418        }
2419    }
2420
2421    #[test]
2422    fn test_parse_containing_constraint() {
2423        let input = r#"
2424TestModule DEFINITIONS ::= BEGIN
2425    EncodedCert ::= OCTET STRING (CONTAINING INTEGER)
2426END
2427        "#;
2428
2429        let module = parse(input).unwrap();
2430        let def = &module.definitions[0];
2431
2432        if let Type::Constrained { constraint, .. } = &def.ty {
2433            if let ConstraintSpec::Subtype(SubtypeConstraint::ContainedSubtype(inner_type)) =
2434                &constraint.spec
2435            {
2436                assert!(matches!(inner_type.as_ref(), Type::Integer(_, _)));
2437            } else {
2438                panic!("Expected ContainedSubtype constraint");
2439            }
2440        } else {
2441            panic!("Expected Constrained type");
2442        }
2443    }
2444
2445    #[test]
2446    fn test_parse_inner_type_constraint() {
2447        let input = r#"
2448TestModule DEFINITIONS ::= BEGIN
2449    PositiveList ::= SEQUENCE OF INTEGER (1..MAX)
2450END
2451        "#;
2452
2453        let module = parse(input).unwrap();
2454        let def = &module.definitions[0];
2455
2456        // Inner type constraints on SEQUENCE OF create a SequenceOf with constrained inner type
2457        if let Type::SequenceOf(inner_type, _) = &def.ty {
2458            // The inner type should be constrained
2459            if let Type::Constrained {
2460                base_type,
2461                constraint,
2462            } = inner_type.as_ref()
2463            {
2464                assert!(matches!(base_type.as_ref(), Type::Integer(_, _)));
2465                if let ConstraintSpec::Subtype(SubtypeConstraint::ValueRange { min, max }) =
2466                    &constraint.spec
2467                {
2468                    assert_eq!(*min, ConstraintValue::Integer(1));
2469                    assert_eq!(*max, ConstraintValue::Max);
2470                } else {
2471                    panic!("Expected ValueRange constraint on inner type");
2472                }
2473            } else {
2474                panic!("Expected inner type to be Constrained");
2475            }
2476        } else {
2477            panic!("Expected SequenceOf type, got: {:?}", def.ty);
2478        }
2479    }
2480
2481    #[test]
2482    fn test_parse_complex_nested_union() {
2483        let input = r#"
2484TestModule DEFINITIONS ::= BEGIN
2485    ComplexRange ::= INTEGER (0..10 | 20..30 | 40..50)
2486END
2487        "#;
2488
2489        let module = parse(input).unwrap();
2490        let def = &module.definitions[0];
2491
2492        if let Type::Constrained { constraint, .. } = &def.ty {
2493            if let ConstraintSpec::Subtype(SubtypeConstraint::Union(elements)) = &constraint.spec {
2494                assert_eq!(elements.len(), 3);
2495                for element in elements {
2496                    assert!(matches!(element, SubtypeConstraint::ValueRange { .. }));
2497                }
2498            } else {
2499                panic!("Expected Union constraint");
2500            }
2501        } else {
2502            panic!("Expected Constrained type");
2503        }
2504    }
2505
2506    #[test]
2507    fn test_parse_nested_parentheses() {
2508        let input = r#"
2509TestModule DEFINITIONS ::= BEGIN
2510    Nested ::= INTEGER ((0..10) | (20..30))
2511END
2512        "#;
2513
2514        let module = parse(input).unwrap();
2515        let def = &module.definitions[0];
2516
2517        if let Type::Constrained { constraint, .. } = &def.ty {
2518            if let ConstraintSpec::Subtype(SubtypeConstraint::Union(elements)) = &constraint.spec {
2519                assert_eq!(elements.len(), 2);
2520            } else {
2521                panic!("Expected Union constraint");
2522            }
2523        } else {
2524            panic!("Expected Constrained type");
2525        }
2526    }
2527
2528    #[test]
2529    fn test_parse_size_constraint_on_string() {
2530        let input = r#"
2531TestModule DEFINITIONS ::= BEGIN
2532    ShortString ::= IA5String (SIZE (1..64))
2533END
2534        "#;
2535
2536        let result = parse(input);
2537        if let Err(e) = &result {
2538            println!("Parse error: {}", e);
2539        }
2540        let module = result.unwrap();
2541        let def = &module.definitions[0];
2542
2543        assert_eq!(def.name, "ShortString");
2544        // Expect Constrained type with SIZE constraint
2545        if let Type::Constrained {
2546            base_type,
2547            constraint,
2548        } = &def.ty
2549        {
2550            // The base type should be a TypeRef to IA5String now (not inline IA5String(None))
2551            // because the parser creates type references for known types
2552            println!("base_type: {:?}", base_type);
2553            // Accept either TypeRef or IA5String(None)
2554            assert!(
2555                matches!(base_type.as_ref(), Type::IA5String(None))
2556                    || matches!(base_type.as_ref(), Type::TypeRef(s) if s == "IA5String")
2557            );
2558            if let ConstraintSpec::Subtype(SubtypeConstraint::SizeConstraint(inner)) =
2559                &constraint.spec
2560            {
2561                // The inner constraint should be a ValueRange
2562                if let SubtypeConstraint::ValueRange { min, max } = inner.as_ref() {
2563                    assert_eq!(*min, ConstraintValue::Integer(1));
2564                    assert_eq!(*max, ConstraintValue::Integer(64));
2565                } else {
2566                    panic!("Expected ValueRange inside SIZE constraint");
2567                }
2568            } else {
2569                panic!("Expected SizeConstraint, got {:?}", constraint.spec);
2570            }
2571        } else {
2572            panic!("Expected Constrained type, got {:?}", def.ty);
2573        }
2574    }
2575}